xref: /freebsd/contrib/wpa/src/utils/os_unix.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
139beb93cSSam Leffler /*
2e28a4053SRui Paulo  * OS specific functions for UNIX/POSIX systems
34bc52338SCy Schubert  * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
11f05cddf9SRui Paulo #include <time.h>
125b9c547cSRui Paulo #include <sys/wait.h>
13f05cddf9SRui Paulo 
14f05cddf9SRui Paulo #ifdef ANDROID
155b9c547cSRui Paulo #include <sys/capability.h>
165b9c547cSRui Paulo #include <sys/prctl.h>
17f05cddf9SRui Paulo #include <private/android_filesystem_config.h>
18f05cddf9SRui Paulo #endif /* ANDROID */
19f05cddf9SRui Paulo 
20325151a3SRui Paulo #ifdef __MACH__
21325151a3SRui Paulo #include <CoreServices/CoreServices.h>
22325151a3SRui Paulo #include <mach/mach.h>
23325151a3SRui Paulo #include <mach/mach_time.h>
24325151a3SRui Paulo #endif /* __MACH__ */
25325151a3SRui Paulo 
2639beb93cSSam Leffler #include "os.h"
275b9c547cSRui Paulo #include "common.h"
2839beb93cSSam Leffler 
29e28a4053SRui Paulo #ifdef WPA_TRACE
30e28a4053SRui Paulo 
31e28a4053SRui Paulo #include "wpa_debug.h"
32e28a4053SRui Paulo #include "trace.h"
33f05cddf9SRui Paulo #include "list.h"
34e28a4053SRui Paulo 
355b9c547cSRui Paulo static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
36e28a4053SRui Paulo 
37e28a4053SRui Paulo #define ALLOC_MAGIC 0xa84ef1b2
38e28a4053SRui Paulo #define FREED_MAGIC 0x67fd487a
39e28a4053SRui Paulo 
40e28a4053SRui Paulo struct os_alloc_trace {
41e28a4053SRui Paulo 	unsigned int magic;
42c1d255d3SCy Schubert 	struct dl_list list __attribute__((aligned(16)));
43e28a4053SRui Paulo 	size_t len;
44e28a4053SRui Paulo 	WPA_TRACE_INFO
45325151a3SRui Paulo } __attribute__((aligned(16)));
46e28a4053SRui Paulo 
47e28a4053SRui Paulo #endif /* WPA_TRACE */
48e28a4053SRui Paulo 
49e28a4053SRui Paulo 
os_sleep(os_time_t sec,os_time_t usec)5039beb93cSSam Leffler void os_sleep(os_time_t sec, os_time_t usec)
5139beb93cSSam Leffler {
52c1d255d3SCy Schubert #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
53c1d255d3SCy Schubert 	const struct timespec req = { sec, usec * 1000 };
54c1d255d3SCy Schubert 
55c1d255d3SCy Schubert 	nanosleep(&req, NULL);
56c1d255d3SCy Schubert #else
5739beb93cSSam Leffler 	if (sec)
5839beb93cSSam Leffler 		sleep(sec);
5939beb93cSSam Leffler 	if (usec)
6039beb93cSSam Leffler 		usleep(usec);
61c1d255d3SCy Schubert #endif
6239beb93cSSam Leffler }
6339beb93cSSam Leffler 
6439beb93cSSam Leffler 
os_get_time(struct os_time * t)6539beb93cSSam Leffler int os_get_time(struct os_time *t)
6639beb93cSSam Leffler {
6739beb93cSSam Leffler 	int res;
6839beb93cSSam Leffler 	struct timeval tv;
6939beb93cSSam Leffler 	res = gettimeofday(&tv, NULL);
7039beb93cSSam Leffler 	t->sec = tv.tv_sec;
7139beb93cSSam Leffler 	t->usec = tv.tv_usec;
7239beb93cSSam Leffler 	return res;
7339beb93cSSam Leffler }
7439beb93cSSam Leffler 
os_get_reltime(struct os_reltime * t)755b9c547cSRui Paulo int os_get_reltime(struct os_reltime *t)
765b9c547cSRui Paulo {
77325151a3SRui Paulo #ifndef __MACH__
785b9c547cSRui Paulo #if defined(CLOCK_BOOTTIME)
795b9c547cSRui Paulo 	static clockid_t clock_id = CLOCK_BOOTTIME;
805b9c547cSRui Paulo #elif defined(CLOCK_MONOTONIC)
815b9c547cSRui Paulo 	static clockid_t clock_id = CLOCK_MONOTONIC;
825b9c547cSRui Paulo #else
835b9c547cSRui Paulo 	static clockid_t clock_id = CLOCK_REALTIME;
845b9c547cSRui Paulo #endif
855b9c547cSRui Paulo 	struct timespec ts;
865b9c547cSRui Paulo 	int res;
875b9c547cSRui Paulo 
8885732ac8SCy Schubert 	if (TEST_FAIL())
8985732ac8SCy Schubert 		return -1;
9085732ac8SCy Schubert 
915b9c547cSRui Paulo 	while (1) {
925b9c547cSRui Paulo 		res = clock_gettime(clock_id, &ts);
935b9c547cSRui Paulo 		if (res == 0) {
945b9c547cSRui Paulo 			t->sec = ts.tv_sec;
955b9c547cSRui Paulo 			t->usec = ts.tv_nsec / 1000;
965b9c547cSRui Paulo 			return 0;
975b9c547cSRui Paulo 		}
985b9c547cSRui Paulo 		switch (clock_id) {
99cab9ccf3SWarner Losh #ifdef CLOCK_BOOTTIME
1005b9c547cSRui Paulo 		case CLOCK_BOOTTIME:
1015b9c547cSRui Paulo 			clock_id = CLOCK_MONOTONIC;
1025b9c547cSRui Paulo 			break;
1035b9c547cSRui Paulo #endif
104cab9ccf3SWarner Losh #ifdef CLOCK_MONOTONIC
105676041c4SWarner Losh /*
106676041c4SWarner Losh  * FreeBSD has both BOOTTIME and MONOTONIC defined to the same value, since they
107676041c4SWarner Losh  * mean the same thing. FreeBSD 14.1 and ealier don't, so need this case.
108676041c4SWarner Losh  */
109676041c4SWarner Losh #if !(defined(CLOCK_BOOTTIME) && CLOCK_BOOTTIME == CLOCK_MONOTONIC)
1105b9c547cSRui Paulo 		case CLOCK_MONOTONIC:
1115b9c547cSRui Paulo 			clock_id = CLOCK_REALTIME;
1125b9c547cSRui Paulo 			break;
1135b9c547cSRui Paulo #endif
114676041c4SWarner Losh #endif
1155b9c547cSRui Paulo 		case CLOCK_REALTIME:
1165b9c547cSRui Paulo 			return -1;
1175b9c547cSRui Paulo 		}
1185b9c547cSRui Paulo 	}
119325151a3SRui Paulo #else /* __MACH__ */
120325151a3SRui Paulo 	uint64_t abstime, nano;
121325151a3SRui Paulo 	static mach_timebase_info_data_t info = { 0, 0 };
122325151a3SRui Paulo 
123325151a3SRui Paulo 	if (!info.denom) {
124325151a3SRui Paulo 		if (mach_timebase_info(&info) != KERN_SUCCESS)
125325151a3SRui Paulo 			return -1;
126325151a3SRui Paulo 	}
127325151a3SRui Paulo 
128325151a3SRui Paulo 	abstime = mach_absolute_time();
129325151a3SRui Paulo 	nano = (abstime * info.numer) / info.denom;
130325151a3SRui Paulo 
131325151a3SRui Paulo 	t->sec = nano / NSEC_PER_SEC;
132325151a3SRui Paulo 	t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
133325151a3SRui Paulo 
134325151a3SRui Paulo 	return 0;
135325151a3SRui Paulo #endif /* __MACH__ */
1365b9c547cSRui Paulo }
1375b9c547cSRui Paulo 
1385b9c547cSRui Paulo 
os_mktime(int year,int month,int day,int hour,int min,int sec,os_time_t * t)13939beb93cSSam Leffler int os_mktime(int year, int month, int day, int hour, int min, int sec,
14039beb93cSSam Leffler 	      os_time_t *t)
14139beb93cSSam Leffler {
14239beb93cSSam Leffler 	struct tm tm, *tm1;
14339beb93cSSam Leffler 	time_t t_local, t1, t2;
14439beb93cSSam Leffler 	os_time_t tz_offset;
14539beb93cSSam Leffler 
14639beb93cSSam Leffler 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
14739beb93cSSam Leffler 	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
14839beb93cSSam Leffler 	    sec > 60)
14939beb93cSSam Leffler 		return -1;
15039beb93cSSam Leffler 
15139beb93cSSam Leffler 	memset(&tm, 0, sizeof(tm));
15239beb93cSSam Leffler 	tm.tm_year = year - 1900;
15339beb93cSSam Leffler 	tm.tm_mon = month - 1;
15439beb93cSSam Leffler 	tm.tm_mday = day;
15539beb93cSSam Leffler 	tm.tm_hour = hour;
15639beb93cSSam Leffler 	tm.tm_min = min;
15739beb93cSSam Leffler 	tm.tm_sec = sec;
15839beb93cSSam Leffler 
15939beb93cSSam Leffler 	t_local = mktime(&tm);
16039beb93cSSam Leffler 
16139beb93cSSam Leffler 	/* figure out offset to UTC */
16239beb93cSSam Leffler 	tm1 = localtime(&t_local);
16339beb93cSSam Leffler 	if (tm1) {
16439beb93cSSam Leffler 		t1 = mktime(tm1);
16539beb93cSSam Leffler 		tm1 = gmtime(&t_local);
16639beb93cSSam Leffler 		if (tm1) {
16739beb93cSSam Leffler 			t2 = mktime(tm1);
16839beb93cSSam Leffler 			tz_offset = t2 - t1;
16939beb93cSSam Leffler 		} else
17039beb93cSSam Leffler 			tz_offset = 0;
17139beb93cSSam Leffler 	} else
17239beb93cSSam Leffler 		tz_offset = 0;
17339beb93cSSam Leffler 
17439beb93cSSam Leffler 	*t = (os_time_t) t_local - tz_offset;
17539beb93cSSam Leffler 	return 0;
17639beb93cSSam Leffler }
17739beb93cSSam Leffler 
17839beb93cSSam Leffler 
os_gmtime(os_time_t t,struct os_tm * tm)179f05cddf9SRui Paulo int os_gmtime(os_time_t t, struct os_tm *tm)
180f05cddf9SRui Paulo {
181f05cddf9SRui Paulo 	struct tm *tm2;
182f05cddf9SRui Paulo 	time_t t2 = t;
183f05cddf9SRui Paulo 
184f05cddf9SRui Paulo 	tm2 = gmtime(&t2);
185f05cddf9SRui Paulo 	if (tm2 == NULL)
186f05cddf9SRui Paulo 		return -1;
187f05cddf9SRui Paulo 	tm->sec = tm2->tm_sec;
188f05cddf9SRui Paulo 	tm->min = tm2->tm_min;
189f05cddf9SRui Paulo 	tm->hour = tm2->tm_hour;
190f05cddf9SRui Paulo 	tm->day = tm2->tm_mday;
191f05cddf9SRui Paulo 	tm->month = tm2->tm_mon + 1;
192f05cddf9SRui Paulo 	tm->year = tm2->tm_year + 1900;
193f05cddf9SRui Paulo 	return 0;
194f05cddf9SRui Paulo }
195f05cddf9SRui Paulo 
196f05cddf9SRui Paulo 
19739beb93cSSam Leffler #ifdef __APPLE__
19839beb93cSSam Leffler #include <fcntl.h>
os_daemon(int nochdir,int noclose)19939beb93cSSam Leffler static int os_daemon(int nochdir, int noclose)
20039beb93cSSam Leffler {
20139beb93cSSam Leffler 	int devnull;
20239beb93cSSam Leffler 
20339beb93cSSam Leffler 	if (chdir("/") < 0)
20439beb93cSSam Leffler 		return -1;
20539beb93cSSam Leffler 
20639beb93cSSam Leffler 	devnull = open("/dev/null", O_RDWR);
20739beb93cSSam Leffler 	if (devnull < 0)
20839beb93cSSam Leffler 		return -1;
20939beb93cSSam Leffler 
21039beb93cSSam Leffler 	if (dup2(devnull, STDIN_FILENO) < 0) {
21139beb93cSSam Leffler 		close(devnull);
21239beb93cSSam Leffler 		return -1;
21339beb93cSSam Leffler 	}
21439beb93cSSam Leffler 
21539beb93cSSam Leffler 	if (dup2(devnull, STDOUT_FILENO) < 0) {
21639beb93cSSam Leffler 		close(devnull);
21739beb93cSSam Leffler 		return -1;
21839beb93cSSam Leffler 	}
21939beb93cSSam Leffler 
22039beb93cSSam Leffler 	if (dup2(devnull, STDERR_FILENO) < 0) {
22139beb93cSSam Leffler 		close(devnull);
22239beb93cSSam Leffler 		return -1;
22339beb93cSSam Leffler 	}
22439beb93cSSam Leffler 
22539beb93cSSam Leffler 	return 0;
22639beb93cSSam Leffler }
22739beb93cSSam Leffler #else /* __APPLE__ */
22839beb93cSSam Leffler #define os_daemon daemon
22939beb93cSSam Leffler #endif /* __APPLE__ */
23039beb93cSSam Leffler 
23139beb93cSSam Leffler 
os_daemonize(const char * pid_file)23239beb93cSSam Leffler int os_daemonize(const char *pid_file)
23339beb93cSSam Leffler {
234f05cddf9SRui Paulo #if defined(__uClinux__) || defined(__sun__)
23539beb93cSSam Leffler 	return -1;
236f05cddf9SRui Paulo #else /* defined(__uClinux__) || defined(__sun__) */
23739beb93cSSam Leffler 	if (os_daemon(0, 0)) {
23839beb93cSSam Leffler 		perror("daemon");
23939beb93cSSam Leffler 		return -1;
24039beb93cSSam Leffler 	}
24139beb93cSSam Leffler 
24239beb93cSSam Leffler 	if (pid_file) {
24339beb93cSSam Leffler 		FILE *f = fopen(pid_file, "w");
24439beb93cSSam Leffler 		if (f) {
24539beb93cSSam Leffler 			fprintf(f, "%u\n", getpid());
24639beb93cSSam Leffler 			fclose(f);
24739beb93cSSam Leffler 		}
24839beb93cSSam Leffler 	}
24939beb93cSSam Leffler 
25039beb93cSSam Leffler 	return -0;
251f05cddf9SRui Paulo #endif /* defined(__uClinux__) || defined(__sun__) */
25239beb93cSSam Leffler }
25339beb93cSSam Leffler 
25439beb93cSSam Leffler 
os_daemonize_terminate(const char * pid_file)25539beb93cSSam Leffler void os_daemonize_terminate(const char *pid_file)
25639beb93cSSam Leffler {
25739beb93cSSam Leffler 	if (pid_file)
25839beb93cSSam Leffler 		unlink(pid_file);
25939beb93cSSam Leffler }
26039beb93cSSam Leffler 
26139beb93cSSam Leffler 
os_get_random(unsigned char * buf,size_t len)26239beb93cSSam Leffler int os_get_random(unsigned char *buf, size_t len)
26339beb93cSSam Leffler {
2644bc52338SCy Schubert #ifdef TEST_FUZZ
2654bc52338SCy Schubert 	size_t i;
2664bc52338SCy Schubert 
2674bc52338SCy Schubert 	for (i = 0; i < len; i++)
2684bc52338SCy Schubert 		buf[i] = i & 0xff;
2694bc52338SCy Schubert 	return 0;
2704bc52338SCy Schubert #else /* TEST_FUZZ */
27139beb93cSSam Leffler 	FILE *f;
27239beb93cSSam Leffler 	size_t rc;
27339beb93cSSam Leffler 
274325151a3SRui Paulo 	if (TEST_FAIL())
275325151a3SRui Paulo 		return -1;
276325151a3SRui Paulo 
27739beb93cSSam Leffler 	f = fopen("/dev/urandom", "rb");
27839beb93cSSam Leffler 	if (f == NULL) {
27939beb93cSSam Leffler 		printf("Could not open /dev/urandom.\n");
28039beb93cSSam Leffler 		return -1;
28139beb93cSSam Leffler 	}
28239beb93cSSam Leffler 
28339beb93cSSam Leffler 	rc = fread(buf, 1, len, f);
28439beb93cSSam Leffler 	fclose(f);
28539beb93cSSam Leffler 
28639beb93cSSam Leffler 	return rc != len ? -1 : 0;
2874bc52338SCy Schubert #endif /* TEST_FUZZ */
28839beb93cSSam Leffler }
28939beb93cSSam Leffler 
29039beb93cSSam Leffler 
os_random(void)29139beb93cSSam Leffler unsigned long os_random(void)
29239beb93cSSam Leffler {
29339beb93cSSam Leffler 	return random();
29439beb93cSSam Leffler }
29539beb93cSSam Leffler 
29639beb93cSSam Leffler 
os_rel2abs_path(const char * rel_path)29739beb93cSSam Leffler char * os_rel2abs_path(const char *rel_path)
29839beb93cSSam Leffler {
29939beb93cSSam Leffler 	char *buf = NULL, *cwd, *ret;
30039beb93cSSam Leffler 	size_t len = 128, cwd_len, rel_len, ret_len;
30139beb93cSSam Leffler 	int last_errno;
30239beb93cSSam Leffler 
3035b9c547cSRui Paulo 	if (!rel_path)
3045b9c547cSRui Paulo 		return NULL;
3055b9c547cSRui Paulo 
30639beb93cSSam Leffler 	if (rel_path[0] == '/')
307e28a4053SRui Paulo 		return os_strdup(rel_path);
30839beb93cSSam Leffler 
30939beb93cSSam Leffler 	for (;;) {
310e28a4053SRui Paulo 		buf = os_malloc(len);
31139beb93cSSam Leffler 		if (buf == NULL)
31239beb93cSSam Leffler 			return NULL;
31339beb93cSSam Leffler 		cwd = getcwd(buf, len);
31439beb93cSSam Leffler 		if (cwd == NULL) {
31539beb93cSSam Leffler 			last_errno = errno;
316e28a4053SRui Paulo 			os_free(buf);
31739beb93cSSam Leffler 			if (last_errno != ERANGE)
31839beb93cSSam Leffler 				return NULL;
31939beb93cSSam Leffler 			len *= 2;
32039beb93cSSam Leffler 			if (len > 2000)
32139beb93cSSam Leffler 				return NULL;
32239beb93cSSam Leffler 		} else {
32339beb93cSSam Leffler 			buf[len - 1] = '\0';
32439beb93cSSam Leffler 			break;
32539beb93cSSam Leffler 		}
32639beb93cSSam Leffler 	}
32739beb93cSSam Leffler 
328e28a4053SRui Paulo 	cwd_len = os_strlen(cwd);
329e28a4053SRui Paulo 	rel_len = os_strlen(rel_path);
33039beb93cSSam Leffler 	ret_len = cwd_len + 1 + rel_len + 1;
331e28a4053SRui Paulo 	ret = os_malloc(ret_len);
33239beb93cSSam Leffler 	if (ret) {
333e28a4053SRui Paulo 		os_memcpy(ret, cwd, cwd_len);
33439beb93cSSam Leffler 		ret[cwd_len] = '/';
335e28a4053SRui Paulo 		os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
33639beb93cSSam Leffler 		ret[ret_len - 1] = '\0';
33739beb93cSSam Leffler 	}
338e28a4053SRui Paulo 	os_free(buf);
33939beb93cSSam Leffler 	return ret;
34039beb93cSSam Leffler }
34139beb93cSSam Leffler 
34239beb93cSSam Leffler 
os_program_init(void)34339beb93cSSam Leffler int os_program_init(void)
34439beb93cSSam Leffler {
345c1d255d3SCy Schubert 	unsigned int seed;
346c1d255d3SCy Schubert 
347f05cddf9SRui Paulo #ifdef ANDROID
348f05cddf9SRui Paulo 	/*
349f05cddf9SRui Paulo 	 * We ignore errors here since errors are normal if we
350f05cddf9SRui Paulo 	 * are already running as non-root.
351f05cddf9SRui Paulo 	 */
3525b9c547cSRui Paulo #ifdef ANDROID_SETGROUPS_OVERRIDE
3535b9c547cSRui Paulo 	gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
3545b9c547cSRui Paulo #else /* ANDROID_SETGROUPS_OVERRIDE */
355f05cddf9SRui Paulo 	gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
3565b9c547cSRui Paulo #endif /* ANDROID_SETGROUPS_OVERRIDE */
357f05cddf9SRui Paulo 	struct __user_cap_header_struct header;
358f05cddf9SRui Paulo 	struct __user_cap_data_struct cap;
359f05cddf9SRui Paulo 
3605b9c547cSRui Paulo 	setgroups(ARRAY_SIZE(groups), groups);
361f05cddf9SRui Paulo 
362f05cddf9SRui Paulo 	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
363f05cddf9SRui Paulo 
364f05cddf9SRui Paulo 	setgid(AID_WIFI);
365f05cddf9SRui Paulo 	setuid(AID_WIFI);
366f05cddf9SRui Paulo 
367f05cddf9SRui Paulo 	header.version = _LINUX_CAPABILITY_VERSION;
368f05cddf9SRui Paulo 	header.pid = 0;
369f05cddf9SRui Paulo 	cap.effective = cap.permitted =
370f05cddf9SRui Paulo 		(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
371f05cddf9SRui Paulo 	cap.inheritable = 0;
372f05cddf9SRui Paulo 	capset(&header, &cap);
373f05cddf9SRui Paulo #endif /* ANDROID */
374f05cddf9SRui Paulo 
375c1d255d3SCy Schubert 	if (os_get_random((unsigned char *) &seed, sizeof(seed)) == 0)
376c1d255d3SCy Schubert 		srandom(seed);
377c1d255d3SCy Schubert 
37839beb93cSSam Leffler 	return 0;
37939beb93cSSam Leffler }
38039beb93cSSam Leffler 
38139beb93cSSam Leffler 
os_program_deinit(void)38239beb93cSSam Leffler void os_program_deinit(void)
38339beb93cSSam Leffler {
384e28a4053SRui Paulo #ifdef WPA_TRACE
385e28a4053SRui Paulo 	struct os_alloc_trace *a;
386e28a4053SRui Paulo 	unsigned long total = 0;
387e28a4053SRui Paulo 	dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
388e28a4053SRui Paulo 		total += a->len;
389e28a4053SRui Paulo 		if (a->magic != ALLOC_MAGIC) {
390e28a4053SRui Paulo 			wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
391e28a4053SRui Paulo 				   "len %lu",
392e28a4053SRui Paulo 				   a, a->magic, (unsigned long) a->len);
393e28a4053SRui Paulo 			continue;
394e28a4053SRui Paulo 		}
395e28a4053SRui Paulo 		wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
396e28a4053SRui Paulo 			   a, (unsigned long) a->len);
397e28a4053SRui Paulo 		wpa_trace_dump("memleak", a);
398e28a4053SRui Paulo 	}
399e28a4053SRui Paulo 	if (total)
400e28a4053SRui Paulo 		wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
401e28a4053SRui Paulo 			   (unsigned long) total);
402780fb4a2SCy Schubert 	wpa_trace_deinit();
403e28a4053SRui Paulo #endif /* WPA_TRACE */
40439beb93cSSam Leffler }
40539beb93cSSam Leffler 
40639beb93cSSam Leffler 
os_setenv(const char * name,const char * value,int overwrite)40739beb93cSSam Leffler int os_setenv(const char *name, const char *value, int overwrite)
40839beb93cSSam Leffler {
40939beb93cSSam Leffler 	return setenv(name, value, overwrite);
41039beb93cSSam Leffler }
41139beb93cSSam Leffler 
41239beb93cSSam Leffler 
os_unsetenv(const char * name)41339beb93cSSam Leffler int os_unsetenv(const char *name)
41439beb93cSSam Leffler {
4153157ba21SRui Paulo #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
4163157ba21SRui Paulo     defined(__OpenBSD__)
41739beb93cSSam Leffler 	unsetenv(name);
41839beb93cSSam Leffler 	return 0;
41939beb93cSSam Leffler #else
42039beb93cSSam Leffler 	return unsetenv(name);
42139beb93cSSam Leffler #endif
42239beb93cSSam Leffler }
42339beb93cSSam Leffler 
42439beb93cSSam Leffler 
os_readfile(const char * name,size_t * len)42539beb93cSSam Leffler char * os_readfile(const char *name, size_t *len)
42639beb93cSSam Leffler {
42739beb93cSSam Leffler 	FILE *f;
42839beb93cSSam Leffler 	char *buf;
429f05cddf9SRui Paulo 	long pos;
43039beb93cSSam Leffler 
43139beb93cSSam Leffler 	f = fopen(name, "rb");
43239beb93cSSam Leffler 	if (f == NULL)
43339beb93cSSam Leffler 		return NULL;
43439beb93cSSam Leffler 
435f05cddf9SRui Paulo 	if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
436f05cddf9SRui Paulo 		fclose(f);
437f05cddf9SRui Paulo 		return NULL;
438f05cddf9SRui Paulo 	}
439f05cddf9SRui Paulo 	*len = pos;
440f05cddf9SRui Paulo 	if (fseek(f, 0, SEEK_SET) < 0) {
441f05cddf9SRui Paulo 		fclose(f);
442f05cddf9SRui Paulo 		return NULL;
443f05cddf9SRui Paulo 	}
44439beb93cSSam Leffler 
445e28a4053SRui Paulo 	buf = os_malloc(*len);
44639beb93cSSam Leffler 	if (buf == NULL) {
44739beb93cSSam Leffler 		fclose(f);
44839beb93cSSam Leffler 		return NULL;
44939beb93cSSam Leffler 	}
45039beb93cSSam Leffler 
45139beb93cSSam Leffler 	if (fread(buf, 1, *len, f) != *len) {
45239beb93cSSam Leffler 		fclose(f);
453e28a4053SRui Paulo 		os_free(buf);
45439beb93cSSam Leffler 		return NULL;
45539beb93cSSam Leffler 	}
45639beb93cSSam Leffler 
45739beb93cSSam Leffler 	fclose(f);
45839beb93cSSam Leffler 
45939beb93cSSam Leffler 	return buf;
46039beb93cSSam Leffler }
46139beb93cSSam Leffler 
46239beb93cSSam Leffler 
os_file_exists(const char * fname)4635b9c547cSRui Paulo int os_file_exists(const char *fname)
4645b9c547cSRui Paulo {
465780fb4a2SCy Schubert 	return access(fname, F_OK) == 0;
4665b9c547cSRui Paulo }
4675b9c547cSRui Paulo 
4685b9c547cSRui Paulo 
469c1d255d3SCy Schubert #if !defined __DragonFly__
os_fdatasync(FILE * stream)470325151a3SRui Paulo int os_fdatasync(FILE *stream)
471325151a3SRui Paulo {
472325151a3SRui Paulo 	if (!fflush(stream)) {
473c1d255d3SCy Schubert #if defined __FreeBSD__ || defined __linux__
474325151a3SRui Paulo 		return fdatasync(fileno(stream));
475c1d255d3SCy Schubert #else /* !__linux__ && !__FreeBSD__ */
476325151a3SRui Paulo #ifdef F_FULLFSYNC
477325151a3SRui Paulo 		/* OS X does not implement fdatasync(). */
478325151a3SRui Paulo 		return fcntl(fileno(stream), F_FULLFSYNC);
479325151a3SRui Paulo #else /* F_FULLFSYNC */
480325151a3SRui Paulo 		return fsync(fileno(stream));
481325151a3SRui Paulo #endif /* F_FULLFSYNC */
482325151a3SRui Paulo #endif /* __linux__ */
483325151a3SRui Paulo 	}
484325151a3SRui Paulo 
485325151a3SRui Paulo 	return -1;
486325151a3SRui Paulo }
487c1d255d3SCy Schubert #endif
488325151a3SRui Paulo 
489325151a3SRui Paulo 
490e28a4053SRui Paulo #ifndef WPA_TRACE
os_zalloc(size_t size)49139beb93cSSam Leffler void * os_zalloc(size_t size)
49239beb93cSSam Leffler {
49339beb93cSSam Leffler 	return calloc(1, size);
49439beb93cSSam Leffler }
495e28a4053SRui Paulo #endif /* WPA_TRACE */
49639beb93cSSam Leffler 
49739beb93cSSam Leffler 
os_strlcpy(char * dest,const char * src,size_t siz)49839beb93cSSam Leffler size_t os_strlcpy(char *dest, const char *src, size_t siz)
49939beb93cSSam Leffler {
50039beb93cSSam Leffler 	const char *s = src;
50139beb93cSSam Leffler 	size_t left = siz;
50239beb93cSSam Leffler 
50339beb93cSSam Leffler 	if (left) {
50439beb93cSSam Leffler 		/* Copy string up to the maximum size of the dest buffer */
50539beb93cSSam Leffler 		while (--left != 0) {
50639beb93cSSam Leffler 			if ((*dest++ = *s++) == '\0')
50739beb93cSSam Leffler 				break;
50839beb93cSSam Leffler 		}
50939beb93cSSam Leffler 	}
51039beb93cSSam Leffler 
51139beb93cSSam Leffler 	if (left == 0) {
51239beb93cSSam Leffler 		/* Not enough room for the string; force NUL-termination */
51339beb93cSSam Leffler 		if (siz != 0)
51439beb93cSSam Leffler 			*dest = '\0';
51539beb93cSSam Leffler 		while (*s++)
51639beb93cSSam Leffler 			; /* determine total src string length */
51739beb93cSSam Leffler 	}
51839beb93cSSam Leffler 
51939beb93cSSam Leffler 	return s - src - 1;
52039beb93cSSam Leffler }
521e28a4053SRui Paulo 
522e28a4053SRui Paulo 
os_memcmp_const(const void * a,const void * b,size_t len)5235b9c547cSRui Paulo int os_memcmp_const(const void *a, const void *b, size_t len)
5245b9c547cSRui Paulo {
5255b9c547cSRui Paulo 	const u8 *aa = a;
5265b9c547cSRui Paulo 	const u8 *bb = b;
5275b9c547cSRui Paulo 	size_t i;
5285b9c547cSRui Paulo 	u8 res;
5295b9c547cSRui Paulo 
5305b9c547cSRui Paulo 	for (res = 0, i = 0; i < len; i++)
5315b9c547cSRui Paulo 		res |= aa[i] ^ bb[i];
5325b9c547cSRui Paulo 
5335b9c547cSRui Paulo 	return res;
5345b9c547cSRui Paulo }
5355b9c547cSRui Paulo 
5365b9c547cSRui Paulo 
os_memdup(const void * src,size_t len)53785732ac8SCy Schubert void * os_memdup(const void *src, size_t len)
53885732ac8SCy Schubert {
53985732ac8SCy Schubert 	void *r = os_malloc(len);
54085732ac8SCy Schubert 
5414bc52338SCy Schubert 	if (r && src)
54285732ac8SCy Schubert 		os_memcpy(r, src, len);
54385732ac8SCy Schubert 	return r;
54485732ac8SCy Schubert }
54585732ac8SCy Schubert 
54685732ac8SCy Schubert 
547e28a4053SRui Paulo #ifdef WPA_TRACE
548e28a4053SRui Paulo 
5495b9c547cSRui Paulo #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
550*a90b9d01SCy Schubert struct wpa_trace_test_fail {
551*a90b9d01SCy Schubert 	unsigned int fail_after;
552*a90b9d01SCy Schubert 	char pattern[256];
553*a90b9d01SCy Schubert } wpa_trace_test_fail[5][2];
5545b9c547cSRui Paulo 
testing_test_fail(const char * tag,bool is_alloc)555*a90b9d01SCy Schubert int testing_test_fail(const char *tag, bool is_alloc)
5565b9c547cSRui Paulo {
557*a90b9d01SCy Schubert 	const char *ignore_list[] = {
558*a90b9d01SCy Schubert 		"os_malloc", "os_zalloc", "os_calloc", "os_realloc",
559*a90b9d01SCy Schubert 		"os_realloc_array", "os_strdup", "os_memdup"
560*a90b9d01SCy Schubert 	};
5615b9c547cSRui Paulo 	const char *func[WPA_TRACE_LEN];
562*a90b9d01SCy Schubert 	size_t i, j, res, len, idx;
5635b9c547cSRui Paulo 	char *pos, *next;
5645b9c547cSRui Paulo 	int match;
5655b9c547cSRui Paulo 
566*a90b9d01SCy Schubert 	is_alloc = !!is_alloc;
567*a90b9d01SCy Schubert 
568*a90b9d01SCy Schubert 	for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) {
569*a90b9d01SCy Schubert 		if (wpa_trace_test_fail[is_alloc][idx].fail_after != 0)
570*a90b9d01SCy Schubert 			break;
571*a90b9d01SCy Schubert 	}
572*a90b9d01SCy Schubert 	if (idx >= ARRAY_SIZE(wpa_trace_test_fail[is_alloc]))
5735b9c547cSRui Paulo 		return 0;
5745b9c547cSRui Paulo 
5755b9c547cSRui Paulo 	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
5765b9c547cSRui Paulo 	i = 0;
577*a90b9d01SCy Schubert 
578*a90b9d01SCy Schubert 	if (is_alloc) {
579*a90b9d01SCy Schubert 		/* Skip our own stack frame */
58085732ac8SCy Schubert 		i++;
5815b9c547cSRui Paulo 
582*a90b9d01SCy Schubert 		/* Skip allocation helpers */
583*a90b9d01SCy Schubert 		for (j = 0; j < ARRAY_SIZE(ignore_list) && i < res; j++) {
584*a90b9d01SCy Schubert 			if (os_strcmp(func[i], ignore_list[j]) == 0)
585*a90b9d01SCy Schubert 				i++;
586*a90b9d01SCy Schubert 		}
587*a90b9d01SCy Schubert 	} else {
588*a90b9d01SCy Schubert 		/* Not allocation, we might have a tag, if so, replace our
589*a90b9d01SCy Schubert 		 * own stack frame with the tag, otherwise skip it.
590*a90b9d01SCy Schubert 		 */
591*a90b9d01SCy Schubert 		if (tag)
592*a90b9d01SCy Schubert 			func[0] = tag;
593*a90b9d01SCy Schubert 		else
594*a90b9d01SCy Schubert 			i++;
595*a90b9d01SCy Schubert 	}
596*a90b9d01SCy Schubert 
597*a90b9d01SCy Schubert 	pos = wpa_trace_test_fail[is_alloc][idx].pattern;
598*a90b9d01SCy Schubert 
599*a90b9d01SCy Schubert 	/* The prefixes mean:
600*a90b9d01SCy Schubert 	 * - '=': The function needs to be next in the backtrace
601*a90b9d01SCy Schubert 	 * - '?': The function is optionally present in the backtrace
602*a90b9d01SCy Schubert 	 */
6035b9c547cSRui Paulo 
6045b9c547cSRui Paulo 	match = 0;
6055b9c547cSRui Paulo 	while (i < res) {
6065b9c547cSRui Paulo 		int allow_skip = 1;
6075b9c547cSRui Paulo 		int maybe = 0;
608*a90b9d01SCy Schubert 		bool prefix = false;
6095b9c547cSRui Paulo 
6105b9c547cSRui Paulo 		if (*pos == '=') {
6115b9c547cSRui Paulo 			allow_skip = 0;
6125b9c547cSRui Paulo 			pos++;
6135b9c547cSRui Paulo 		} else if (*pos == '?') {
6145b9c547cSRui Paulo 			maybe = 1;
6155b9c547cSRui Paulo 			pos++;
6165b9c547cSRui Paulo 		}
6175b9c547cSRui Paulo 		next = os_strchr(pos, ';');
6185b9c547cSRui Paulo 		if (next)
6195b9c547cSRui Paulo 			len = next - pos;
6205b9c547cSRui Paulo 		else
6215b9c547cSRui Paulo 			len = os_strlen(pos);
622*a90b9d01SCy Schubert 		if (len >= 1 && pos[len - 1] == '*') {
623*a90b9d01SCy Schubert 			prefix = true;
624*a90b9d01SCy Schubert 			len -= 1;
625*a90b9d01SCy Schubert 		}
626*a90b9d01SCy Schubert 		if (os_strncmp(pos, func[i], len) != 0 ||
627*a90b9d01SCy Schubert 		    (!prefix && func[i][len] != '\0')) {
6285b9c547cSRui Paulo 			if (maybe && next) {
6295b9c547cSRui Paulo 				pos = next + 1;
6305b9c547cSRui Paulo 				continue;
6315b9c547cSRui Paulo 			}
6325b9c547cSRui Paulo 			if (allow_skip) {
6335b9c547cSRui Paulo 				i++;
6345b9c547cSRui Paulo 				continue;
6355b9c547cSRui Paulo 			}
6365b9c547cSRui Paulo 			return 0;
6375b9c547cSRui Paulo 		}
6385b9c547cSRui Paulo 		if (!next) {
6395b9c547cSRui Paulo 			match = 1;
6405b9c547cSRui Paulo 			break;
6415b9c547cSRui Paulo 		}
6425b9c547cSRui Paulo 		pos = next + 1;
6435b9c547cSRui Paulo 		i++;
6445b9c547cSRui Paulo 	}
6455b9c547cSRui Paulo 	if (!match)
6465b9c547cSRui Paulo 		return 0;
6475b9c547cSRui Paulo 
648*a90b9d01SCy Schubert 	wpa_trace_test_fail[is_alloc][idx].fail_after--;
649*a90b9d01SCy Schubert 	if (wpa_trace_test_fail[is_alloc][idx].fail_after == 0) {
650325151a3SRui Paulo 		wpa_printf(MSG_INFO, "TESTING: fail at %s",
651*a90b9d01SCy Schubert 			   wpa_trace_test_fail[is_alloc][idx].pattern);
652325151a3SRui Paulo 		for (i = 0; i < res; i++)
653325151a3SRui Paulo 			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
654325151a3SRui Paulo 				   (int) i, func[i]);
655325151a3SRui Paulo 		return 1;
656325151a3SRui Paulo 	}
657325151a3SRui Paulo 
658325151a3SRui Paulo 	return 0;
659325151a3SRui Paulo }
660325151a3SRui Paulo 
6615b9c547cSRui Paulo 
testing_set_fail_pattern(bool is_alloc,char * patterns)662*a90b9d01SCy Schubert int testing_set_fail_pattern(bool is_alloc, char *patterns)
663*a90b9d01SCy Schubert {
664*a90b9d01SCy Schubert #ifdef WPA_TRACE_BFD
665*a90b9d01SCy Schubert 	char *token, *context = NULL;
666*a90b9d01SCy Schubert 	size_t idx;
667*a90b9d01SCy Schubert 
668*a90b9d01SCy Schubert 	is_alloc = !!is_alloc;
669*a90b9d01SCy Schubert 
670*a90b9d01SCy Schubert 	os_memset(wpa_trace_test_fail[is_alloc], 0,
671*a90b9d01SCy Schubert 		  sizeof(wpa_trace_test_fail[is_alloc]));
672*a90b9d01SCy Schubert 
673*a90b9d01SCy Schubert 	idx = 0;
674*a90b9d01SCy Schubert 	while ((token = str_token(patterns, " \n\r\t", &context)) &&
675*a90b9d01SCy Schubert 	       idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc])) {
676*a90b9d01SCy Schubert 		wpa_trace_test_fail[is_alloc][idx].fail_after = atoi(token);
677*a90b9d01SCy Schubert 		token = os_strchr(token, ':');
678*a90b9d01SCy Schubert 		if (!token) {
679*a90b9d01SCy Schubert 			os_memset(wpa_trace_test_fail[is_alloc], 0,
680*a90b9d01SCy Schubert 				  sizeof(wpa_trace_test_fail[is_alloc]));
681*a90b9d01SCy Schubert 			return -1;
682*a90b9d01SCy Schubert 		}
683*a90b9d01SCy Schubert 
684*a90b9d01SCy Schubert 		os_strlcpy(wpa_trace_test_fail[is_alloc][idx].pattern,
685*a90b9d01SCy Schubert 			   token + 1,
686*a90b9d01SCy Schubert 			   sizeof(wpa_trace_test_fail[is_alloc][0].pattern));
687*a90b9d01SCy Schubert 		idx++;
688*a90b9d01SCy Schubert 	}
689*a90b9d01SCy Schubert 
690*a90b9d01SCy Schubert 	return 0;
691*a90b9d01SCy Schubert #else /* WPA_TRACE_BFD */
692*a90b9d01SCy Schubert 	return -1;
693*a90b9d01SCy Schubert #endif /* WPA_TRACE_BFD */
694*a90b9d01SCy Schubert }
695*a90b9d01SCy Schubert 
696*a90b9d01SCy Schubert 
testing_get_fail_pattern(bool is_alloc,char * buf,size_t buflen)697*a90b9d01SCy Schubert int testing_get_fail_pattern(bool is_alloc, char *buf, size_t buflen)
698*a90b9d01SCy Schubert {
699*a90b9d01SCy Schubert #ifdef WPA_TRACE_BFD
700*a90b9d01SCy Schubert 	size_t idx, ret;
701*a90b9d01SCy Schubert 	char *pos = buf;
702*a90b9d01SCy Schubert 	char *end = buf + buflen;
703*a90b9d01SCy Schubert 
704*a90b9d01SCy Schubert 	is_alloc = !!is_alloc;
705*a90b9d01SCy Schubert 
706*a90b9d01SCy Schubert 	for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) {
707*a90b9d01SCy Schubert 		if (wpa_trace_test_fail[is_alloc][idx].pattern[0] == '\0')
708*a90b9d01SCy Schubert 			break;
709*a90b9d01SCy Schubert 
710*a90b9d01SCy Schubert 		ret = os_snprintf(pos, end - pos, "%s%u:%s",
711*a90b9d01SCy Schubert 				  pos == buf ? "" : " ",
712*a90b9d01SCy Schubert 				  wpa_trace_test_fail[is_alloc][idx].fail_after,
713*a90b9d01SCy Schubert 				  wpa_trace_test_fail[is_alloc][idx].pattern);
714*a90b9d01SCy Schubert 		if (os_snprintf_error(end - pos, ret))
715*a90b9d01SCy Schubert 			break;
716*a90b9d01SCy Schubert 		pos += ret;
717*a90b9d01SCy Schubert 	}
718*a90b9d01SCy Schubert 
719*a90b9d01SCy Schubert 	return pos - buf;
720*a90b9d01SCy Schubert #else /* WPA_TRACE_BFD */
721*a90b9d01SCy Schubert 	return -1;
722*a90b9d01SCy Schubert #endif /* WPA_TRACE_BFD */
723*a90b9d01SCy Schubert }
724*a90b9d01SCy Schubert 
725*a90b9d01SCy Schubert #else /* defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS) */
726*a90b9d01SCy Schubert 
testing_test_fail(const char * tag,bool is_alloc)727*a90b9d01SCy Schubert static inline int testing_test_fail(const char *tag, bool is_alloc)
7285b9c547cSRui Paulo {
7295b9c547cSRui Paulo 	return 0;
7305b9c547cSRui Paulo }
731*a90b9d01SCy Schubert 
7325b9c547cSRui Paulo #endif
7335b9c547cSRui Paulo 
os_malloc(size_t size)734e28a4053SRui Paulo void * os_malloc(size_t size)
735e28a4053SRui Paulo {
736e28a4053SRui Paulo 	struct os_alloc_trace *a;
7375b9c547cSRui Paulo 
738*a90b9d01SCy Schubert 	if (testing_test_fail(NULL, true))
7395b9c547cSRui Paulo 		return NULL;
7405b9c547cSRui Paulo 
741e28a4053SRui Paulo 	a = malloc(sizeof(*a) + size);
742e28a4053SRui Paulo 	if (a == NULL)
743e28a4053SRui Paulo 		return NULL;
744e28a4053SRui Paulo 	a->magic = ALLOC_MAGIC;
745e28a4053SRui Paulo 	dl_list_add(&alloc_list, &a->list);
746e28a4053SRui Paulo 	a->len = size;
747e28a4053SRui Paulo 	wpa_trace_record(a);
748e28a4053SRui Paulo 	return a + 1;
749e28a4053SRui Paulo }
750e28a4053SRui Paulo 
751e28a4053SRui Paulo 
os_realloc(void * ptr,size_t size)752e28a4053SRui Paulo void * os_realloc(void *ptr, size_t size)
753e28a4053SRui Paulo {
754e28a4053SRui Paulo 	struct os_alloc_trace *a;
755e28a4053SRui Paulo 	size_t copy_len;
756e28a4053SRui Paulo 	void *n;
757e28a4053SRui Paulo 
758e28a4053SRui Paulo 	if (ptr == NULL)
759e28a4053SRui Paulo 		return os_malloc(size);
760e28a4053SRui Paulo 
761e28a4053SRui Paulo 	a = (struct os_alloc_trace *) ptr - 1;
762e28a4053SRui Paulo 	if (a->magic != ALLOC_MAGIC) {
763e28a4053SRui Paulo 		wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
764e28a4053SRui Paulo 			   a, a->magic,
765e28a4053SRui Paulo 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
766e28a4053SRui Paulo 		wpa_trace_show("Invalid os_realloc() call");
767e28a4053SRui Paulo 		abort();
768e28a4053SRui Paulo 	}
769e28a4053SRui Paulo 	n = os_malloc(size);
770e28a4053SRui Paulo 	if (n == NULL)
771e28a4053SRui Paulo 		return NULL;
772e28a4053SRui Paulo 	copy_len = a->len;
773e28a4053SRui Paulo 	if (copy_len > size)
774e28a4053SRui Paulo 		copy_len = size;
775e28a4053SRui Paulo 	os_memcpy(n, a + 1, copy_len);
776e28a4053SRui Paulo 	os_free(ptr);
777e28a4053SRui Paulo 	return n;
778e28a4053SRui Paulo }
779e28a4053SRui Paulo 
780e28a4053SRui Paulo 
os_free(void * ptr)781e28a4053SRui Paulo void os_free(void *ptr)
782e28a4053SRui Paulo {
783e28a4053SRui Paulo 	struct os_alloc_trace *a;
784e28a4053SRui Paulo 
785e28a4053SRui Paulo 	if (ptr == NULL)
786e28a4053SRui Paulo 		return;
787e28a4053SRui Paulo 	a = (struct os_alloc_trace *) ptr - 1;
788e28a4053SRui Paulo 	if (a->magic != ALLOC_MAGIC) {
789e28a4053SRui Paulo 		wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
790e28a4053SRui Paulo 			   a, a->magic,
791e28a4053SRui Paulo 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
792e28a4053SRui Paulo 		wpa_trace_show("Invalid os_free() call");
793e28a4053SRui Paulo 		abort();
794e28a4053SRui Paulo 	}
795e28a4053SRui Paulo 	dl_list_del(&a->list);
796e28a4053SRui Paulo 	a->magic = FREED_MAGIC;
797e28a4053SRui Paulo 
798e28a4053SRui Paulo 	wpa_trace_check_ref(ptr);
799e28a4053SRui Paulo 	free(a);
800e28a4053SRui Paulo }
801e28a4053SRui Paulo 
802e28a4053SRui Paulo 
os_zalloc(size_t size)803e28a4053SRui Paulo void * os_zalloc(size_t size)
804e28a4053SRui Paulo {
805e28a4053SRui Paulo 	void *ptr = os_malloc(size);
806e28a4053SRui Paulo 	if (ptr)
807e28a4053SRui Paulo 		os_memset(ptr, 0, size);
808e28a4053SRui Paulo 	return ptr;
809e28a4053SRui Paulo }
810e28a4053SRui Paulo 
811e28a4053SRui Paulo 
os_strdup(const char * s)812e28a4053SRui Paulo char * os_strdup(const char *s)
813e28a4053SRui Paulo {
814e28a4053SRui Paulo 	size_t len;
815e28a4053SRui Paulo 	char *d;
816e28a4053SRui Paulo 	len = os_strlen(s);
817e28a4053SRui Paulo 	d = os_malloc(len + 1);
818e28a4053SRui Paulo 	if (d == NULL)
819e28a4053SRui Paulo 		return NULL;
820e28a4053SRui Paulo 	os_memcpy(d, s, len);
821e28a4053SRui Paulo 	d[len] = '\0';
822e28a4053SRui Paulo 	return d;
823e28a4053SRui Paulo }
824e28a4053SRui Paulo 
825e28a4053SRui Paulo #endif /* WPA_TRACE */
8265b9c547cSRui Paulo 
8275b9c547cSRui Paulo 
os_exec(const char * program,const char * arg,int wait_completion)8285b9c547cSRui Paulo int os_exec(const char *program, const char *arg, int wait_completion)
8295b9c547cSRui Paulo {
8305b9c547cSRui Paulo 	pid_t pid;
8315b9c547cSRui Paulo 	int pid_status;
8325b9c547cSRui Paulo 
8335b9c547cSRui Paulo 	pid = fork();
8345b9c547cSRui Paulo 	if (pid < 0) {
8355b9c547cSRui Paulo 		perror("fork");
8365b9c547cSRui Paulo 		return -1;
8375b9c547cSRui Paulo 	}
8385b9c547cSRui Paulo 
8395b9c547cSRui Paulo 	if (pid == 0) {
8405b9c547cSRui Paulo 		/* run the external command in the child process */
8415b9c547cSRui Paulo 		const int MAX_ARG = 30;
8425b9c547cSRui Paulo 		char *_program, *_arg, *pos;
8435b9c547cSRui Paulo 		char *argv[MAX_ARG + 1];
8445b9c547cSRui Paulo 		int i;
8455b9c547cSRui Paulo 
8465b9c547cSRui Paulo 		_program = os_strdup(program);
8475b9c547cSRui Paulo 		_arg = os_strdup(arg);
8485b9c547cSRui Paulo 
8495b9c547cSRui Paulo 		argv[0] = _program;
8505b9c547cSRui Paulo 
8515b9c547cSRui Paulo 		i = 1;
8525b9c547cSRui Paulo 		pos = _arg;
8535b9c547cSRui Paulo 		while (i < MAX_ARG && pos && *pos) {
8545b9c547cSRui Paulo 			while (*pos == ' ')
8555b9c547cSRui Paulo 				pos++;
8565b9c547cSRui Paulo 			if (*pos == '\0')
8575b9c547cSRui Paulo 				break;
8585b9c547cSRui Paulo 			argv[i++] = pos;
8595b9c547cSRui Paulo 			pos = os_strchr(pos, ' ');
8605b9c547cSRui Paulo 			if (pos)
8615b9c547cSRui Paulo 				*pos++ = '\0';
8625b9c547cSRui Paulo 		}
8635b9c547cSRui Paulo 		argv[i] = NULL;
8645b9c547cSRui Paulo 
8655b9c547cSRui Paulo 		execv(program, argv);
8665b9c547cSRui Paulo 		perror("execv");
8675b9c547cSRui Paulo 		os_free(_program);
8685b9c547cSRui Paulo 		os_free(_arg);
8695b9c547cSRui Paulo 		exit(0);
8705b9c547cSRui Paulo 		return -1;
8715b9c547cSRui Paulo 	}
8725b9c547cSRui Paulo 
8735b9c547cSRui Paulo 	if (wait_completion) {
8745b9c547cSRui Paulo 		/* wait for the child process to complete in the parent */
8755b9c547cSRui Paulo 		waitpid(pid, &pid_status, 0);
8765b9c547cSRui Paulo 	}
8775b9c547cSRui Paulo 
8785b9c547cSRui Paulo 	return 0;
8795b9c547cSRui Paulo }
880