summaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/browser-wpadebug.c6
-rw-r--r--src/utils/common.c97
-rw-r--r--src/utils/common.h41
-rw-r--r--src/utils/eloop.c45
-rw-r--r--src/utils/http_curl.c14
-rw-r--r--src/utils/includes.h7
-rw-r--r--src/utils/os.h15
-rw-r--r--src/utils/os_internal.c6
-rw-r--r--src/utils/os_none.c6
-rw-r--r--src/utils/os_unix.c120
-rw-r--r--src/utils/os_win32.c18
-rw-r--r--src/utils/radiotap.c4
-rw-r--r--src/utils/utils_module_tests.c440
-rw-r--r--src/utils/wpa_debug.c90
-rw-r--r--src/utils/wpa_debug.h27
-rw-r--r--src/utils/wpabuf.c2
16 files changed, 854 insertions, 84 deletions
diff --git a/src/utils/browser-wpadebug.c b/src/utils/browser-wpadebug.c
index 5fc40fac610e..59ba4d1e02d8 100644
--- a/src/utils/browser-wpadebug.c
+++ b/src/utils/browser-wpadebug.c
@@ -96,7 +96,7 @@ int hs20_web_browser(const char *url)
if (pid == 0) {
/* run the external command in the child process */
- char *argv[12];
+ char *argv[14];
argv[0] = "browser-wpadebug";
argv[1] = "start";
@@ -109,7 +109,9 @@ int hs20_web_browser(const char *url)
argv[8] = "-e";
argv[9] = "w1.fi.wpadebug.URL";
argv[10] = (void *) url;
- argv[11] = NULL;
+ argv[11] = "--user";
+ argv[12] = "-3"; /* USER_CURRENT_OR_SELF */
+ argv[13] = NULL;
execv("/system/bin/am", argv);
wpa_printf(MSG_ERROR, "execv: %s", strerror(errno));
diff --git a/src/utils/common.c b/src/utils/common.c
index 5fd795f3f303..660e9fc985d6 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -8,6 +8,7 @@
#include "includes.h"
+#include "common/ieee802_11_defs.h"
#include "common.h"
@@ -277,6 +278,31 @@ int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...)
return ret;
}
+
+int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len,
+ char sep)
+{
+ size_t i;
+ char *pos = buf, *end = buf + buf_size;
+ int ret;
+
+ if (buf_size == 0)
+ return 0;
+
+ for (i = 0; i < len; i++) {
+ ret = os_snprintf(pos, end - pos, "%02x%c",
+ data[i], sep);
+ if (os_snprintf_error(end - pos, ret)) {
+ end[-1] = '\0';
+ return pos - buf;
+ }
+ pos += ret;
+ }
+ pos[-1] = '\0';
+ return pos - buf;
+}
+
+
static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
size_t len, int uppercase)
{
@@ -584,7 +610,7 @@ size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
*/
const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
{
- static char ssid_txt[32 * 4 + 1];
+ static char ssid_txt[SSID_MAX_LEN * 4 + 1];
if (ssid == NULL) {
ssid_txt[0] = '\0';
@@ -947,6 +973,48 @@ int random_mac_addr_keep_oui(u8 *addr)
/**
+ * cstr_token - Get next token from const char string
+ * @str: a constant string to tokenize
+ * @delim: a string of delimiters
+ * @last: a pointer to a character following the returned token
+ * It has to be set to NULL for the first call and passed for any
+ * futher call.
+ * Returns: a pointer to token position in str or NULL
+ *
+ * This function is similar to str_token, but it can be used with both
+ * char and const char strings. Differences:
+ * - The str buffer remains unmodified
+ * - The returned token is not a NULL terminated string, but a token
+ * position in str buffer. If a return value is not NULL a size
+ * of the returned token could be calculated as (last - token).
+ */
+const char * cstr_token(const char *str, const char *delim, const char **last)
+{
+ const char *end, *token = str;
+
+ if (!str || !delim || !last)
+ return NULL;
+
+ if (*last)
+ token = *last;
+
+ while (*token && os_strchr(delim, *token))
+ token++;
+
+ if (!*token)
+ return NULL;
+
+ end = token + 1;
+
+ while (*end && !os_strchr(delim, *end))
+ end++;
+
+ *last = end;
+ return token;
+}
+
+
+/**
* str_token - Get next token from a string
* @buf: String to tokenize. Note that the string might be modified.
* @delim: String of delimiters
@@ -956,25 +1024,12 @@ int random_mac_addr_keep_oui(u8 *addr)
*/
char * str_token(char *str, const char *delim, char **context)
{
- char *end, *pos = str;
-
- if (*context)
- pos = *context;
-
- while (*pos && os_strchr(delim, *pos))
- pos++;
- if (!*pos)
- return NULL;
-
- end = pos + 1;
- while (*end && !os_strchr(delim, *end))
- end++;
+ char *token = (char *) cstr_token(str, delim, (const char **) context);
- if (*end)
- *end++ = '\0';
+ if (token && **context)
+ *(*context)++ = '\0';
- *context = end;
- return pos;
+ return token;
}
@@ -1062,3 +1117,9 @@ size_t utf8_escape(const char *inp, size_t in_size,
return res_size;
}
+
+
+int is_ctrl_char(char c)
+{
+ return c > 0 && c < 32;
+}
diff --git a/src/utils/common.h b/src/utils/common.h
index 576e8e7e2d4e..0b9cc3d88209 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -53,16 +53,6 @@ static inline unsigned int bswap_32(unsigned int v)
}
#endif /* __APPLE__ */
-#ifdef CONFIG_TI_COMPILER
-#define __BIG_ENDIAN 4321
-#define __LITTLE_ENDIAN 1234
-#ifdef __big_endian__
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#endif
-#endif /* CONFIG_TI_COMPILER */
-
#ifdef CONFIG_NATIVE_WINDOWS
#include <winsock.h>
@@ -110,22 +100,6 @@ typedef INT8 s8;
#define WPA_TYPES_DEFINED
#endif /* __vxworks */
-#ifdef CONFIG_TI_COMPILER
-#ifdef _LLONG_AVAILABLE
-typedef unsigned long long u64;
-#else
-/*
- * TODO: 64-bit variable not available. Using long as a workaround to test the
- * build, but this will likely not work for all operations.
- */
-typedef unsigned long u64;
-#endif
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-#define WPA_TYPES_DEFINED
-#endif /* CONFIG_TI_COMPILER */
-
#ifndef WPA_TYPES_DEFINED
#ifdef CONFIG_USE_INTTYPES_H
#include <inttypes.h>
@@ -262,7 +236,7 @@ static inline void WPA_PUT_BE24(u8 *a, u32 val)
static inline u32 WPA_GET_BE32(const u8 *a)
{
- return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
+ return ((u32) a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
}
static inline void WPA_PUT_BE32(u8 *a, u32 val)
@@ -275,7 +249,7 @@ static inline void WPA_PUT_BE32(u8 *a, u32 val)
static inline u32 WPA_GET_LE32(const u8 *a)
{
- return (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
+ return ((u32) a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
}
static inline void WPA_PUT_LE32(u8 *a, u32 val)
@@ -433,7 +407,7 @@ void perror(const char *s);
#endif
#ifndef BIT
-#define BIT(x) (1 << (x))
+#define BIT(x) (1U << (x))
#endif
/*
@@ -480,6 +454,8 @@ int hexstr2bin(const char *hex, u8 *buf, size_t len);
void inc_byte_array(u8 *counter, size_t len);
void wpa_get_ntp_timestamp(u8 *buf);
int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...);
+int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len,
+ char sep);
int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len);
int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
size_t len);
@@ -516,6 +492,11 @@ static inline int is_broadcast_ether_addr(const u8 *a)
return (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff;
}
+static inline int is_multicast_ether_addr(const u8 *a)
+{
+ return a[0] & 0x01;
+}
+
#define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff"
#include "wpa_debug.h"
@@ -547,11 +528,13 @@ void bin_clear_free(void *bin, size_t len);
int random_mac_addr(u8 *addr);
int random_mac_addr_keep_oui(u8 *addr);
+const char * cstr_token(const char *str, const char *delim, const char **last);
char * str_token(char *str, const char *delim, char **context);
size_t utf8_escape(const char *inp, size_t in_size,
char *outp, size_t out_size);
size_t utf8_unescape(const char *inp, size_t in_size,
char *outp, size_t out_size);
+int is_ctrl_char(char c);
/*
diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index 4a565ebdbd0a..8647229b8eb5 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -61,11 +61,8 @@ struct eloop_signal {
struct eloop_sock_table {
int count;
struct eloop_sock *table;
-#ifdef CONFIG_ELOOP_EPOLL
eloop_event_type type;
-#else /* CONFIG_ELOOP_EPOLL */
int changed;
-#endif /* CONFIG_ELOOP_EPOLL */
};
struct eloop_data {
@@ -256,9 +253,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
table->table = tmp;
eloop.max_sock = new_max_sock;
eloop.count++;
-#ifndef CONFIG_ELOOP_EPOLL
table->changed = 1;
-#endif /* CONFIG_ELOOP_EPOLL */
eloop_trace_sock_add_ref(table);
#ifdef CONFIG_ELOOP_EPOLL
@@ -314,9 +309,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
}
table->count--;
eloop.count--;
-#ifndef CONFIG_ELOOP_EPOLL
table->changed = 1;
-#endif /* CONFIG_ELOOP_EPOLL */
eloop_trace_sock_add_ref(table);
#ifdef CONFIG_ELOOP_EPOLL
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
@@ -523,6 +516,10 @@ static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
continue;
table->handler(table->sock, table->eloop_data,
table->user_data);
+ if (eloop.readers.changed ||
+ eloop.writers.changed ||
+ eloop.exceptions.changed)
+ break;
}
}
#endif /* CONFIG_ELOOP_EPOLL */
@@ -923,6 +920,20 @@ void eloop_run(void)
(!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
struct eloop_timeout *timeout;
+
+ if (eloop.pending_terminate) {
+ /*
+ * This may happen in some corner cases where a signal
+ * is received during a blocking operation. We need to
+ * process the pending signals and exit if requested to
+ * avoid hitting the SIGALRM limit if the blocking
+ * operation took more than two seconds.
+ */
+ eloop_process_pending_signals();
+ if (eloop.terminate)
+ break;
+ }
+
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
list);
if (timeout) {
@@ -977,6 +988,11 @@ void eloop_run(void)
, strerror(errno));
goto out;
}
+
+ eloop.readers.changed = 0;
+ eloop.writers.changed = 0;
+ eloop.exceptions.changed = 0;
+
eloop_process_pending_signals();
/* check if some registered timeouts have occurred */
@@ -998,6 +1014,19 @@ void eloop_run(void)
if (res <= 0)
continue;
+ if (eloop.readers.changed ||
+ eloop.writers.changed ||
+ eloop.exceptions.changed) {
+ /*
+ * Sockets may have been closed and reopened with the
+ * same FD in the signal or timeout handlers, so we
+ * must skip the previous results and check again
+ * whether any of the currently registered sockets have
+ * events.
+ */
+ continue;
+ }
+
#ifdef CONFIG_ELOOP_POLL
eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
&eloop.exceptions, eloop.pollfds_map,
@@ -1073,7 +1102,7 @@ void eloop_destroy(void)
int eloop_terminated(void)
{
- return eloop.terminate;
+ return eloop.terminate || eloop.pending_terminate;
}
diff --git a/src/utils/http_curl.c b/src/utils/http_curl.c
index b38cf796ca2a..653eb541ab47 100644
--- a/src/utils/http_curl.c
+++ b/src/utils/http_curl.c
@@ -855,8 +855,10 @@ static int validate_server_cert(struct http_ctx *ctx, X509 *cert)
struct http_cert hcert;
int ret;
- if (ctx->cert_cb == NULL)
+ if (ctx->cert_cb == NULL) {
+ wpa_printf(MSG_DEBUG, "%s: no cert_cb configured", __func__);
return 0;
+ }
if (0) {
BIO *out;
@@ -950,7 +952,8 @@ static int curl_cb_ssl_verify(int preverify_ok, X509_STORE_CTX *x509_ctx)
ssl_ctx = ssl->ctx;
ctx = SSL_CTX_get_app_data(ssl_ctx);
- wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify");
+ wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify, preverify_ok: %d",
+ preverify_ok);
err = X509_STORE_CTX_get_error(x509_ctx);
err_str = X509_verify_cert_error_string(err);
@@ -1249,9 +1252,14 @@ static CURL * setup_curl_post(struct http_ctx *ctx, const char *address,
const char *client_key)
{
CURL *curl;
+#ifdef EAP_TLS_OPENSSL
+ const char *extra = " tls=openssl";
+#else /* EAP_TLS_OPENSSL */
+ const char *extra = "";
+#endif /* EAP_TLS_OPENSSL */
wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s "
- "username=%s", address, ca_fname, username);
+ "username=%s%s", address, ca_fname, username, extra);
curl = curl_easy_init();
if (curl == NULL)
diff --git a/src/utils/includes.h b/src/utils/includes.h
index 6c6ec87d0eaf..75513fc8c1ef 100644
--- a/src/utils/includes.h
+++ b/src/utils/includes.h
@@ -17,26 +17,22 @@
#include "build_config.h"
#include <stdlib.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#ifndef _WIN32_WCE
-#ifndef CONFIG_TI_COMPILER
#include <signal.h>
#include <sys/types.h>
-#endif /* CONFIG_TI_COMPILER */
#include <errno.h>
#endif /* _WIN32_WCE */
#include <ctype.h>
-#ifndef CONFIG_TI_COMPILER
#ifndef _MSC_VER
#include <unistd.h>
#endif /* _MSC_VER */
-#endif /* CONFIG_TI_COMPILER */
#ifndef CONFIG_NATIVE_WINDOWS
-#ifndef CONFIG_TI_COMPILER
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -44,7 +40,6 @@
#include <sys/uio.h>
#include <sys/time.h>
#endif /* __vxworks */
-#endif /* CONFIG_TI_COMPILER */
#endif /* CONFIG_NATIVE_WINDOWS */
#endif /* INCLUDES_H */
diff --git a/src/utils/os.h b/src/utils/os.h
index 77250d6371c9..9e496fb65978 100644
--- a/src/utils/os.h
+++ b/src/utils/os.h
@@ -247,6 +247,13 @@ char * os_readfile(const char *name, size_t *len);
int os_file_exists(const char *fname);
/**
+ * os_fdatasync - Sync a file's (for a given stream) state with storage device
+ * @stream: the stream to be flushed
+ * Returns: 0 if the operation succeeded or -1 on failure
+ */
+int os_fdatasync(FILE *stream);
+
+/**
* os_zalloc - Allocate and zero memory
* @size: Number of bytes to allocate
* Returns: Pointer to allocated and zeroed memory or %NULL on failure
@@ -646,4 +653,12 @@ int os_exec(const char *program, const char *arg, int wait_completion);
#define strcpy OS_DO_NOT_USE_strcpy
#endif /* OS_REJECT_C_LIB_FUNCTIONS */
+
+#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
+#define TEST_FAIL() testing_test_fail()
+int testing_test_fail(void);
+#else
+#define TEST_FAIL() 0
+#endif
+
#endif /* OS_H */
diff --git a/src/utils/os_internal.c b/src/utils/os_internal.c
index 77733ad916cd..ed6eb3c6b677 100644
--- a/src/utils/os_internal.c
+++ b/src/utils/os_internal.c
@@ -243,6 +243,12 @@ char * os_readfile(const char *name, size_t *len)
}
+int os_fdatasync(FILE *stream)
+{
+ return 0;
+}
+
+
void * os_zalloc(size_t size)
{
void *n = os_malloc(size);
diff --git a/src/utils/os_none.c b/src/utils/os_none.c
index 83fe025167b6..0c3214d32ce5 100644
--- a/src/utils/os_none.c
+++ b/src/utils/os_none.c
@@ -102,6 +102,12 @@ char * os_readfile(const char *name, size_t *len)
}
+int os_fdatasync(FILE *stream)
+{
+ return 0;
+}
+
+
void * os_zalloc(size_t size)
{
return NULL;
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index e0c1125d5305..ffa2e788b3db 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -17,6 +17,12 @@
#include <private/android_filesystem_config.h>
#endif /* ANDROID */
+#ifdef __MACH__
+#include <CoreServices/CoreServices.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#endif /* __MACH__ */
+
#include "os.h"
#include "common.h"
@@ -36,7 +42,7 @@ struct os_alloc_trace {
struct dl_list list;
size_t len;
WPA_TRACE_INFO
-};
+} __attribute__((aligned(16)));
#endif /* WPA_TRACE */
@@ -63,6 +69,7 @@ int os_get_time(struct os_time *t)
int os_get_reltime(struct os_reltime *t)
{
+#ifndef __MACH__
#if defined(CLOCK_BOOTTIME)
static clockid_t clock_id = CLOCK_BOOTTIME;
#elif defined(CLOCK_MONOTONIC)
@@ -95,6 +102,23 @@ int os_get_reltime(struct os_reltime *t)
return -1;
}
}
+#else /* __MACH__ */
+ uint64_t abstime, nano;
+ static mach_timebase_info_data_t info = { 0, 0 };
+
+ if (!info.denom) {
+ if (mach_timebase_info(&info) != KERN_SUCCESS)
+ return -1;
+ }
+
+ abstime = mach_absolute_time();
+ nano = (abstime * info.numer) / info.denom;
+
+ t->sec = nano / NSEC_PER_SEC;
+ t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
+
+ return 0;
+#endif /* __MACH__ */
}
@@ -226,6 +250,9 @@ int os_get_random(unsigned char *buf, size_t len)
FILE *f;
size_t rc;
+ if (TEST_FAIL())
+ return -1;
+
f = fopen("/dev/urandom", "rb");
if (f == NULL) {
printf("Could not open /dev/urandom.\n");
@@ -415,6 +442,25 @@ int os_file_exists(const char *fname)
}
+int os_fdatasync(FILE *stream)
+{
+ if (!fflush(stream)) {
+#ifndef __MACH__
+ return fdatasync(fileno(stream));
+#else /* __MACH__ */
+#ifdef F_FULLFSYNC
+ /* OS X does not implement fdatasync(). */
+ return fcntl(fileno(stream), F_FULLFSYNC);
+#else /* F_FULLFSYNC */
+#error Neither fdatasync nor F_FULLSYNC are defined
+#endif /* F_FULLFSYNC */
+#endif /* __MACH__ */
+ }
+
+ return -1;
+}
+
+
#ifndef WPA_TRACE
void * os_zalloc(size_t size)
{
@@ -548,6 +594,78 @@ static int testing_fail_alloc(void)
return 0;
}
+
+char wpa_trace_test_fail_func[256] = { 0 };
+unsigned int wpa_trace_test_fail_after;
+
+int testing_test_fail(void)
+{
+ const char *func[WPA_TRACE_LEN];
+ size_t i, res, len;
+ char *pos, *next;
+ int match;
+
+ if (!wpa_trace_test_fail_after)
+ return 0;
+
+ res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
+ i = 0;
+ if (i < res && os_strcmp(func[i], __func__) == 0)
+ i++;
+
+ pos = wpa_trace_test_fail_func;
+
+ match = 0;
+ while (i < res) {
+ int allow_skip = 1;
+ int maybe = 0;
+
+ if (*pos == '=') {
+ allow_skip = 0;
+ pos++;
+ } else if (*pos == '?') {
+ maybe = 1;
+ pos++;
+ }
+ next = os_strchr(pos, ';');
+ if (next)
+ len = next - pos;
+ else
+ len = os_strlen(pos);
+ if (os_memcmp(pos, func[i], len) != 0) {
+ if (maybe && next) {
+ pos = next + 1;
+ continue;
+ }
+ if (allow_skip) {
+ i++;
+ continue;
+ }
+ return 0;
+ }
+ if (!next) {
+ match = 1;
+ break;
+ }
+ pos = next + 1;
+ i++;
+ }
+ if (!match)
+ return 0;
+
+ wpa_trace_test_fail_after--;
+ if (wpa_trace_test_fail_after == 0) {
+ wpa_printf(MSG_INFO, "TESTING: fail at %s",
+ wpa_trace_test_fail_func);
+ for (i = 0; i < res; i++)
+ wpa_printf(MSG_INFO, "backtrace[%d] = %s",
+ (int) i, func[i]);
+ return 1;
+ }
+
+ return 0;
+}
+
#else
static inline int testing_fail_alloc(void)
diff --git a/src/utils/os_win32.c b/src/utils/os_win32.c
index 296ea13f153b..dea27b9f2ad8 100644
--- a/src/utils/os_win32.c
+++ b/src/utils/os_win32.c
@@ -216,6 +216,24 @@ char * os_readfile(const char *name, size_t *len)
}
+int os_fdatasync(FILE *stream)
+{
+ HANDLE h;
+
+ if (stream == NULL)
+ return -1;
+
+ h = (HANDLE) _get_osfhandle(_fileno(stream));
+ if (h == INVALID_HANDLE_VALUE)
+ return -1;
+
+ if (!FlushFileBuffers(h))
+ return -1;
+
+ return 0;
+}
+
+
void * os_zalloc(size_t size)
{
return calloc(1, size);
diff --git a/src/utils/radiotap.c b/src/utils/radiotap.c
index f8f815a86be9..c9a502335592 100644
--- a/src/utils/radiotap.c
+++ b/src/utils/radiotap.c
@@ -123,13 +123,13 @@ int ieee80211_radiotap_iterator_init(
/* find payload start allowing for extended bitmap(s) */
- if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+ if (iterator->_bitmap_shifter & BIT(IEEE80211_RADIOTAP_EXT)) {
if ((unsigned long)iterator->_arg -
(unsigned long)iterator->_rtheader + sizeof(uint32_t) >
(unsigned long)iterator->_max_length)
return -EINVAL;
while (get_unaligned_le32(iterator->_arg) &
- (1 << IEEE80211_RADIOTAP_EXT)) {
+ BIT(IEEE80211_RADIOTAP_EXT)) {
iterator->_arg += sizeof(uint32_t);
/*
diff --git a/src/utils/utils_module_tests.c b/src/utils/utils_module_tests.c
index 4b97dadd786c..41511b9999a6 100644
--- a/src/utils/utils_module_tests.c
+++ b/src/utils/utils_module_tests.c
@@ -9,10 +9,13 @@
#include "utils/includes.h"
#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
#include "utils/bitfield.h"
#include "utils/ext_password.h"
#include "utils/trace.h"
#include "utils/base64.h"
+#include "utils/ip_addr.h"
+#include "utils/eloop.h"
struct printf_test_data {
@@ -43,6 +46,7 @@ static int printf_encode_decode_tests(void)
char buf[100];
u8 bin[100];
int errors = 0;
+ int array[10];
wpa_printf(MSG_INFO, "printf encode/decode tests");
@@ -91,9 +95,24 @@ static int printf_encode_decode_tests(void)
if (printf_decode(bin, 3, "\\xa") != 1 || bin[0] != 10)
errors++;
+ if (printf_decode(bin, 3, "\\xq") != 1 || bin[0] != 'q')
+ errors++;
+
if (printf_decode(bin, 3, "\\a") != 1 || bin[0] != 'a')
errors++;
+ array[0] = 10;
+ array[1] = 10;
+ array[2] = 5;
+ array[3] = 10;
+ array[4] = 5;
+ array[5] = 0;
+ if (int_array_len(array) != 5)
+ errors++;
+ int_array_sort_unique(array);
+ if (int_array_len(array) != 2)
+ errors++;
+
if (errors) {
wpa_printf(MSG_ERROR, "%d printf test(s) failed", errors);
return -1;
@@ -335,11 +354,14 @@ static int base64_tests(void)
static int common_tests(void)
{
- char buf[3];
+ char buf[3], longbuf[100];
u8 addr[ETH_ALEN] = { 1, 2, 3, 4, 5, 6 };
u8 bin[3];
int errors = 0;
struct wpa_freq_range_list ranges;
+ size_t len;
+ const char *txt;
+ u8 ssid[255];
wpa_printf(MSG_INFO, "common tests");
@@ -395,6 +417,21 @@ static int common_tests(void)
if (utf8_escape("a", 0, buf, sizeof(buf)) != 1 || buf[0] != 'a')
errors++;
+ os_memset(ssid, 0, sizeof(ssid));
+ txt = wpa_ssid_txt(ssid, sizeof(ssid));
+ len = os_strlen(txt);
+ /* Verify that SSID_MAX_LEN * 4 buffer limit is enforced. */
+ if (len != SSID_MAX_LEN * 4) {
+ wpa_printf(MSG_ERROR,
+ "Unexpected wpa_ssid_txt() result with too long SSID");
+ errors++;
+ }
+
+ if (wpa_snprintf_hex_sep(longbuf, 0, addr, ETH_ALEN, '-') != 0 ||
+ wpa_snprintf_hex_sep(longbuf, 5, addr, ETH_ALEN, '-') != 3 ||
+ os_strcmp(longbuf, "01-0") != 0)
+ errors++;
+
if (errors) {
wpa_printf(MSG_ERROR, "%d common test(s) failed", errors);
return -1;
@@ -404,6 +441,403 @@ static int common_tests(void)
}
+static int os_tests(void)
+{
+ int errors = 0;
+ void *ptr;
+ os_time_t t;
+
+ wpa_printf(MSG_INFO, "os tests");
+
+ ptr = os_calloc((size_t) -1, (size_t) -1);
+ if (ptr) {
+ errors++;
+ os_free(ptr);
+ }
+ ptr = os_calloc((size_t) 2, (size_t) -1);
+ if (ptr) {
+ errors++;
+ os_free(ptr);
+ }
+ ptr = os_calloc((size_t) -1, (size_t) 2);
+ if (ptr) {
+ errors++;
+ os_free(ptr);
+ }
+
+ ptr = os_realloc_array(NULL, (size_t) -1, (size_t) -1);
+ if (ptr) {
+ errors++;
+ os_free(ptr);
+ }
+
+ os_sleep(1, 1);
+
+ if (os_mktime(1969, 1, 1, 1, 1, 1, &t) == 0 ||
+ os_mktime(1971, 0, 1, 1, 1, 1, &t) == 0 ||
+ os_mktime(1971, 13, 1, 1, 1, 1, &t) == 0 ||
+ os_mktime(1971, 1, 0, 1, 1, 1, &t) == 0 ||
+ os_mktime(1971, 1, 32, 1, 1, 1, &t) == 0 ||
+ os_mktime(1971, 1, 1, -1, 1, 1, &t) == 0 ||
+ os_mktime(1971, 1, 1, 24, 1, 1, &t) == 0 ||
+ os_mktime(1971, 1, 1, 1, -1, 1, &t) == 0 ||
+ os_mktime(1971, 1, 1, 1, 60, 1, &t) == 0 ||
+ os_mktime(1971, 1, 1, 1, 1, -1, &t) == 0 ||
+ os_mktime(1971, 1, 1, 1, 1, 61, &t) == 0 ||
+ os_mktime(1971, 1, 1, 1, 1, 1, &t) != 0 ||
+ os_mktime(2020, 1, 2, 3, 4, 5, &t) != 0 ||
+ os_mktime(2015, 12, 31, 23, 59, 59, &t) != 0)
+ errors++;
+
+ if (os_setenv("hwsim_test_env", "test value", 0) != 0 ||
+ os_setenv("hwsim_test_env", "test value 2", 1) != 0 ||
+ os_unsetenv("hwsim_test_env") != 0)
+ errors++;
+
+ if (os_file_exists("/this-file-does-not-exists-hwsim") != 0)
+ errors++;
+
+ if (errors) {
+ wpa_printf(MSG_ERROR, "%d os test(s) failed", errors);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int wpabuf_tests(void)
+{
+ int errors = 0;
+ void *ptr;
+ struct wpabuf *buf;
+
+ wpa_printf(MSG_INFO, "wpabuf tests");
+
+ ptr = os_malloc(100);
+ if (ptr) {
+ buf = wpabuf_alloc_ext_data(ptr, 100);
+ if (buf) {
+ if (wpabuf_resize(&buf, 100) < 0)
+ errors++;
+ else
+ wpabuf_put(buf, 100);
+ wpabuf_free(buf);
+ } else {
+ errors++;
+ os_free(ptr);
+ }
+ } else {
+ errors++;
+ }
+
+ buf = wpabuf_alloc(100);
+ if (buf) {
+ struct wpabuf *buf2;
+
+ wpabuf_put(buf, 100);
+ if (wpabuf_resize(&buf, 100) < 0)
+ errors++;
+ else
+ wpabuf_put(buf, 100);
+ buf2 = wpabuf_concat(buf, NULL);
+ if (buf2 != buf)
+ errors++;
+ wpabuf_free(buf2);
+ } else {
+ errors++;
+ }
+
+ buf = NULL;
+ buf = wpabuf_zeropad(buf, 10);
+ if (buf != NULL)
+ errors++;
+
+ if (errors) {
+ wpa_printf(MSG_ERROR, "%d wpabuf test(s) failed", errors);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int ip_addr_tests(void)
+{
+ int errors = 0;
+ struct hostapd_ip_addr addr;
+ char buf[100];
+
+ wpa_printf(MSG_INFO, "ip_addr tests");
+
+ if (hostapd_parse_ip_addr("1.2.3.4", &addr) != 0 ||
+ addr.af != AF_INET ||
+ hostapd_ip_txt(NULL, buf, sizeof(buf)) != NULL ||
+ hostapd_ip_txt(&addr, buf, 1) != buf || buf[0] != '\0' ||
+ hostapd_ip_txt(&addr, buf, 0) != NULL ||
+ hostapd_ip_txt(&addr, buf, sizeof(buf)) != buf)
+ errors++;
+
+ if (hostapd_parse_ip_addr("::", &addr) != 0 ||
+ addr.af != AF_INET6 ||
+ hostapd_ip_txt(&addr, buf, 1) != buf || buf[0] != '\0' ||
+ hostapd_ip_txt(&addr, buf, sizeof(buf)) != buf)
+ errors++;
+
+ if (errors) {
+ wpa_printf(MSG_ERROR, "%d ip_addr test(s) failed", errors);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+struct test_eloop {
+ unsigned int magic;
+ int close_in_timeout;
+ int pipefd1[2];
+ int pipefd2[2];
+};
+
+
+static void eloop_tests_start(int close_in_timeout);
+
+
+static void eloop_test_read_2(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct test_eloop *t = eloop_ctx;
+ ssize_t res;
+ char buf[10];
+
+ wpa_printf(MSG_INFO, "%s: sock=%d", __func__, sock);
+
+ if (t->magic != 0x12345678) {
+ wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
+ __func__, t->magic);
+ }
+
+ if (t->pipefd2[0] != sock) {
+ wpa_printf(MSG_INFO, "%s: unexpected sock %d != %d",
+ __func__, sock, t->pipefd2[0]);
+ }
+
+ res = read(sock, buf, sizeof(buf));
+ wpa_printf(MSG_INFO, "%s: sock=%d --> res=%d",
+ __func__, sock, (int) res);
+}
+
+
+static void eloop_test_read_2_wrong(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct test_eloop *t = eloop_ctx;
+
+ wpa_printf(MSG_INFO, "%s: sock=%d", __func__, sock);
+
+ if (t->magic != 0x12345678) {
+ wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
+ __func__, t->magic);
+ }
+
+ if (t->pipefd2[0] != sock) {
+ wpa_printf(MSG_INFO, "%s: unexpected sock %d != %d",
+ __func__, sock, t->pipefd2[0]);
+ }
+
+ /*
+ * This is expected to block due to the original socket with data having
+ * been closed and no new data having been written to the new socket
+ * with the same fd. To avoid blocking the process during test, skip the
+ * read here.
+ */
+ wpa_printf(MSG_ERROR, "%s: FAIL - should not have called this function",
+ __func__);
+}
+
+
+static void reopen_pipefd2(struct test_eloop *t)
+{
+ if (t->pipefd2[0] < 0) {
+ wpa_printf(MSG_INFO, "pipefd2 had been closed");
+ } else {
+ int res;
+
+ wpa_printf(MSG_INFO, "close pipefd2");
+ eloop_unregister_read_sock(t->pipefd2[0]);
+ close(t->pipefd2[0]);
+ t->pipefd2[0] = -1;
+ close(t->pipefd2[1]);
+ t->pipefd2[1] = -1;
+
+ res = pipe(t->pipefd2);
+ if (res < 0) {
+ wpa_printf(MSG_INFO, "pipe: %s", strerror(errno));
+ t->pipefd2[0] = -1;
+ t->pipefd2[1] = -1;
+ return;
+ }
+
+ wpa_printf(MSG_INFO,
+ "re-register pipefd2 with new sockets %d,%d",
+ t->pipefd2[0], t->pipefd2[1]);
+ eloop_register_read_sock(t->pipefd2[0], eloop_test_read_2_wrong,
+ t, NULL);
+ }
+}
+
+
+static void eloop_test_read_1(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct test_eloop *t = eloop_ctx;
+ ssize_t res;
+ char buf[10];
+
+ wpa_printf(MSG_INFO, "%s: sock=%d", __func__, sock);
+
+ if (t->magic != 0x12345678) {
+ wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
+ __func__, t->magic);
+ }
+
+ if (t->pipefd1[0] != sock) {
+ wpa_printf(MSG_INFO, "%s: unexpected sock %d != %d",
+ __func__, sock, t->pipefd1[0]);
+ }
+
+ res = read(sock, buf, sizeof(buf));
+ wpa_printf(MSG_INFO, "%s: sock=%d --> res=%d",
+ __func__, sock, (int) res);
+
+ if (!t->close_in_timeout)
+ reopen_pipefd2(t);
+}
+
+
+static void eloop_test_cb(void *eloop_data, void *user_ctx)
+{
+ struct test_eloop *t = eloop_data;
+
+ wpa_printf(MSG_INFO, "%s", __func__);
+
+ if (t->magic != 0x12345678) {
+ wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
+ __func__, t->magic);
+ }
+
+ if (t->close_in_timeout)
+ reopen_pipefd2(t);
+}
+
+
+static void eloop_test_timeout(void *eloop_data, void *user_ctx)
+{
+ struct test_eloop *t = eloop_data;
+ int next_run = 0;
+
+ wpa_printf(MSG_INFO, "%s", __func__);
+
+ if (t->magic != 0x12345678) {
+ wpa_printf(MSG_INFO, "%s: unexpected magic 0x%x",
+ __func__, t->magic);
+ }
+
+ if (t->pipefd1[0] >= 0) {
+ wpa_printf(MSG_INFO, "pipefd1 had not been closed");
+ eloop_unregister_read_sock(t->pipefd1[0]);
+ close(t->pipefd1[0]);
+ t->pipefd1[0] = -1;
+ close(t->pipefd1[1]);
+ t->pipefd1[1] = -1;
+ }
+
+ if (t->pipefd2[0] >= 0) {
+ wpa_printf(MSG_INFO, "pipefd2 had not been closed");
+ eloop_unregister_read_sock(t->pipefd2[0]);
+ close(t->pipefd2[0]);
+ t->pipefd2[0] = -1;
+ close(t->pipefd2[1]);
+ t->pipefd2[1] = -1;
+ }
+
+ next_run = t->close_in_timeout;
+ t->magic = 0;
+ wpa_printf(MSG_INFO, "%s - free(%p)", __func__, t);
+ os_free(t);
+
+ if (next_run)
+ eloop_tests_start(0);
+}
+
+
+static void eloop_tests_start(int close_in_timeout)
+{
+ struct test_eloop *t;
+ int res;
+
+ t = os_zalloc(sizeof(*t));
+ if (!t)
+ return;
+ t->magic = 0x12345678;
+ t->close_in_timeout = close_in_timeout;
+
+ wpa_printf(MSG_INFO, "starting eloop tests (%p) (close_in_timeout=%d)",
+ t, close_in_timeout);
+
+ res = pipe(t->pipefd1);
+ if (res < 0) {
+ wpa_printf(MSG_INFO, "pipe: %s", strerror(errno));
+ os_free(t);
+ return;
+ }
+
+ res = pipe(t->pipefd2);
+ if (res < 0) {
+ wpa_printf(MSG_INFO, "pipe: %s", strerror(errno));
+ close(t->pipefd1[0]);
+ close(t->pipefd1[1]);
+ os_free(t);
+ return;
+ }
+
+ wpa_printf(MSG_INFO, "pipe fds: %d,%d %d,%d",
+ t->pipefd1[0], t->pipefd1[1],
+ t->pipefd2[0], t->pipefd2[1]);
+
+ eloop_register_read_sock(t->pipefd1[0], eloop_test_read_1, t, NULL);
+ eloop_register_read_sock(t->pipefd2[0], eloop_test_read_2, t, NULL);
+ eloop_register_timeout(0, 0, eloop_test_cb, t, NULL);
+ eloop_register_timeout(0, 200000, eloop_test_timeout, t, NULL);
+
+ if (write(t->pipefd1[1], "HELLO", 5) < 0)
+ wpa_printf(MSG_INFO, "write: %s", strerror(errno));
+ if (write(t->pipefd2[1], "TEST", 4) < 0)
+ wpa_printf(MSG_INFO, "write: %s", strerror(errno));
+ os_sleep(0, 50000);
+ wpa_printf(MSG_INFO, "waiting for eloop callbacks");
+}
+
+
+static void eloop_tests_run(void *eloop_data, void *user_ctx)
+{
+ eloop_tests_start(1);
+}
+
+
+static int eloop_tests(void)
+{
+ wpa_printf(MSG_INFO, "schedule eloop tests to be run");
+
+ /*
+ * Cannot return error from these without a significant design change,
+ * so for now, run the tests from a scheduled timeout and require
+ * separate verification of the results from the debug log.
+ */
+ eloop_register_timeout(0, 0, eloop_tests_run, NULL, NULL);
+
+ return 0;
+}
+
+
int utils_module_tests(void)
{
int ret = 0;
@@ -416,6 +850,10 @@ int utils_module_tests(void)
bitfield_tests() < 0 ||
base64_tests() < 0 ||
common_tests() < 0 ||
+ os_tests() < 0 ||
+ wpabuf_tests() < 0 ||
+ ip_addr_tests() < 0 ||
+ eloop_tests() < 0 ||
int_array_tests() < 0)
ret = -1;
diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
index 0d1190518536..61c0d5ce68c7 100644
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -307,7 +307,7 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf,
"%s - hexdump(len=%lu):%s%s",
title, (long unsigned int) len, display,
len > slen ? " ..." : "");
- os_free(strbuf);
+ bin_clear_free(strbuf, 1 + 3 * slen);
return;
}
#else /* CONFIG_ANDROID_LOG */
@@ -339,7 +339,7 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf,
syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s",
title, (unsigned long) len, display);
- os_free(strbuf);
+ bin_clear_free(strbuf, 1 + 3 * len);
return;
}
#endif /* CONFIG_DEBUG_SYSLOG */
@@ -635,8 +635,8 @@ void wpa_msg(void *ctx, int level, const char *fmt, ...)
va_end(ap);
wpa_printf(level, "%s%s", prefix, buf);
if (wpa_msg_cb)
- wpa_msg_cb(ctx, level, 0, buf, len);
- os_free(buf);
+ wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len);
+ bin_clear_free(buf, buflen);
}
@@ -663,8 +663,8 @@ void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
va_start(ap, fmt);
len = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
- wpa_msg_cb(ctx, level, 0, buf, len);
- os_free(buf);
+ wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len);
+ bin_clear_free(buf, buflen);
}
@@ -690,8 +690,8 @@ void wpa_msg_global(void *ctx, int level, const char *fmt, ...)
va_end(ap);
wpa_printf(level, "%s", buf);
if (wpa_msg_cb)
- wpa_msg_cb(ctx, level, 1, buf, len);
- os_free(buf);
+ wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len);
+ bin_clear_free(buf, buflen);
}
@@ -718,8 +718,8 @@ void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...)
va_start(ap, fmt);
len = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
- wpa_msg_cb(ctx, level, 1, buf, len);
- os_free(buf);
+ wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len);
+ bin_clear_free(buf, buflen);
}
@@ -745,7 +745,34 @@ void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
va_end(ap);
wpa_printf(level, "%s", buf);
if (wpa_msg_cb)
- wpa_msg_cb(ctx, level, 2, buf, len);
+ wpa_msg_cb(ctx, level, WPA_MSG_NO_GLOBAL, buf, len);
+ bin_clear_free(buf, buflen);
+}
+
+
+void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ int buflen;
+ int len;
+
+ va_start(ap, fmt);
+ buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
+
+ buf = os_malloc(buflen);
+ if (buf == NULL) {
+ wpa_printf(MSG_ERROR, "%s: Failed to allocate message buffer",
+ __func__);
+ return;
+ }
+ va_start(ap, fmt);
+ len = vsnprintf(buf, buflen, fmt, ap);
+ va_end(ap);
+ wpa_printf(level, "%s", buf);
+ if (wpa_msg_cb)
+ wpa_msg_cb(ctx, level, WPA_MSG_ONLY_GLOBAL, buf, len);
os_free(buf);
}
@@ -789,6 +816,45 @@ void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
MAC2STR(addr), buf);
else
wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
- os_free(buf);
+ bin_clear_free(buf, buflen);
}
#endif /* CONFIG_NO_HOSTAPD_LOGGER */
+
+
+const char * debug_level_str(int level)
+{
+ switch (level) {
+ case MSG_EXCESSIVE:
+ return "EXCESSIVE";
+ case MSG_MSGDUMP:
+ return "MSGDUMP";
+ case MSG_DEBUG:
+ return "DEBUG";
+ case MSG_INFO:
+ return "INFO";
+ case MSG_WARNING:
+ return "WARNING";
+ case MSG_ERROR:
+ return "ERROR";
+ default:
+ return "?";
+ }
+}
+
+
+int str_to_debug_level(const char *s)
+{
+ if (os_strcasecmp(s, "EXCESSIVE") == 0)
+ return MSG_EXCESSIVE;
+ if (os_strcasecmp(s, "MSGDUMP") == 0)
+ return MSG_MSGDUMP;
+ if (os_strcasecmp(s, "DEBUG") == 0)
+ return MSG_DEBUG;
+ if (os_strcasecmp(s, "INFO") == 0)
+ return MSG_INFO;
+ if (os_strcasecmp(s, "WARNING") == 0)
+ return MSG_WARNING;
+ if (os_strcasecmp(s, "ERROR") == 0)
+ return MSG_ERROR;
+ return -1;
+}
diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h
index 400bea9e599f..17d8f963802e 100644
--- a/src/utils/wpa_debug.h
+++ b/src/utils/wpa_debug.h
@@ -164,6 +164,7 @@ void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
#define wpa_msg_global(args...) do { } while (0)
#define wpa_msg_global_ctrl(args...) do { } while (0)
#define wpa_msg_no_global(args...) do { } while (0)
+#define wpa_msg_global_only(args...) do { } while (0)
#define wpa_msg_register_cb(f) do { } while (0)
#define wpa_msg_register_ifname_cb(f) do { } while (0)
#else /* CONFIG_NO_WPA_MSG */
@@ -243,7 +244,28 @@ PRINTF_FORMAT(3, 4);
void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
PRINTF_FORMAT(3, 4);
-typedef void (*wpa_msg_cb_func)(void *ctx, int level, int global,
+/**
+ * wpa_msg_global_only - Conditional printf for ctrl_iface monitors
+ * @ctx: Pointer to context data; this is the ctx variable registered
+ * with struct wpa_driver_ops::init()
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages.
+ * This function is like wpa_msg_global(), but it sends the output only as a
+ * global event.
+ */
+void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...)
+PRINTF_FORMAT(3, 4);
+
+enum wpa_msg_type {
+ WPA_MSG_PER_INTERFACE,
+ WPA_MSG_GLOBAL,
+ WPA_MSG_NO_GLOBAL,
+ WPA_MSG_ONLY_GLOBAL,
+};
+
+typedef void (*wpa_msg_cb_func)(void *ctx, int level, enum wpa_msg_type type,
const char *txt, size_t len);
/**
@@ -342,4 +364,7 @@ static inline void wpa_debug_close_linux_tracing(void)
#define WPA_ASSERT(a) do { } while (0)
#endif
+const char * debug_level_str(int level);
+int str_to_debug_level(const char *s);
+
#endif /* WPA_DEBUG_H */
diff --git a/src/utils/wpabuf.c b/src/utils/wpabuf.c
index 7aafa0a5169b..11e7323619de 100644
--- a/src/utils/wpabuf.c
+++ b/src/utils/wpabuf.c
@@ -17,7 +17,7 @@
struct wpabuf_trace {
unsigned int magic;
-};
+} __attribute__((aligned(8)));
static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf)
{