blob: 494bf4cc0a1a9ad6874d76054d21d11e5f7b550a [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * OS specific functions for UNIX/POSIX systems
Hai Shalom021b0b52019-04-10 11:17:58 -07003 * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011#include <time.h>
Jouni Malinen772e12c2014-10-07 10:29:35 -070012#include <sys/wait.h>
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#ifdef ANDROID
Yifan Honge0317902017-07-20 14:15:22 -070015#include <grp.h>
16#include <pwd.h>
Nick Kralevicha562b192013-02-28 13:55:41 -080017#include <sys/capability.h>
Elliott Hughes0f4fce12014-07-18 17:45:49 -070018#include <sys/prctl.h>
Yifan Honge0317902017-07-20 14:15:22 -070019#include <sys/types.h>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#endif /* ANDROID */
21
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080022#ifdef __MACH__
23#include <CoreServices/CoreServices.h>
24#include <mach/mach.h>
25#include <mach/mach_time.h>
26#endif /* __MACH__ */
27
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070028#include "os.h"
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070029#include "common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030
31#ifdef WPA_TRACE
32
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033#include "wpa_debug.h"
34#include "trace.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080035#include "list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070036
Dmitry Shmidt7f656022015-02-25 14:36:37 -080037static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070038
39#define ALLOC_MAGIC 0xa84ef1b2
40#define FREED_MAGIC 0x67fd487a
41
42struct os_alloc_trace {
43 unsigned int magic;
44 struct dl_list list;
45 size_t len;
46 WPA_TRACE_INFO
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080047} __attribute__((aligned(16)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048
49#endif /* WPA_TRACE */
50
51
52void os_sleep(os_time_t sec, os_time_t usec)
53{
Hai Shalomc3565922019-10-28 11:58:20 -070054#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
55 const struct timespec req = { sec, usec * 1000 };
56
57 nanosleep(&req, NULL);
58#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059 if (sec)
60 sleep(sec);
61 if (usec)
62 usleep(usec);
Hai Shalomc3565922019-10-28 11:58:20 -070063#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064}
65
66
67int os_get_time(struct os_time *t)
68{
69 int res;
70 struct timeval tv;
71 res = gettimeofday(&tv, NULL);
72 t->sec = tv.tv_sec;
73 t->usec = tv.tv_usec;
74 return res;
75}
76
77
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -080078int os_get_reltime(struct os_reltime *t)
79{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080080#ifndef __MACH__
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -080081#if defined(CLOCK_BOOTTIME)
82 static clockid_t clock_id = CLOCK_BOOTTIME;
83#elif defined(CLOCK_MONOTONIC)
84 static clockid_t clock_id = CLOCK_MONOTONIC;
85#else
86 static clockid_t clock_id = CLOCK_REALTIME;
87#endif
88 struct timespec ts;
89 int res;
90
Paul Stewart092955c2017-02-06 09:13:09 -080091 if (TEST_FAIL())
92 return -1;
93
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -080094 while (1) {
95 res = clock_gettime(clock_id, &ts);
96 if (res == 0) {
97 t->sec = ts.tv_sec;
98 t->usec = ts.tv_nsec / 1000;
99 return 0;
100 }
101 switch (clock_id) {
102#ifdef CLOCK_BOOTTIME
103 case CLOCK_BOOTTIME:
104 clock_id = CLOCK_MONOTONIC;
105 break;
106#endif
107#ifdef CLOCK_MONOTONIC
108 case CLOCK_MONOTONIC:
109 clock_id = CLOCK_REALTIME;
110 break;
111#endif
112 case CLOCK_REALTIME:
113 return -1;
114 }
115 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800116#else /* __MACH__ */
117 uint64_t abstime, nano;
118 static mach_timebase_info_data_t info = { 0, 0 };
119
120 if (!info.denom) {
121 if (mach_timebase_info(&info) != KERN_SUCCESS)
122 return -1;
123 }
124
125 abstime = mach_absolute_time();
126 nano = (abstime * info.numer) / info.denom;
127
128 t->sec = nano / NSEC_PER_SEC;
129 t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
130
131 return 0;
132#endif /* __MACH__ */
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -0800133}
134
135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136int os_mktime(int year, int month, int day, int hour, int min, int sec,
137 os_time_t *t)
138{
139 struct tm tm, *tm1;
140 time_t t_local, t1, t2;
141 os_time_t tz_offset;
142
143 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
144 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
145 sec > 60)
146 return -1;
147
148 memset(&tm, 0, sizeof(tm));
149 tm.tm_year = year - 1900;
150 tm.tm_mon = month - 1;
151 tm.tm_mday = day;
152 tm.tm_hour = hour;
153 tm.tm_min = min;
154 tm.tm_sec = sec;
155
156 t_local = mktime(&tm);
157
158 /* figure out offset to UTC */
159 tm1 = localtime(&t_local);
160 if (tm1) {
161 t1 = mktime(tm1);
162 tm1 = gmtime(&t_local);
163 if (tm1) {
164 t2 = mktime(tm1);
165 tz_offset = t2 - t1;
166 } else
167 tz_offset = 0;
168 } else
169 tz_offset = 0;
170
171 *t = (os_time_t) t_local - tz_offset;
172 return 0;
173}
174
175
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800176int os_gmtime(os_time_t t, struct os_tm *tm)
177{
178 struct tm *tm2;
179 time_t t2 = t;
180
181 tm2 = gmtime(&t2);
182 if (tm2 == NULL)
183 return -1;
184 tm->sec = tm2->tm_sec;
185 tm->min = tm2->tm_min;
186 tm->hour = tm2->tm_hour;
187 tm->day = tm2->tm_mday;
188 tm->month = tm2->tm_mon + 1;
189 tm->year = tm2->tm_year + 1900;
190 return 0;
191}
192
193
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700194#ifdef __APPLE__
195#include <fcntl.h>
196static int os_daemon(int nochdir, int noclose)
197{
198 int devnull;
199
200 if (chdir("/") < 0)
201 return -1;
202
203 devnull = open("/dev/null", O_RDWR);
204 if (devnull < 0)
205 return -1;
206
207 if (dup2(devnull, STDIN_FILENO) < 0) {
208 close(devnull);
209 return -1;
210 }
211
212 if (dup2(devnull, STDOUT_FILENO) < 0) {
213 close(devnull);
214 return -1;
215 }
216
217 if (dup2(devnull, STDERR_FILENO) < 0) {
218 close(devnull);
219 return -1;
220 }
221
222 return 0;
223}
224#else /* __APPLE__ */
225#define os_daemon daemon
226#endif /* __APPLE__ */
227
228
229int os_daemonize(const char *pid_file)
230{
231#if defined(__uClinux__) || defined(__sun__)
232 return -1;
233#else /* defined(__uClinux__) || defined(__sun__) */
234 if (os_daemon(0, 0)) {
235 perror("daemon");
236 return -1;
237 }
238
239 if (pid_file) {
240 FILE *f = fopen(pid_file, "w");
241 if (f) {
242 fprintf(f, "%u\n", getpid());
243 fclose(f);
244 }
245 }
246
247 return -0;
248#endif /* defined(__uClinux__) || defined(__sun__) */
249}
250
251
252void os_daemonize_terminate(const char *pid_file)
253{
254 if (pid_file)
255 unlink(pid_file);
256}
257
258
259int os_get_random(unsigned char *buf, size_t len)
260{
Hai Shalom74f70d42019-02-11 14:42:39 -0800261#ifdef TEST_FUZZ
262 size_t i;
263
264 for (i = 0; i < len; i++)
265 buf[i] = i & 0xff;
266 return 0;
267#else /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700268 FILE *f;
269 size_t rc;
270
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800271 if (TEST_FAIL())
272 return -1;
273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700274 f = fopen("/dev/urandom", "rb");
275 if (f == NULL) {
276 printf("Could not open /dev/urandom.\n");
277 return -1;
278 }
279
280 rc = fread(buf, 1, len, f);
281 fclose(f);
282
283 return rc != len ? -1 : 0;
Hai Shalom74f70d42019-02-11 14:42:39 -0800284#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700285}
286
287
288unsigned long os_random(void)
289{
290 return random();
291}
292
293
294char * os_rel2abs_path(const char *rel_path)
295{
296 char *buf = NULL, *cwd, *ret;
297 size_t len = 128, cwd_len, rel_len, ret_len;
298 int last_errno;
299
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700300 if (!rel_path)
301 return NULL;
302
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303 if (rel_path[0] == '/')
304 return os_strdup(rel_path);
305
306 for (;;) {
307 buf = os_malloc(len);
308 if (buf == NULL)
309 return NULL;
310 cwd = getcwd(buf, len);
311 if (cwd == NULL) {
312 last_errno = errno;
313 os_free(buf);
314 if (last_errno != ERANGE)
315 return NULL;
316 len *= 2;
317 if (len > 2000)
318 return NULL;
319 } else {
320 buf[len - 1] = '\0';
321 break;
322 }
323 }
324
325 cwd_len = os_strlen(cwd);
326 rel_len = os_strlen(rel_path);
327 ret_len = cwd_len + 1 + rel_len + 1;
328 ret = os_malloc(ret_len);
329 if (ret) {
330 os_memcpy(ret, cwd, cwd_len);
331 ret[cwd_len] = '/';
332 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
333 ret[ret_len - 1] = '\0';
334 }
335 os_free(buf);
336 return ret;
337}
338
339
340int os_program_init(void)
341{
342#ifdef ANDROID
Yifan Honge0317902017-07-20 14:15:22 -0700343 struct __user_cap_header_struct header;
344 struct __user_cap_data_struct cap;
345 struct group *grp = getgrnam("wifi");
346 gid_t gid_wifi = grp ? grp->gr_gid : 0;
347 struct passwd *pwd = getpwnam("wifi");
348 uid_t uid_wifi = pwd ? pwd->pw_uid : 0;
349
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700350 /*
351 * We ignore errors here since errors are normal if we
352 * are already running as non-root.
353 */
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800354#ifdef ANDROID_SETGROUPS_OVERRIDE
355 gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
Yifan Honge0317902017-07-20 14:15:22 -0700356
357 if (!gid_wifi || !uid_wifi) return -1;
Pavel Grafov7b28f302018-02-14 14:29:41 +0000358 setgroups(ARRAY_SIZE(groups), groups);
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800359#else /* ANDROID_SETGROUPS_OVERRIDE */
Pavel Grafov4d8552e2018-02-06 11:28:29 +0000360 gid_t groups[4];
361 int group_idx = 0;
Yifan Honge0317902017-07-20 14:15:22 -0700362
363 if (!gid_wifi || !uid_wifi) return -1;
Pavel Grafov4d8552e2018-02-06 11:28:29 +0000364 groups[group_idx] = gid_wifi;
Yifan Honge0317902017-07-20 14:15:22 -0700365
366 grp = getgrnam("inet");
Pavel Grafov4d8552e2018-02-06 11:28:29 +0000367 groups[++group_idx] = grp ? grp->gr_gid : 0;
368 if (!groups[group_idx]) return -1;
Yifan Honge0317902017-07-20 14:15:22 -0700369
370 grp = getgrnam("keystore");
Pavel Grafov4d8552e2018-02-06 11:28:29 +0000371 groups[++group_idx] = grp ? grp->gr_gid : 0;
372 if (!groups[group_idx]) return -1;
373
374 grp = getgrnam("log");
375 groups[++group_idx] = grp ? grp->gr_gid : 0;
376 if (!groups[group_idx]) group_idx--;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700377
Pavel Grafov4d8552e2018-02-06 11:28:29 +0000378 setgroups(group_idx + 1, groups);
Pavel Grafov7b28f302018-02-14 14:29:41 +0000379#endif /* ANDROID_SETGROUPS_OVERRIDE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380
381 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
382
Yifan Honge0317902017-07-20 14:15:22 -0700383 setgid(gid_wifi);
384 setuid(uid_wifi);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700385
386 header.version = _LINUX_CAPABILITY_VERSION;
387 header.pid = 0;
388 cap.effective = cap.permitted =
389 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
390 cap.inheritable = 0;
391 capset(&header, &cap);
392#endif /* ANDROID */
393
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700394 return 0;
395}
396
397
398void os_program_deinit(void)
399{
400#ifdef WPA_TRACE
401 struct os_alloc_trace *a;
402 unsigned long total = 0;
403 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
404 total += a->len;
405 if (a->magic != ALLOC_MAGIC) {
406 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
407 "len %lu",
408 a, a->magic, (unsigned long) a->len);
409 continue;
410 }
411 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
412 a, (unsigned long) a->len);
413 wpa_trace_dump("memleak", a);
414 }
415 if (total)
416 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
417 (unsigned long) total);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800418 wpa_trace_deinit();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419#endif /* WPA_TRACE */
420}
421
422
423int os_setenv(const char *name, const char *value, int overwrite)
424{
425 return setenv(name, value, overwrite);
426}
427
428
429int os_unsetenv(const char *name)
430{
431#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
432 defined(__OpenBSD__)
433 unsetenv(name);
434 return 0;
435#else
436 return unsetenv(name);
437#endif
438}
439
440
441char * os_readfile(const char *name, size_t *len)
442{
443 FILE *f;
444 char *buf;
445 long pos;
446
447 f = fopen(name, "rb");
448 if (f == NULL)
449 return NULL;
450
451 if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
452 fclose(f);
453 return NULL;
454 }
455 *len = pos;
456 if (fseek(f, 0, SEEK_SET) < 0) {
457 fclose(f);
458 return NULL;
459 }
460
461 buf = os_malloc(*len);
462 if (buf == NULL) {
463 fclose(f);
464 return NULL;
465 }
466
467 if (fread(buf, 1, *len, f) != *len) {
468 fclose(f);
469 os_free(buf);
470 return NULL;
471 }
472
473 fclose(f);
474
475 return buf;
476}
477
478
Dmitry Shmidtd5dc24e2014-03-12 14:22:04 -0700479int os_file_exists(const char *fname)
480{
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -0700481 return access(fname, F_OK) == 0;
Dmitry Shmidtd5dc24e2014-03-12 14:22:04 -0700482}
483
484
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800485int os_fdatasync(FILE *stream)
Mitchell Wills447c7ff2015-08-24 17:24:30 -0700486{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800487 if (!fflush(stream)) {
488#ifdef __linux__
489 return fdatasync(fileno(stream));
490#else /* !__linux__ */
491#ifdef F_FULLFSYNC
492 /* OS X does not implement fdatasync(). */
493 return fcntl(fileno(stream), F_FULLFSYNC);
494#else /* F_FULLFSYNC */
Mitchell Wills447c7ff2015-08-24 17:24:30 -0700495 return fsync(fileno(stream));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800496#endif /* F_FULLFSYNC */
497#endif /* __linux__ */
498 }
499
Mitchell Wills447c7ff2015-08-24 17:24:30 -0700500 return -1;
501}
502
503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700504#ifndef WPA_TRACE
505void * os_zalloc(size_t size)
506{
507 return calloc(1, size);
508}
509#endif /* WPA_TRACE */
510
511
512size_t os_strlcpy(char *dest, const char *src, size_t siz)
513{
514 const char *s = src;
515 size_t left = siz;
516
517 if (left) {
518 /* Copy string up to the maximum size of the dest buffer */
519 while (--left != 0) {
520 if ((*dest++ = *s++) == '\0')
521 break;
522 }
523 }
524
525 if (left == 0) {
526 /* Not enough room for the string; force NUL-termination */
527 if (siz != 0)
528 *dest = '\0';
529 while (*s++)
530 ; /* determine total src string length */
531 }
532
533 return s - src - 1;
534}
535
536
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700537int os_memcmp_const(const void *a, const void *b, size_t len)
538{
539 const u8 *aa = a;
540 const u8 *bb = b;
541 size_t i;
542 u8 res;
543
544 for (res = 0, i = 0; i < len; i++)
545 res |= aa[i] ^ bb[i];
546
547 return res;
548}
549
550
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700551void * os_memdup(const void *src, size_t len)
552{
553 void *r = os_malloc(len);
554
Hai Shalom021b0b52019-04-10 11:17:58 -0700555 if (r && src)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700556 os_memcpy(r, src, len);
557 return r;
558}
559
560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700561#ifdef WPA_TRACE
562
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800563#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
564char wpa_trace_fail_func[256] = { 0 };
565unsigned int wpa_trace_fail_after;
566
567static int testing_fail_alloc(void)
568{
569 const char *func[WPA_TRACE_LEN];
570 size_t i, res, len;
571 char *pos, *next;
572 int match;
573
574 if (!wpa_trace_fail_after)
575 return 0;
576
577 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
578 i = 0;
579 if (i < res && os_strcmp(func[i], __func__) == 0)
580 i++;
581 if (i < res && os_strcmp(func[i], "os_malloc") == 0)
582 i++;
583 if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
584 i++;
585 if (i < res && os_strcmp(func[i], "os_calloc") == 0)
586 i++;
587 if (i < res && os_strcmp(func[i], "os_realloc") == 0)
588 i++;
589 if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
590 i++;
591 if (i < res && os_strcmp(func[i], "os_strdup") == 0)
592 i++;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700593 if (i < res && os_strcmp(func[i], "os_memdup") == 0)
594 i++;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800595
596 pos = wpa_trace_fail_func;
597
598 match = 0;
599 while (i < res) {
600 int allow_skip = 1;
601 int maybe = 0;
602
603 if (*pos == '=') {
604 allow_skip = 0;
605 pos++;
606 } else if (*pos == '?') {
607 maybe = 1;
608 pos++;
609 }
610 next = os_strchr(pos, ';');
611 if (next)
612 len = next - pos;
613 else
614 len = os_strlen(pos);
615 if (os_memcmp(pos, func[i], len) != 0) {
616 if (maybe && next) {
617 pos = next + 1;
618 continue;
619 }
620 if (allow_skip) {
621 i++;
622 continue;
623 }
624 return 0;
625 }
626 if (!next) {
627 match = 1;
628 break;
629 }
630 pos = next + 1;
631 i++;
632 }
633 if (!match)
634 return 0;
635
636 wpa_trace_fail_after--;
637 if (wpa_trace_fail_after == 0) {
638 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
639 wpa_trace_fail_func);
640 for (i = 0; i < res; i++)
641 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
642 (int) i, func[i]);
643 return 1;
644 }
645
646 return 0;
647}
648
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800649
650char wpa_trace_test_fail_func[256] = { 0 };
651unsigned int wpa_trace_test_fail_after;
652
653int testing_test_fail(void)
654{
655 const char *func[WPA_TRACE_LEN];
656 size_t i, res, len;
657 char *pos, *next;
658 int match;
659
660 if (!wpa_trace_test_fail_after)
661 return 0;
662
663 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
664 i = 0;
665 if (i < res && os_strcmp(func[i], __func__) == 0)
666 i++;
667
668 pos = wpa_trace_test_fail_func;
669
670 match = 0;
671 while (i < res) {
672 int allow_skip = 1;
673 int maybe = 0;
674
675 if (*pos == '=') {
676 allow_skip = 0;
677 pos++;
678 } else if (*pos == '?') {
679 maybe = 1;
680 pos++;
681 }
682 next = os_strchr(pos, ';');
683 if (next)
684 len = next - pos;
685 else
686 len = os_strlen(pos);
687 if (os_memcmp(pos, func[i], len) != 0) {
688 if (maybe && next) {
689 pos = next + 1;
690 continue;
691 }
692 if (allow_skip) {
693 i++;
694 continue;
695 }
696 return 0;
697 }
698 if (!next) {
699 match = 1;
700 break;
701 }
702 pos = next + 1;
703 i++;
704 }
705 if (!match)
706 return 0;
707
708 wpa_trace_test_fail_after--;
709 if (wpa_trace_test_fail_after == 0) {
710 wpa_printf(MSG_INFO, "TESTING: fail at %s",
711 wpa_trace_test_fail_func);
712 for (i = 0; i < res; i++)
713 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
714 (int) i, func[i]);
715 return 1;
716 }
717
718 return 0;
719}
720
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800721#else
722
723static inline int testing_fail_alloc(void)
724{
725 return 0;
726}
727#endif
728
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700729void * os_malloc(size_t size)
730{
731 struct os_alloc_trace *a;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800732
733 if (testing_fail_alloc())
734 return NULL;
735
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736 a = malloc(sizeof(*a) + size);
737 if (a == NULL)
738 return NULL;
739 a->magic = ALLOC_MAGIC;
740 dl_list_add(&alloc_list, &a->list);
741 a->len = size;
742 wpa_trace_record(a);
743 return a + 1;
744}
745
746
747void * os_realloc(void *ptr, size_t size)
748{
749 struct os_alloc_trace *a;
750 size_t copy_len;
751 void *n;
752
753 if (ptr == NULL)
754 return os_malloc(size);
755
756 a = (struct os_alloc_trace *) ptr - 1;
757 if (a->magic != ALLOC_MAGIC) {
758 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
759 a, a->magic,
760 a->magic == FREED_MAGIC ? " (already freed)" : "");
761 wpa_trace_show("Invalid os_realloc() call");
762 abort();
763 }
764 n = os_malloc(size);
765 if (n == NULL)
766 return NULL;
767 copy_len = a->len;
768 if (copy_len > size)
769 copy_len = size;
770 os_memcpy(n, a + 1, copy_len);
771 os_free(ptr);
772 return n;
773}
774
775
776void os_free(void *ptr)
777{
778 struct os_alloc_trace *a;
779
780 if (ptr == NULL)
781 return;
782 a = (struct os_alloc_trace *) ptr - 1;
783 if (a->magic != ALLOC_MAGIC) {
784 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
785 a, a->magic,
786 a->magic == FREED_MAGIC ? " (already freed)" : "");
787 wpa_trace_show("Invalid os_free() call");
788 abort();
789 }
790 dl_list_del(&a->list);
791 a->magic = FREED_MAGIC;
792
793 wpa_trace_check_ref(ptr);
794 free(a);
795}
796
797
798void * os_zalloc(size_t size)
799{
800 void *ptr = os_malloc(size);
801 if (ptr)
802 os_memset(ptr, 0, size);
803 return ptr;
804}
805
806
807char * os_strdup(const char *s)
808{
809 size_t len;
810 char *d;
811 len = os_strlen(s);
812 d = os_malloc(len + 1);
813 if (d == NULL)
814 return NULL;
815 os_memcpy(d, s, len);
816 d[len] = '\0';
817 return d;
818}
819
820#endif /* WPA_TRACE */
Jouni Malinen772e12c2014-10-07 10:29:35 -0700821
822
823int os_exec(const char *program, const char *arg, int wait_completion)
824{
825 pid_t pid;
826 int pid_status;
827
828 pid = fork();
829 if (pid < 0) {
830 perror("fork");
831 return -1;
832 }
833
834 if (pid == 0) {
835 /* run the external command in the child process */
836 const int MAX_ARG = 30;
837 char *_program, *_arg, *pos;
838 char *argv[MAX_ARG + 1];
839 int i;
840
841 _program = os_strdup(program);
842 _arg = os_strdup(arg);
843
844 argv[0] = _program;
845
846 i = 1;
847 pos = _arg;
848 while (i < MAX_ARG && pos && *pos) {
849 while (*pos == ' ')
850 pos++;
851 if (*pos == '\0')
852 break;
853 argv[i++] = pos;
854 pos = os_strchr(pos, ' ');
855 if (pos)
856 *pos++ = '\0';
857 }
858 argv[i] = NULL;
859
860 execv(program, argv);
861 perror("execv");
862 os_free(_program);
863 os_free(_arg);
864 exit(0);
865 return -1;
866 }
867
868 if (wait_completion) {
869 /* wait for the child process to complete in the parent */
870 waitpid(pid, &pid_status, 0);
871 }
872
873 return 0;
874}