replace common qcom sources with samsung ones

This commit is contained in:
SaschaNes
2025-08-12 22:13:00 +02:00
parent ba24dcded9
commit 6f7753de11
5682 changed files with 2450203 additions and 103634 deletions

View File

@@ -0,0 +1,978 @@
/*
* wpa_supplicant/hostapd / common helper functions, etc.
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
static int hex2num(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
int hex2byte(const char *hex)
{
int a, b;
a = hex2num(*hex++);
if (a < 0)
return -1;
b = hex2num(*hex++);
if (b < 0)
return -1;
return (a << 4) | b;
}
static const char * hwaddr_parse(const char *txt, u8 *addr)
{
size_t i;
for (i = 0; i < ETH_ALEN; i++) {
int a;
a = hex2byte(txt);
if (a < 0)
return NULL;
txt += 2;
addr[i] = a;
if (i < ETH_ALEN - 1 && *txt++ != ':')
return NULL;
}
return txt;
}
/**
* hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
* @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
* @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
* Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
*/
int hwaddr_aton(const char *txt, u8 *addr)
{
return hwaddr_parse(txt, addr) ? 0 : -1;
}
/**
* hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format)
* @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00")
* @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
* @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes)
* @maskable: Flag to indicate whether a mask is allowed
* Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
*/
int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable)
{
const char *r;
/* parse address part */
r = hwaddr_parse(txt, addr);
if (!r)
return -1;
/* check for optional mask */
if (*r == '\0' || isspace(*r)) {
/* no mask specified, assume default */
os_memset(mask, 0xff, ETH_ALEN);
} else if (maskable && *r == '/') {
/* mask specified and allowed */
r = hwaddr_parse(r + 1, mask);
/* parser error? */
if (!r)
return -1;
} else {
/* mask specified but not allowed or trailing garbage */
return -1;
}
return 0;
}
/**
* hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format)
* @txt: MAC address as a string (e.g., "001122334455")
* @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
* Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
*/
int hwaddr_compact_aton(const char *txt, u8 *addr)
{
int i;
for (i = 0; i < 6; i++) {
int a, b;
a = hex2num(*txt++);
if (a < 0)
return -1;
b = hex2num(*txt++);
if (b < 0)
return -1;
*addr++ = (a << 4) | b;
}
return 0;
}
/**
* hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
* @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
* @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
* Returns: Characters used (> 0) on success, -1 on failure
*/
int hwaddr_aton2(const char *txt, u8 *addr)
{
int i;
const char *pos = txt;
for (i = 0; i < 6; i++) {
int a, b;
while (*pos == ':' || *pos == '.' || *pos == '-')
pos++;
a = hex2num(*pos++);
if (a < 0)
return -1;
b = hex2num(*pos++);
if (b < 0)
return -1;
*addr++ = (a << 4) | b;
}
return pos - txt;
}
/**
* hexstr2bin - Convert ASCII hex string into binary data
* @hex: ASCII hex string (e.g., "01ab")
* @buf: Buffer for the binary data
* @len: Length of the text to convert in bytes (of buf); hex will be double
* this size
* Returns: 0 on success, -1 on failure (invalid hex string)
*/
int hexstr2bin(const char *hex, u8 *buf, size_t len)
{
size_t i;
int a;
const char *ipos = hex;
u8 *opos = buf;
for (i = 0; i < len; i++) {
a = hex2byte(ipos);
if (a < 0)
return -1;
*opos++ = a;
ipos += 2;
}
return 0;
}
int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask)
{
size_t i;
int print_mask = 0;
int res;
for (i = 0; i < ETH_ALEN; i++) {
if (mask[i] != 0xff) {
print_mask = 1;
break;
}
}
if (print_mask)
res = os_snprintf(buf, len, MACSTR "/" MACSTR,
MAC2STR(addr), MAC2STR(mask));
else
res = os_snprintf(buf, len, MACSTR, MAC2STR(addr));
if (os_snprintf_error(len, res))
return -1;
return res;
}
/**
* inc_byte_array - Increment arbitrary length byte array by one
* @counter: Pointer to byte array
* @len: Length of the counter in bytes
*
* This function increments the last byte of the counter by one and continues
* rolling over to more significant bytes if the byte was incremented from
* 0xff to 0x00.
*/
void inc_byte_array(u8 *counter, size_t len)
{
int pos = len - 1;
while (pos >= 0) {
counter[pos]++;
if (counter[pos] != 0)
break;
pos--;
}
}
void wpa_get_ntp_timestamp(u8 *buf)
{
struct os_time now;
u32 sec, usec;
be32 tmp;
/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
os_get_time(&now);
sec = now.sec + 2208988800U; /* Epoch to 1900 */
/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
usec = now.usec;
usec = 4295 * usec - (usec >> 5) - (usec >> 9);
tmp = host_to_be32(sec);
os_memcpy(buf, (u8 *) &tmp, 4);
tmp = host_to_be32(usec);
os_memcpy(buf + 4, (u8 *) &tmp, 4);
}
/**
* wpa_scnprintf - Simpler-to-use snprintf function
* @buf: Output buffer
* @size: Buffer size
* @fmt: format
*
* Simpler snprintf version that doesn't require further error checks - the
* return value only indicates how many bytes were actually written, excluding
* the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough).
*/
int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...)
{
va_list ap;
int ret;
if (!size)
return 0;
va_start(ap, fmt);
ret = vsnprintf(buf, size, fmt, ap);
va_end(ap);
if (ret < 0)
return 0;
if ((size_t) ret >= size)
return size - 1;
return ret;
}
static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data,
size_t len, int uppercase)
{
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, uppercase ? "%02X" : "%02x",
data[i]);
if (os_snprintf_error(end - pos, ret)) {
end[-1] = '\0';
return pos - buf;
}
pos += ret;
}
end[-1] = '\0';
return pos - buf;
}
/**
* wpa_snprintf_hex - Print data as a hex string into a buffer
* @buf: Memory area to use as the output buffer
* @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
* @data: Data to be printed
* @len: Length of data in bytes
* Returns: Number of bytes written
*/
int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len)
{
return _wpa_snprintf_hex(buf, buf_size, data, len, 0);
}
/**
* wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf
* @buf: Memory area to use as the output buffer
* @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1)
* @data: Data to be printed
* @len: Length of data in bytes
* Returns: Number of bytes written
*/
int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
size_t len)
{
return _wpa_snprintf_hex(buf, buf_size, data, len, 1);
}
#ifdef CONFIG_ANSI_C_EXTRA
#ifdef _WIN32_WCE
void perror(const char *s)
{
wpa_printf(MSG_ERROR, "%s: GetLastError: %d",
s, (int) GetLastError());
}
#endif /* _WIN32_WCE */
int optind = 1;
int optopt;
char *optarg;
int getopt(int argc, char *const argv[], const char *optstring)
{
static int optchr = 1;
char *cp;
if (optchr == 1) {
if (optind >= argc) {
/* all arguments processed */
return EOF;
}
if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
/* no option characters */
return EOF;
}
}
if (os_strcmp(argv[optind], "--") == 0) {
/* no more options */
optind++;
return EOF;
}
optopt = argv[optind][optchr];
cp = os_strchr(optstring, optopt);
if (cp == NULL || optopt == ':') {
if (argv[optind][++optchr] == '\0') {
optchr = 1;
optind++;
}
return '?';
}
if (cp[1] == ':') {
/* Argument required */
optchr = 1;
if (argv[optind][optchr + 1]) {
/* No space between option and argument */
optarg = &argv[optind++][optchr + 1];
} else if (++optind >= argc) {
/* option requires an argument */
return '?';
} else {
/* Argument in the next argv */
optarg = argv[optind++];
}
} else {
/* No argument */
if (argv[optind][++optchr] == '\0') {
optchr = 1;
optind++;
}
optarg = NULL;
}
return *cp;
}
#endif /* CONFIG_ANSI_C_EXTRA */
#ifdef CONFIG_NATIVE_WINDOWS
/**
* wpa_unicode2ascii_inplace - Convert unicode string into ASCII
* @str: Pointer to string to convert
*
* This function converts a unicode string to ASCII using the same
* buffer for output. If UNICODE is not set, the buffer is not
* modified.
*/
void wpa_unicode2ascii_inplace(TCHAR *str)
{
#ifdef UNICODE
char *dst = (char *) str;
while (*str)
*dst++ = (char) *str++;
*dst = '\0';
#endif /* UNICODE */
}
TCHAR * wpa_strdup_tchar(const char *str)
{
#ifdef UNICODE
TCHAR *buf;
buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR));
if (buf == NULL)
return NULL;
wsprintf(buf, L"%S", str);
return buf;
#else /* UNICODE */
return os_strdup(str);
#endif /* UNICODE */
}
#endif /* CONFIG_NATIVE_WINDOWS */
void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
{
char *end = txt + maxlen;
size_t i;
for (i = 0; i < len; i++) {
if (txt + 4 >= end)
break;
switch (data[i]) {
case '\"':
*txt++ = '\\';
*txt++ = '\"';
break;
case '\\':
*txt++ = '\\';
*txt++ = '\\';
break;
case '\033':
*txt++ = '\\';
*txt++ = 'e';
break;
case '\n':
*txt++ = '\\';
*txt++ = 'n';
break;
case '\r':
*txt++ = '\\';
*txt++ = 'r';
break;
case '\t':
*txt++ = '\\';
*txt++ = 't';
break;
default:
if (data[i] >= 32 && data[i] <= 127) {
*txt++ = data[i];
} else {
txt += os_snprintf(txt, end - txt, "\\x%02x",
data[i]);
}
break;
}
}
*txt = '\0';
}
size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
{
const char *pos = str;
size_t len = 0;
int val;
while (*pos) {
if (len + 1 >= maxlen)
break;
switch (*pos) {
case '\\':
pos++;
switch (*pos) {
case '\\':
buf[len++] = '\\';
pos++;
break;
case '"':
buf[len++] = '"';
pos++;
break;
case 'n':
buf[len++] = '\n';
pos++;
break;
case 'r':
buf[len++] = '\r';
pos++;
break;
case 't':
buf[len++] = '\t';
pos++;
break;
case 'e':
buf[len++] = '\033';
pos++;
break;
case 'x':
pos++;
val = hex2byte(pos);
if (val < 0) {
val = hex2num(*pos);
if (val < 0)
break;
buf[len++] = val;
pos++;
} else {
buf[len++] = val;
pos += 2;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
val = *pos++ - '0';
if (*pos >= '0' && *pos <= '7')
val = val * 8 + (*pos++ - '0');
if (*pos >= '0' && *pos <= '7')
val = val * 8 + (*pos++ - '0');
buf[len++] = val;
break;
default:
break;
}
break;
default:
buf[len++] = *pos++;
break;
}
}
if (maxlen > len)
buf[len] = '\0';
return len;
}
/**
* wpa_ssid_txt - Convert SSID to a printable string
* @ssid: SSID (32-octet string)
* @ssid_len: Length of ssid in octets
* Returns: Pointer to a printable string
*
* This function can be used to convert SSIDs into printable form. In most
* cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
* does not limit the used character set, so anything could be used in an SSID.
*
* This function uses a static buffer, so only one call can be used at the
* time, i.e., this is not re-entrant and the returned buffer must be used
* before calling this again.
*/
const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
{
static char ssid_txt[32 * 4 + 1];
if (ssid == NULL) {
ssid_txt[0] = '\0';
return ssid_txt;
}
printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
return ssid_txt;
}
void * __hide_aliasing_typecast(void *foo)
{
return foo;
}
char * wpa_config_parse_string(const char *value, size_t *len)
{
if (*value == '"') {
const char *pos;
char *str;
value++;
pos = os_strrchr(value, '"');
if (pos == NULL || pos[1] != '\0')
return NULL;
*len = pos - value;
str = dup_binstr(value, *len);
if (str == NULL)
return NULL;
return str;
} else if (*value == 'P' && value[1] == '"') {
const char *pos;
char *tstr, *str;
size_t tlen;
value += 2;
pos = os_strrchr(value, '"');
if (pos == NULL || pos[1] != '\0')
return NULL;
tlen = pos - value;
tstr = dup_binstr(value, tlen);
if (tstr == NULL)
return NULL;
str = os_malloc(tlen + 1);
if (str == NULL) {
os_free(tstr);
return NULL;
}
*len = printf_decode((u8 *) str, tlen + 1, tstr);
os_free(tstr);
return str;
} else {
u8 *str;
size_t tlen, hlen = os_strlen(value);
if (hlen & 1)
return NULL;
tlen = hlen / 2;
str = os_malloc(tlen + 1);
if (str == NULL)
return NULL;
if (hexstr2bin(value, str, tlen)) {
os_free(str);
return NULL;
}
str[tlen] = '\0';
*len = tlen;
return (char *) str;
}
}
int is_hex(const u8 *data, size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
if (data[i] < 32 || data[i] >= 127)
return 1;
}
return 0;
}
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len)
{
size_t len = 0;
os_memset(res, 0, res_len);
if (src1) {
if (src1_len >= res_len) {
os_memcpy(res, src1, res_len);
return res_len;
}
os_memcpy(res, src1, src1_len);
len += src1_len;
}
if (src2) {
if (len + src2_len >= res_len) {
os_memcpy(res + len, src2, res_len - len);
return res_len;
}
os_memcpy(res + len, src2, src2_len);
len += src2_len;
}
return len;
}
char * dup_binstr(const void *src, size_t len)
{
char *res;
if (src == NULL)
return NULL;
res = os_malloc(len + 1);
if (res == NULL)
return NULL;
os_memcpy(res, src, len);
res[len] = '\0';
return res;
}
int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value)
{
struct wpa_freq_range *freq = NULL, *n;
unsigned int count = 0;
const char *pos, *pos2, *pos3;
/*
* Comma separated list of frequency ranges.
* For example: 2412-2432,2462,5000-6000
*/
pos = value;
while (pos && pos[0]) {
n = os_realloc_array(freq, count + 1,
sizeof(struct wpa_freq_range));
if (n == NULL) {
os_free(freq);
return -1;
}
freq = n;
freq[count].min = atoi(pos);
pos2 = os_strchr(pos, '-');
pos3 = os_strchr(pos, ',');
if (pos2 && (!pos3 || pos2 < pos3)) {
pos2++;
freq[count].max = atoi(pos2);
} else
freq[count].max = freq[count].min;
pos = pos3;
if (pos)
pos++;
count++;
}
os_free(res->range);
res->range = freq;
res->num = count;
return 0;
}
int freq_range_list_includes(const struct wpa_freq_range_list *list,
unsigned int freq)
{
unsigned int i;
if (list == NULL)
return 0;
for (i = 0; i < list->num; i++) {
if (freq >= list->range[i].min && freq <= list->range[i].max)
return 1;
}
return 0;
}
char * freq_range_list_str(const struct wpa_freq_range_list *list)
{
char *buf, *pos, *end;
size_t maxlen;
unsigned int i;
int res;
if (list->num == 0)
return NULL;
maxlen = list->num * 30;
buf = os_malloc(maxlen);
if (buf == NULL)
return NULL;
pos = buf;
end = buf + maxlen;
for (i = 0; i < list->num; i++) {
struct wpa_freq_range *range = &list->range[i];
if (range->min == range->max)
res = os_snprintf(pos, end - pos, "%s%u",
i == 0 ? "" : ",", range->min);
else
res = os_snprintf(pos, end - pos, "%s%u-%u",
i == 0 ? "" : ",",
range->min, range->max);
if (os_snprintf_error(end - pos, res)) {
os_free(buf);
return NULL;
}
pos += res;
}
return buf;
}
int int_array_len(const int *a)
{
int i;
for (i = 0; a && a[i]; i++)
;
return i;
}
void int_array_concat(int **res, const int *a)
{
int reslen, alen, i;
int *n;
reslen = int_array_len(*res);
alen = int_array_len(a);
n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
if (n == NULL) {
os_free(*res);
*res = NULL;
return;
}
for (i = 0; i <= alen; i++)
n[reslen + i] = a[i];
*res = n;
}
static int freq_cmp(const void *a, const void *b)
{
int _a = *(int *) a;
int _b = *(int *) b;
if (_a == 0)
return 1;
if (_b == 0)
return -1;
return _a - _b;
}
void int_array_sort_unique(int *a)
{
int alen;
int i, j;
if (a == NULL)
return;
alen = int_array_len(a);
qsort(a, alen, sizeof(int), freq_cmp);
i = 0;
j = 1;
while (a[i] && a[j]) {
if (a[i] == a[j]) {
j++;
continue;
}
a[++i] = a[j++];
}
if (a[i])
i++;
a[i] = 0;
}
void int_array_add_unique(int **res, int a)
{
int reslen;
int *n;
for (reslen = 0; *res && (*res)[reslen]; reslen++) {
if ((*res)[reslen] == a)
return; /* already in the list */
}
n = os_realloc_array(*res, reslen + 2, sizeof(int));
if (n == NULL) {
os_free(*res);
*res = NULL;
return;
}
n[reslen] = a;
n[reslen + 1] = 0;
*res = n;
}
void str_clear_free(char *str)
{
if (str) {
size_t len = os_strlen(str);
os_memset(str, 0, len);
os_free(str);
}
}
void bin_clear_free(void *bin, size_t len)
{
if (bin) {
os_memset(bin, 0, len);
os_free(bin);
}
}
int random_mac_addr(u8 *addr)
{
if (os_get_random(addr, ETH_ALEN) < 0)
return -1;
addr[0] &= 0xfe; /* unicast */
addr[0] |= 0x02; /* locally administered */
return 0;
}
int random_mac_addr_keep_oui(u8 *addr)
{
if (os_get_random(addr + 3, 3) < 0)
return -1;
addr[0] &= 0xfe; /* unicast */
addr[0] |= 0x02; /* locally administered */
return 0;
}
/**
* str_token - Get next token from a string
* @buf: String to tokenize. Note that the string might be modified.
* @delim: String of delimiters
* @context: Pointer to save our context. Should be initialized with
* NULL on the first call, and passed for any further call.
* Returns: The next token, NULL if there are no more valid tokens.
*/
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++;
if (*end)
*end++ = '\0';
*context = end;
return pos;
}

View File

@@ -0,0 +1,329 @@
/*
* WPA Supplicant - Common definitions
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef DEFS_H
#define DEFS_H
#ifdef FALSE
#undef FALSE
#endif
#ifdef TRUE
#undef TRUE
#endif
typedef enum { FALSE = 0, TRUE = 1 } Boolean;
#define WPA_CIPHER_NONE BIT(0)
#define WPA_CIPHER_WEP40 BIT(1)
#define WPA_CIPHER_WEP104 BIT(2)
#define WPA_CIPHER_TKIP BIT(3)
#define WPA_CIPHER_CCMP BIT(4)
#define WPA_CIPHER_AES_128_CMAC BIT(5)
#define WPA_CIPHER_GCMP BIT(6)
#define WPA_CIPHER_SMS4 BIT(7)
#define WPA_CIPHER_GCMP_256 BIT(8)
#define WPA_CIPHER_CCMP_256 BIT(9)
#define WPA_CIPHER_BIP_GMAC_128 BIT(11)
#define WPA_CIPHER_BIP_GMAC_256 BIT(12)
#define WPA_CIPHER_BIP_CMAC_256 BIT(13)
#define WPA_CIPHER_GTK_NOT_USED BIT(14)
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
#define WPA_KEY_MGMT_PSK BIT(1)
#define WPA_KEY_MGMT_NONE BIT(2)
#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
#define WPA_KEY_MGMT_WPA_NONE BIT(4)
#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
#define WPA_KEY_MGMT_FT_PSK BIT(6)
#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
#define WPA_KEY_MGMT_WPS BIT(9)
#define WPA_KEY_MGMT_SAE BIT(10)
#define WPA_KEY_MGMT_FT_SAE BIT(11)
#define WPA_KEY_MGMT_WAPI_PSK BIT(12)
#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
#define WPA_KEY_MGMT_CCKM BIT(14)
#define WPA_KEY_MGMT_OSEN BIT(15)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17)
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
{
return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_CCKM |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
}
static inline int wpa_key_mgmt_wpa_psk(int akm)
{
return !!(akm & (WPA_KEY_MGMT_PSK |
WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_PSK_SHA256 |
WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_FT_SAE));
}
static inline int wpa_key_mgmt_ft(int akm)
{
return !!(akm & (WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_FT_SAE));
}
static inline int wpa_key_mgmt_sae(int akm)
{
return !!(akm & (WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_FT_SAE));
}
static inline int wpa_key_mgmt_sha256(int akm)
{
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_IEEE8021X_SUITE_B));
}
static inline int wpa_key_mgmt_sha384(int akm)
{
return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192);
}
static inline int wpa_key_mgmt_suite_b(int akm)
{
return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
}
static inline int wpa_key_mgmt_wpa(int akm)
{
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
wpa_key_mgmt_wpa_psk(akm) ||
wpa_key_mgmt_sae(akm);
}
static inline int wpa_key_mgmt_wpa_any(int akm)
{
return wpa_key_mgmt_wpa(akm) || (akm & WPA_KEY_MGMT_WPA_NONE);
}
static inline int wpa_key_mgmt_cckm(int akm)
{
return akm == WPA_KEY_MGMT_CCKM;
}
#define WPA_PROTO_WPA BIT(0)
#define WPA_PROTO_RSN BIT(1)
#define WPA_PROTO_WAPI BIT(2)
#define WPA_PROTO_OSEN BIT(3)
#define WPA_AUTH_ALG_OPEN BIT(0)
#define WPA_AUTH_ALG_SHARED BIT(1)
#define WPA_AUTH_ALG_LEAP BIT(2)
#define WPA_AUTH_ALG_FT BIT(3)
#define WPA_AUTH_ALG_SAE BIT(4)
enum wpa_alg {
WPA_ALG_NONE,
WPA_ALG_WEP,
WPA_ALG_TKIP,
WPA_ALG_CCMP,
WPA_ALG_IGTK,
WPA_ALG_PMK,
WPA_ALG_GCMP,
WPA_ALG_SMS4,
WPA_ALG_KRK,
WPA_ALG_GCMP_256,
WPA_ALG_CCMP_256,
WPA_ALG_BIP_GMAC_128,
WPA_ALG_BIP_GMAC_256,
WPA_ALG_BIP_CMAC_256
};
/**
* enum wpa_states - wpa_supplicant state
*
* These enumeration values are used to indicate the current wpa_supplicant
* state (wpa_s->wpa_state). The current state can be retrieved with
* wpa_supplicant_get_state() function and the state can be changed by calling
* wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the
* wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used
* to access the state variable.
*/
enum wpa_states {
/**
* WPA_DISCONNECTED - Disconnected state
*
* This state indicates that client is not associated, but is likely to
* start looking for an access point. This state is entered when a
* connection is lost.
*/
WPA_DISCONNECTED,
/**
* WPA_INTERFACE_DISABLED - Interface disabled
*
* This stat eis entered if the network interface is disabled, e.g.,
* due to rfkill. wpa_supplicant refuses any new operations that would
* use the radio until the interface has been enabled.
*/
WPA_INTERFACE_DISABLED,
/**
* WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
*
* This state is entered if there are no enabled networks in the
* configuration. wpa_supplicant is not trying to associate with a new
* network and external interaction (e.g., ctrl_iface call to add or
* enable a network) is needed to start association.
*/
WPA_INACTIVE,
/**
* WPA_SCANNING - Scanning for a network
*
* This state is entered when wpa_supplicant starts scanning for a
* network.
*/
WPA_SCANNING,
/**
* WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID
*
* This state is entered when wpa_supplicant has found a suitable BSS
* to authenticate with and the driver is configured to try to
* authenticate with this BSS. This state is used only with drivers
* that use wpa_supplicant as the SME.
*/
WPA_AUTHENTICATING,
/**
* WPA_ASSOCIATING - Trying to associate with a BSS/SSID
*
* This state is entered when wpa_supplicant has found a suitable BSS
* to associate with and the driver is configured to try to associate
* with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
* state is entered when the driver is configured to try to associate
* with a network using the configured SSID and security policy.
*/
WPA_ASSOCIATING,
/**
* WPA_ASSOCIATED - Association completed
*
* This state is entered when the driver reports that association has
* been successfully completed with an AP. If IEEE 802.1X is used
* (with or without WPA/WPA2), wpa_supplicant remains in this state
* until the IEEE 802.1X/EAPOL authentication has been completed.
*/
WPA_ASSOCIATED,
/**
* WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress
*
* This state is entered when WPA/WPA2 4-Way Handshake is started. In
* case of WPA-PSK, this happens when receiving the first EAPOL-Key
* frame after association. In case of WPA-EAP, this state is entered
* when the IEEE 802.1X/EAPOL authentication has been completed.
*/
WPA_4WAY_HANDSHAKE,
/**
* WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress
*
* This state is entered when 4-Way Key Handshake has been completed
* (i.e., when the supplicant sends out message 4/4) and when Group
* Key rekeying is started by the AP (i.e., when supplicant receives
* message 1/2).
*/
WPA_GROUP_HANDSHAKE,
/**
* WPA_COMPLETED - All authentication completed
*
* This state is entered when the full authentication process is
* completed. In case of WPA2, this happens when the 4-Way Handshake is
* successfully completed. With WPA, this state is entered after the
* Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
* completed after dynamic keys are received (or if not used, after
* the EAP authentication has been completed). With static WEP keys and
* plaintext connections, this state is entered when an association
* has been completed.
*
* This state indicates that the supplicant has completed its
* processing for the association phase and that data connection is
* fully configured.
*/
WPA_COMPLETED
};
#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0
#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1
#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2
#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3
#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
/**
* enum mfp_options - Management frame protection (IEEE 802.11w) options
*/
enum mfp_options {
NO_MGMT_FRAME_PROTECTION = 0,
MGMT_FRAME_PROTECTION_OPTIONAL = 1,
MGMT_FRAME_PROTECTION_REQUIRED = 2,
};
#define MGMT_FRAME_PROTECTION_DEFAULT 3
/**
* enum hostapd_hw_mode - Hardware mode
*/
enum hostapd_hw_mode {
HOSTAPD_MODE_IEEE80211B,
HOSTAPD_MODE_IEEE80211G,
HOSTAPD_MODE_IEEE80211A,
HOSTAPD_MODE_IEEE80211AD,
NUM_HOSTAPD_MODES
};
/**
* enum wpa_ctrl_req_type - Control interface request types
*/
enum wpa_ctrl_req_type {
WPA_CTRL_REQ_UNKNOWN,
WPA_CTRL_REQ_EAP_IDENTITY,
WPA_CTRL_REQ_EAP_PASSWORD,
WPA_CTRL_REQ_EAP_NEW_PASSWORD,
WPA_CTRL_REQ_EAP_PIN,
WPA_CTRL_REQ_EAP_OTP,
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
NUM_WPA_CTRL_REQS
};
/* Maximum number of EAP methods to store for EAP server user information */
#define EAP_MAX_METHODS 8
enum mesh_plink_state {
PLINK_LISTEN = 1,
PLINK_OPEN_SENT,
PLINK_OPEN_RCVD,
PLINK_CNF_RCVD,
PLINK_ESTAB,
PLINK_HOLDING,
PLINK_BLOCKED,
};
#endif /* DEFS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,442 @@
/*
* wpa_supplicant/hostapd control interface library
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_CTRL_H
#define WPA_CTRL_H
#ifdef __cplusplus
extern "C" {
#endif
/* wpa_supplicant control interface - fixed message prefixes */
/** Interactive request for identity/password/pin */
#define WPA_CTRL_REQ "CTRL-REQ-"
/** Response to identity/password/pin request */
#define WPA_CTRL_RSP "CTRL-RSP-"
/* Event messages with fixed prefix */
/** Authentication completed successfully and data connection enabled */
#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED "
/** Disconnected, data connection is not available */
#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED "
/** Association rejected during connection attempt */
#define WPA_EVENT_ASSOC_REJECT "CTRL-EVENT-ASSOC-REJECT "
/** wpa_supplicant is exiting */
#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
/** Password change was completed successfully */
#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED "
/** EAP-Request/Notification received */
#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION "
/** EAP authentication started (EAP-Request/Identity received) */
#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED "
/** EAP method proposed by the server */
#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD "
/** EAP method selected */
#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
/** EAP peer certificate from TLS */
#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT "
/** EAP peer certificate alternative subject name component from TLS */
#define WPA_EVENT_EAP_PEER_ALT "CTRL-EVENT-EAP-PEER-ALT "
/** EAP TLS certificate chain validation error */
#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
/** EAP status */
#define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS "
/** EAP authentication completed successfully */
#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
/** EAP authentication failed (EAP-Failure received) */
#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
/** Network block temporarily disabled (e.g., due to authentication failure) */
#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED "
/** Temporarily disabled network block re-enabled */
#define WPA_EVENT_REENABLED "CTRL-EVENT-SSID-REENABLED "
/** New scan started */
#define WPA_EVENT_SCAN_STARTED "CTRL-EVENT-SCAN-STARTED "
/** New scan results available */
#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
/** Scan command failed */
#define WPA_EVENT_SCAN_FAILED "CTRL-EVENT-SCAN-FAILED "
/** wpa_supplicant state change */
#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE "
/** A new BSS entry was added (followed by BSS entry id and BSSID) */
#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
/** A BSS entry was removed (followed by BSS entry id and BSSID) */
#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
/** Change in the signal level was reported by the driver */
#define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE "
/** Regulatory domain channel */
#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
/** RSN IBSS 4-way handshakes completed with specified peer */
#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
/** Notification of frequency conflict due to a concurrent operation.
*
* The indicated network is disabled and needs to be re-enabled before it can
* be used again.
*/
#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT "
/** Frequency ranges that the driver recommends to avoid */
#define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ "
/** WPS overlap detected in PBC mode */
#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
/** Available WPS AP with active PBC found in scan results */
#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC "
/** Available WPS AP with our address as authorized in scan results */
#define WPS_EVENT_AP_AVAILABLE_AUTH "WPS-AP-AVAILABLE-AUTH "
/** Available WPS AP with recently selected PIN registrar found in scan results
*/
#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN "
/** Available WPS AP found in scan results */
#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE "
/** A new credential received */
#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED "
/** M2D received */
#define WPS_EVENT_M2D "WPS-M2D "
/** WPS registration failed after M2/M2D */
#define WPS_EVENT_FAIL "WPS-FAIL "
/** WPS registration completed successfully */
#define WPS_EVENT_SUCCESS "WPS-SUCCESS "
/** WPS enrollment attempt timed out and was terminated */
#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT "
/* PBC mode was activated */
#define WPS_EVENT_ACTIVE "WPS-PBC-ACTIVE "
/* PBC mode was disabled */
#define WPS_EVENT_DISABLE "WPS-PBC-DISABLE "
#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK "
/* WPS ER events */
#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE "
#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD "
#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE "
#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS "
#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG "
/* MESH events */
#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
#define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED "
#define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED "
/* WMM AC events */
#define WMM_AC_EVENT_TSPEC_ADDED "TSPEC-ADDED "
#define WMM_AC_EVENT_TSPEC_REMOVED "TSPEC-REMOVED "
#define WMM_AC_EVENT_TSPEC_REQ_FAILED "TSPEC-REQ-FAILED "
/** P2P device found */
#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND "
/** P2P device lost */
#define P2P_EVENT_DEVICE_LOST "P2P-DEVICE-LOST "
/** A P2P device requested GO negotiation, but we were not ready to start the
* negotiation */
#define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST "
#define P2P_EVENT_GO_NEG_SUCCESS "P2P-GO-NEG-SUCCESS "
#define P2P_EVENT_GO_NEG_FAILURE "P2P-GO-NEG-FAILURE "
#define P2P_EVENT_GROUP_FORMATION_SUCCESS "P2P-GROUP-FORMATION-SUCCESS "
#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE "
#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED "
#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED "
#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE "
#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE "
/* parameters: <peer address> <PIN> */
#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN "
/* parameters: <peer address> */
#define P2P_EVENT_PROV_DISC_ENTER_PIN "P2P-PROV-DISC-ENTER-PIN "
/* parameters: <peer address> */
#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ "
/* parameters: <peer address> */
#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP "
/* parameters: <peer address> <status> */
#define P2P_EVENT_PROV_DISC_FAILURE "P2P-PROV-DISC-FAILURE"
/* parameters: <freq> <src addr> <dialog token> <update indicator> <TLVs> */
#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ "
/* parameters: <src addr> <update indicator> <TLVs> */
#define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP "
#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED "
#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT "
#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED "
#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id="
#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE "
#define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO "
#define P2P_EVENT_NFC_PEER_CLIENT "P2P-NFC-PEER-CLIENT "
#define P2P_EVENT_NFC_WHILE_CLIENT "P2P-NFC-WHILE-CLIENT "
/* parameters: <PMF enabled> <timeout in ms> <Session Information URL> */
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
#define P2P_EVENT_REMOVE_AND_REFORM_GROUP "P2P-REMOVE-AND-REFORM-GROUP "
#define INTERWORKING_AP "INTERWORKING-AP "
#define INTERWORKING_BLACKLISTED "INTERWORKING-BLACKLISTED "
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
#define INTERWORKING_ALREADY_CONNECTED "INTERWORKING-ALREADY-CONNECTED "
#define INTERWORKING_SELECTED "INTERWORKING-SELECTED "
/* Credential block added; parameters: <id> */
#define CRED_ADDED "CRED-ADDED "
/* Credential block modified; parameters: <id> <field> */
#define CRED_MODIFIED "CRED-MODIFIED "
/* Credential block removed; parameters: <id> */
#define CRED_REMOVED "CRED-REMOVED "
#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO "
/* parameters: <addr> <dialog_token> <freq> */
#define GAS_QUERY_START "GAS-QUERY-START "
/* parameters: <addr> <dialog_token> <freq> <status_code> <result> */
#define GAS_QUERY_DONE "GAS-QUERY-DONE "
/* parameters: <addr> <result> */
#define ANQP_QUERY_DONE "ANQP-QUERY-DONE "
#define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION "
#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE "
#define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START "
#define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT "
#define RRM_EVENT_NEIGHBOR_REP_RXED "RRM-NEIGHBOR-REP-RECEIVED "
#define RRM_EVENT_NEIGHBOR_REP_FAILED "RRM-NEIGHBOR-REP-REQUEST-FAILED "
/* hostapd control interface - fixed message prefixes */
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS "
#define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED "
#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED "
#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED "
#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED "
#define AP_STA_CONNECTED "AP-STA-CONNECTED "
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
#define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA "
#define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA "
#define AP_EVENT_ENABLED "AP-ENABLED "
#define AP_EVENT_DISABLED "AP-DISABLED "
#define INTERFACE_ENABLED "INTERFACE-ENABLED "
#define INTERFACE_DISABLED "INTERFACE-DISABLED "
#define ACS_EVENT_STARTED "ACS-STARTED "
#define ACS_EVENT_COMPLETED "ACS-COMPLETED "
#define ACS_EVENT_FAILED "ACS-FAILED "
#define DFS_EVENT_RADAR_DETECTED "DFS-RADAR-DETECTED "
#define DFS_EVENT_NEW_CHANNEL "DFS-NEW-CHANNEL "
#define DFS_EVENT_CAC_START "DFS-CAC-START "
#define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED "
#define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED "
#define AP_CSA_FINISHED "AP-CSA-FINISHED "
/* BSS Transition Management Response frame received */
#define BSS_TM_RESP "BSS-TM-RESP "
/* BSS command information masks */
#define WPA_BSS_MASK_ALL 0xFFFDFFFF
#define WPA_BSS_MASK_ID BIT(0)
#define WPA_BSS_MASK_BSSID BIT(1)
#define WPA_BSS_MASK_FREQ BIT(2)
#define WPA_BSS_MASK_BEACON_INT BIT(3)
#define WPA_BSS_MASK_CAPABILITIES BIT(4)
#define WPA_BSS_MASK_QUAL BIT(5)
#define WPA_BSS_MASK_NOISE BIT(6)
#define WPA_BSS_MASK_LEVEL BIT(7)
#define WPA_BSS_MASK_TSF BIT(8)
#define WPA_BSS_MASK_AGE BIT(9)
#define WPA_BSS_MASK_IE BIT(10)
#define WPA_BSS_MASK_FLAGS BIT(11)
#define WPA_BSS_MASK_SSID BIT(12)
#define WPA_BSS_MASK_WPS_SCAN BIT(13)
#define WPA_BSS_MASK_P2P_SCAN BIT(14)
#define WPA_BSS_MASK_INTERNETW BIT(15)
#define WPA_BSS_MASK_WIFI_DISPLAY BIT(16)
#define WPA_BSS_MASK_DELIM BIT(17)
#define WPA_BSS_MASK_MESH_SCAN BIT(18)
#define WPA_BSS_MASK_FST BIT(19)
/* VENDOR_ELEM_* frame id values */
enum wpa_vendor_elem_frame {
VENDOR_ELEM_PROBE_REQ_P2P = 0,
VENDOR_ELEM_PROBE_RESP_P2P = 1,
VENDOR_ELEM_PROBE_RESP_P2P_GO = 2,
VENDOR_ELEM_BEACON_P2P_GO = 3,
VENDOR_ELEM_P2P_PD_REQ = 4,
VENDOR_ELEM_P2P_PD_RESP = 5,
VENDOR_ELEM_P2P_GO_NEG_REQ = 6,
VENDOR_ELEM_P2P_GO_NEG_RESP = 7,
VENDOR_ELEM_P2P_GO_NEG_CONF = 8,
VENDOR_ELEM_P2P_INV_REQ = 9,
VENDOR_ELEM_P2P_INV_RESP = 10,
VENDOR_ELEM_P2P_ASSOC_REQ = 11,
VENDOR_ELEM_P2P_ASSOC_RESP = 12,
VENDOR_ELEM_ASSOC_REQ = 13,
NUM_VENDOR_ELEM_FRAMES
};
/* wpa_supplicant/hostapd control interface access */
/**
* wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd
* @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
* Returns: Pointer to abstract control interface data or %NULL on failure
*
* This function is used to open a control interface to wpa_supplicant/hostapd.
* ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path
* is configured in wpa_supplicant/hostapd and other programs using the control
* interface need to use matching path configuration.
*/
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
/**
* wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd
* @ctrl: Control interface data from wpa_ctrl_open()
*
* This function is used to close a control interface.
*/
void wpa_ctrl_close(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_request - Send a command to wpa_supplicant/hostapd
* @ctrl: Control interface data from wpa_ctrl_open()
* @cmd: Command; usually, ASCII text, e.g., "PING"
* @cmd_len: Length of the cmd in bytes
* @reply: Buffer for the response
* @reply_len: Reply buffer length
* @msg_cb: Callback function for unsolicited messages or %NULL if not used
* Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
*
* This function is used to send commands to wpa_supplicant/hostapd. Received
* response will be written to reply and reply_len is set to the actual length
* of the reply. This function will block for up to two seconds while waiting
* for the reply. If unsolicited messages are received, the blocking time may
* be longer.
*
* msg_cb can be used to register a callback function that will be called for
* unsolicited messages received while waiting for the command response. These
* messages may be received if wpa_ctrl_request() is called at the same time as
* wpa_supplicant/hostapd is sending such a message. This can happen only if
* the program has used wpa_ctrl_attach() to register itself as a monitor for
* event messages. Alternatively to msg_cb, programs can register two control
* interface connections and use one of them for commands and the other one for
* receiving event messages, in other words, call wpa_ctrl_attach() only for
* the control interface connection that will be used for event messages.
*/
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len));
/**
* wpa_ctrl_attach - Register as an event monitor for the control interface
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: 0 on success, -1 on failure, -2 on timeout
*
* This function registers the control interface connection as a monitor for
* wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the
* control interface connection starts receiving event messages that can be
* read with wpa_ctrl_recv().
*/
int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_detach - Unregister event monitor from the control interface
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: 0 on success, -1 on failure, -2 on timeout
*
* This function unregisters the control interface connection as a monitor for
* wpa_supplicant/hostapd events, i.e., cancels the registration done with
* wpa_ctrl_attach().
*/
int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_recv - Receive a pending control interface message
* @ctrl: Control interface data from wpa_ctrl_open()
* @reply: Buffer for the message data
* @reply_len: Length of the reply buffer
* Returns: 0 on success, -1 on failure
*
* This function will receive a pending control interface message. The received
* response will be written to reply and reply_len is set to the actual length
* of the reply.
* wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
* must have been used to register the control interface as an event monitor.
*/
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
/**
* wpa_ctrl_pending - Check whether there are pending event messages
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: 1 if there are pending messages, 0 if no, or -1 on error
*
* This function will check whether there are any pending control interface
* message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is
* only used for event messages, i.e., wpa_ctrl_attach() must have been used to
* register the control interface as an event monitor.
*/
int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_get_fd - Get file descriptor used by the control interface
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: File descriptor used for the connection
*
* This function can be used to get the file descriptor that is used for the
* control interface connection. The returned value can be used, e.g., with
* select() while waiting for multiple events.
*
* The returned file descriptor must not be used directly for sending or
* receiving packets; instead, the library functions wpa_ctrl_request() and
* wpa_ctrl_recv() must be used for this.
*/
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
#ifdef ANDROID
/**
* wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
* may be left over from clients that were previously connected to
* wpa_supplicant. This keeps these files from being orphaned in the
* event of crashes that prevented them from being removed as part
* of the normal orderly shutdown.
*/
void wpa_ctrl_cleanup(void);
#endif /* ANDROID */
#ifdef CONFIG_CTRL_IFACE_UDP
/* Port range for multiple wpa_supplicant instances and multiple VIFs */
#define WPA_CTRL_IFACE_PORT 9877
#define WPA_CTRL_IFACE_PORT_LIMIT 50 /* decremented from start */
#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
#define WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT 20 /* incremented from start */
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
#endif /* CONFIG_CTRL_IFACE_UDP */
#ifdef __cplusplus
}
#endif
#endif /* WPA_CTRL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/*
* FST module - miscellaneous definitions
* Copyright (c) 2014, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef FST_MISC_H
#define FST_MISC_H
#include "common/defs.h"
/* FST module control interface API */
#define FST_INVALID_SESSION_ID ((u32)-1)
#define FST_MAX_GROUP_ID_SIZE 32
#define FST_MAX_INTERFACE_SIZE 32
enum fst_session_state {
FST_SESSION_STATE_INITIAL,
FST_SESSION_STATE_SETUP_COMPLETION,
FST_SESSION_STATE_TRANSITION_DONE,
FST_SESSION_STATE_TRANSITION_CONFIRMED,
FST_SESSION_STATE_LAST
};
enum fst_event_type {
EVENT_FST_IFACE_STATE_CHANGED, /* An interface has been either attached
* to or detached from an FST group */
EVENT_FST_ESTABLISHED, /* FST Session has been established */
EVENT_FST_SETUP, /* FST Session request received */
EVENT_FST_SESSION_STATE_CHANGED,/* FST Session state has been changed */
EVENT_PEER_STATE_CHANGED, /* FST related generic event occurred,
* see struct fst_hostap_event_data for
* more info */
/* FST Manager internal events */
EVENT_FST_SCAN_STARTED = 100,
EVENT_FST_SCAN_COMPLETED,
EVENT_FST_SIGNAL_CHANGE,
};
enum fst_reason {
REASON_TEARDOWN,
REASON_SETUP,
REASON_SWITCH,
REASON_STT,
REASON_REJECT,
REASON_ERROR_PARAMS,
REASON_RESET,
REASON_DETACH_IFACE,
};
enum fst_initiator {
FST_INITIATOR_UNDEFINED,
FST_INITIATOR_LOCAL,
FST_INITIATOR_REMOTE,
};
union fst_event_extra {
struct fst_event_extra_iface_state {
Boolean attached;
char ifname[FST_MAX_INTERFACE_SIZE];
char group_id[FST_MAX_GROUP_ID_SIZE];
} iface_state; /* for EVENT_FST_IFACE_STATE_CHANGED */
struct fst_event_extra_peer_state {
Boolean connected;
char ifname[FST_MAX_INTERFACE_SIZE];
u8 addr[ETH_ALEN];
} peer_state; /* for EVENT_PEER_STATE_CHANGED */
struct fst_event_extra_session_state {
enum fst_session_state old_state;
enum fst_session_state new_state;
union fst_session_state_switch_extra {
struct {
enum fst_reason reason;
u8 reject_code; /* REASON_REJECT */
/* REASON_SWITCH,
* REASON_TEARDOWN,
* REASON_REJECT
*/
enum fst_initiator initiator;
} to_initial;
} extra;
} session_state; /* for EVENT_FST_SESSION_STATE_CHANGED */
};
/* helpers - prints enum in string form */
#define FST_NAME_UNKNOWN "UNKNOWN"
const char *_fst_get_str_name(unsigned index, const char *names[],
size_t names_size);
int _fst_get_str_num(const char *name, const char *names[],
size_t names_size);
const char *fst_session_event_type_name(enum fst_event_type);
const char *fst_reason_name(enum fst_reason reason);
const char *fst_session_state_name(enum fst_session_state state);
int fst_session_event_num(const char *name);
int fst_reason_num(const char *name);
int fst_session_state_num(const char *name);
#endif /* FST_MISC_H */

View File

@@ -0,0 +1,229 @@
/*
* FST module - shared Control interface definitions
* Copyright (c) 2014, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef FST_CTRL_DEFS_H
#define FST_CTRL_DEFS_H
/* Undefined value */
#define FST_CTRL_PVAL_NONE "NONE"
/* FST-ATTACH parameters */
#define FST_ATTACH_CMD_PNAME_LLT "llt" /* pval = desired LLT */
#define FST_ATTACH_CMD_PNAME_PRIORITY "priority" /* pval = desired priority */
/* FST-MANAGER parameters */
/* FST Session states */
#define FST_CS_PVAL_STATE_INITIAL "INITIAL"
#define FST_CS_PVAL_STATE_SETUP_COMPLETION "SETUP_COMPLETION"
#define FST_CS_PVAL_STATE_TRANSITION_DONE "TRANSITION_DONE"
#define FST_CS_PVAL_STATE_TRANSITION_CONFIRMED "TRANSITION_CONFIRMED"
/* FST Session reset reasons */
#define FST_CS_PVAL_REASON_TEARDOWN "REASON_TEARDOWN"
#define FST_CS_PVAL_REASON_SETUP "REASON_SETUP"
#define FST_CS_PVAL_REASON_SWITCH "REASON_SWITCH"
#define FST_CS_PVAL_REASON_STT "REASON_STT"
#define FST_CS_PVAL_REASON_REJECT "REASON_REJECT"
#define FST_CS_PVAL_REASON_ERROR_PARAMS "REASON_ERROR_PARAMS"
#define FST_CS_PVAL_REASON_RESET "REASON_RESET"
#define FST_CS_PVAL_REASON_DETACH_IFACE "REASON_DETACH_IFACE"
/* FST Session responses */
#define FST_CS_PVAL_RESPONSE_ACCEPT "ACCEPT"
#define FST_CS_PVAL_RESPONSE_REJECT "REJECT"
/* FST Session action initiator */
#define FST_CS_PVAL_INITIATOR_LOCAL "LOCAL"
#define FST_CS_PVAL_INITIATOR_REMOTE "REMOTE"
/* FST-CLI subcommands and parameter names */
#define FST_CMD_HELP "help"
#define FST_CMD_LIST_GROUPS "list_groups"
#define FST_CMD_LIST_IFACES "list_ifaces"
#define FST_CMD_IFACE_PEERS "iface_peers"
#define FST_CMD_GET_PEER_MBIES "get_peer_mbies"
#define FST_CMD_LIST_SESSIONS "list_sessions"
#define FST_CMD_SESSION_ADD "session_add"
#define FST_CMD_SESSION_REMOVE "session_remove"
#define FST_CMD_SESSION_GET "session_get"
#define FST_CSG_PNAME_OLD_PEER_ADDR "old_peer_addr" /* pval = address string */
#define FST_CSG_PNAME_NEW_PEER_ADDR "new_peer_addr" /* pval = address string */
#define FST_CSG_PNAME_OLD_IFNAME "old_ifname" /* pval = ifname */
#define FST_CSG_PNAME_NEW_IFNAME "new_ifname" /* pval = ifname */
#define FST_CSG_PNAME_LLT "llt" /* pval = numeric llt value */
#define FST_CSG_PNAME_STATE "state" /* pval = FST_CS_PVAL_STATE_... */
#define FST_CMD_SESSION_SET "session_set"
#define FST_CSS_PNAME_OLD_PEER_ADDR FST_CSG_PNAME_OLD_PEER_ADDR
#define FST_CSS_PNAME_NEW_PEER_ADDR FST_CSG_PNAME_NEW_PEER_ADDR
#define FST_CSS_PNAME_OLD_IFNAME FST_CSG_PNAME_OLD_IFNAME
#define FST_CSS_PNAME_NEW_IFNAME FST_CSG_PNAME_NEW_IFNAME
#define FST_CSS_PNAME_LLT FST_CSG_PNAME_LLT
#define FST_CMD_SESSION_INITIATE "session_initiate"
#define FST_CMD_SESSION_RESPOND "session_respond"
#define FST_CMD_SESSION_TRANSFER "session_transfer"
#define FST_CMD_SESSION_TEARDOWN "session_teardown"
#ifdef CONFIG_FST_TEST
#define FST_CTR_PVAL_BAD_NEW_BAND "bad_new_band"
#define FST_CMD_TEST_REQUEST "test_request"
#define FST_CTR_IS_SUPPORTED "is_supported"
#define FST_CTR_SEND_SETUP_REQUEST "send_setup_request"
#define FST_CTR_SEND_SETUP_RESPONSE "send_setup_response"
#define FST_CTR_SEND_ACK_REQUEST "send_ack_request"
#define FST_CTR_SEND_ACK_RESPONSE "send_ack_response"
#define FST_CTR_SEND_TEAR_DOWN "send_tear_down"
#define FST_CTR_GET_FSTS_ID "get_fsts_id"
#define FST_CTR_GET_LOCAL_MBIES "get_local_mbies"
#endif
/* Events */
#define FST_CTRL_EVENT_IFACE "FST-EVENT-IFACE"
#define FST_CEI_PNAME_IFNAME "ifname"
#define FST_CEI_PNAME_GROUP "group"
#define FST_CEI_PNAME_ATTACHED "attached"
#define FST_CEI_PNAME_DETACHED "detached"
#define FST_CTRL_EVENT_PEER "FST-EVENT-PEER"
#define FST_CEP_PNAME_IFNAME "ifname"
#define FST_CEP_PNAME_ADDR "peer_addr"
#define FST_CEP_PNAME_CONNECTED "connected"
#define FST_CEP_PNAME_DISCONNECTED "disconnected"
#define FST_CTRL_EVENT_SESSION "FST-EVENT-SESSION"
#define FST_CES_PNAME_SESSION_ID "session_id"
#define FST_CES_PNAME_EVT_TYPE "event_type"
#define FST_PVAL_EVT_TYPE_SESSION_STATE "EVENT_FST_SESSION_STATE"
/* old_state/new_state: pval = FST_CS_PVAL_STATE_... */
#define FST_CES_PNAME_OLD_STATE "old_state"
#define FST_CES_PNAME_NEW_STATE "new_state"
#define FST_CES_PNAME_REASON "reason" /* pval = FST_CS_PVAL_REASON_... */
#define FST_CES_PNAME_REJECT_CODE "reject_code" /* pval = u8 code */
#define FST_CES_PNAME_INITIATOR "initiator" /* pval = FST_CS_PVAL_INITIATOR_... */
#define FST_PVAL_EVT_TYPE_ESTABLISHED "EVENT_FST_ESTABLISHED"
#define FST_PVAL_EVT_TYPE_SETUP "EVENT_FST_SETUP"
#ifdef CONFIG_DBUS
#define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1"
#define WPAS_DBUS_NEW_PATH "/fi/w1/wpa_supplicant1"
#define WPAS_DBUS_NEW_INTERFACE "fi.w1.wpa_supplicant1"
#define WPAS_DBUS_NEW_PATH_INTERFACES WPAS_DBUS_NEW_PATH "/Interfaces"
#define WPAS_DBUS_NEW_IFACE_INTERFACE WPAS_DBUS_NEW_INTERFACE ".Interface"
#define WPAS_DBUS_NEW_IFACE_WPS WPAS_DBUS_NEW_IFACE_INTERFACE ".WPS"
#define WPAS_DBUS_NEW_PATH_FST WPAS_DBUS_NEW_PATH "/FST"
#define WPAS_DBUS_NEW_IFACE_FST WPAS_DBUS_NEW_INTERFACE ".FST"
#define WPAS_DBUS_NEW_FST_GROUPS_PART "Groups"
#define WPAS_DBUS_NEW_IFACE_FST_GROUP WPAS_DBUS_NEW_IFACE_FST ".Group"
#define WPAS_DBUS_NEW_FST_INTERFACES_PART "Interfaces"
#define WPAS_DBUS_NEW_IFACE_FST_INTERFACE WPAS_DBUS_NEW_IFACE_FST ".Interface"
#define WPAS_DBUS_NEW_FST_SESSIONS_PART "Sessions"
#define WPAS_DBUS_NEW_IFACE_FST_SESSION WPAS_DBUS_NEW_IFACE_FST ".Session"
/*
* Global FST properties, methods and signals
*/
#define FST_DBUS_GLOBAL_PROP_GROUPS "Groups"
#define FST_DBUS_GLOBAL_PROP_SESSIONS "Sessions"
/* Session state change to INITIAL specific fields */
#define FST_DBUS_SIG_SSTATE_PNAME_INIT_REASON "init_reason"
#define FST_DBUS_SIG_SSTATE_PNAME_INIT_REJECT_CODE "reject_code"
#define FST_DBUS_SIG_SSTATE_PNAME_INIT_INITIATOR "initiator"
#define FST_DBUS_GLOBAL_SIG "Global"
#define FST_DBUS_GLOBAL_SIG_PARAM_PATH "path"
#define FST_DBUS_GLOBAL_SIG_PARAM_EVENT "event"
#define FST_DBUS_GLOBAL_SIG_PARAM_PARAMS "params"
#define FST_DBUS_GLOBAL_SIG_SALL_PNAME_SESSION_ID "session_id"
#define FST_DBUS_GLOBAL_SIG_EVT_SESSION_SETUP "SessionSetup"
#define FST_DBUS_GLOBAL_SIG_EVT_SESSION_STATE "SessionState"
#define FST_DBUS_GLOBAL_SIG_SSTATE_PNAME_OLD_STATE "old_state"
#define FST_DBUS_GLOBAL_SIG_SSTATE_PNAME_NEW_STATE "new_state"
#define FST_DBUS_GLOBAL_SIG_SSTATE_PNAME_INIT_REASON \
FST_DBUS_SIG_SSTATE_PNAME_INIT_REASON
#define FST_DBUS_GLOBAL_SIG_SSTATE_PNAME_INIT_REJECT_CODE \
FST_DBUS_SIG_SSTATE_PNAME_INIT_REJECT_CODE
#define FST_DBUS_GLOBAL_SIG_SSTATE_PNAME_INIT_INITIATOR \
FST_DBUS_SIG_SSTATE_PNAME_INIT_INITIATOR
#define FST_DBUS_GLOBAL_SIG_EVT_SESSION_ESTAB "SessionEstablished"
#define FST_DBUS_GLOBAL_SIG_EVT_IFACE_PEER_STATE "InterfacePeerState"
#define FST_DBUS_GLOBAL_SIG_PNAME_IFNAME "path"
#define FST_DBUS_GLOBAL_SIG_PNAME_CONNECTED "connected"
#define FST_DBUS_GLOBAL_SIG_PNAME_PEER_ADDR "peer_addr"
/*
* Group FST properties, methods and signals
*/
#define FST_DBUS_GROUP_PROP_SESSIONS "Sessions"
#define FST_DBUS_GROUP_PROP_IFACES "Interfaces"
#define FST_DBUS_GROUP_MTHD_ADD_SESSION "AddSession"
#define FST_DBUS_GROUP_MTHD_ADD_SESSION_ID_PARAM "session_id"
#define FST_DBUS_GROUP_SIG_SESSION_SETUP "Setup"
#define FST_DBUS_GROUP_SIG_SSESSION_PARAM_PATH "path"
/*
* Session FST properties, methods and signals
*/
#define FST_DBUS_SESSION_SIG_STATE "State"
#define FST_DBUS_SESSION_SIG_PARAM_OLD_STATE "old_state"
#define FST_DBUS_SESSION_SIG_PARAM_NEW_STATE "new_state"
#define FST_DBUS_SESSION_SIG_PARAM_PARAMS "params"
#define FST_DBUS_SESSION_SIG_PNAME_REASON \
FST_DBUS_SIG_SSTATE_PNAME_INIT_REASON
#define FST_DBUS_SESSION_SIG_PNAME_REJECT_CODE \
FST_DBUS_SIG_SSTATE_PNAME_INIT_REJECT_CODE
#define FST_DBUS_SESSION_SIG_PNAME_INITIATOR \
FST_DBUS_SIG_SSTATE_PNAME_INIT_INITIATOR
#define FST_DBUS_SESSION_SIG_ESTABLISHED "Established"
#define FST_DBUS_SESSION_MTHD_SET "Set"
#define FST_DBUS_SESSION_MTHD_SET_PNAME_PNAME "pname"
#define FST_DBUS_SESSION_MTHD_SET_PNAME_PVAL "pvalue"
#define FST_DBUS_SESSION_MTHD_INITIATE "Initiate"
#define FST_DBUS_SESSION_MTHD_RESPOND "Respond"
#define FST_DBUS_SESSION_MTHD_RESPOND_PNAME_STATUS "respond_status"
#define FST_DBUS_SESSION_MTHD_TRANSFER "Transfer"
#define FST_DBUS_SESSION_MTHD_TEARDOWN "TearDown"
#define FST_DBUS_SESSION_MTHD_REMOVE "Remove"
#define FST_DBUS_SESSION_PROP_GROUP "Group"
#define FST_DBUS_SESSION_PROP_ID "ID"
#define FST_DBUS_SESSION_PROP_STATE "State"
#define FST_DBUS_SESSION_PROP_OLD_IFACE "OldInterface"
#define FST_DBUS_SESSION_PROP_NEW_IFACE "NewInterface"
#define FST_DBUS_SESSION_PROP_OWN_ADDR "OwnAddress"
#define FST_DBUS_SESSION_PROP_PEER_ADDR "PeerAddress"
#define FST_DBUS_SESSION_PROP_LLT "LLT"
/*
* Interface FST properties, methods and signals
*/
#define FST_DBUS_IFACE_PROP_GROUP_ID "GroupID"
#define FST_DBUS_IFACE_PROP_PRIORITY "Priority"
#define FST_DBUS_IFACE_PROP_LLT "LLT"
#define FST_DBUS_IFACE_PROP_PEER_ADDR "PeerAddress"
#define FST_DBUS_IFACE_PROP_PEER_MBIEs "PeerMBIEs"
#define FST_DBUS_IFACE_SIG_PEER_STATE "PeerState"
#define FST_DBUS_IFACE_SIG_PNAME_CONNECTED "connected"
#define FST_DBUS_IFACE_SIG_PNAME_PEER_ADDR "peer_addr"
#endif
#endif /* FST_CTRL_DEFS_H */

View File

@@ -0,0 +1,92 @@
/*
* FST module implementation
* Copyright (c) 2014, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "common/defs.h"
#include "fst_ctrl_defs.h"
#include "fst_ctrl_aux.h"
static const char *session_event_names[] = {
[EVENT_FST_ESTABLISHED] = FST_PVAL_EVT_TYPE_ESTABLISHED,
[EVENT_FST_SETUP] = FST_PVAL_EVT_TYPE_SETUP,
[EVENT_FST_SESSION_STATE_CHANGED] = FST_PVAL_EVT_TYPE_SESSION_STATE,
};
static const char *reason_names[] = {
[REASON_TEARDOWN] = FST_CS_PVAL_REASON_TEARDOWN,
[REASON_SETUP] = FST_CS_PVAL_REASON_SETUP,
[REASON_SWITCH] = FST_CS_PVAL_REASON_SWITCH,
[REASON_STT] = FST_CS_PVAL_REASON_STT,
[REASON_REJECT] = FST_CS_PVAL_REASON_REJECT,
[REASON_ERROR_PARAMS] = FST_CS_PVAL_REASON_ERROR_PARAMS,
[REASON_RESET] = FST_CS_PVAL_REASON_RESET,
[REASON_DETACH_IFACE] = FST_CS_PVAL_REASON_DETACH_IFACE,
};
static const char *session_state_names[] = {
[FST_SESSION_STATE_INITIAL] = FST_CS_PVAL_STATE_INITIAL,
[FST_SESSION_STATE_SETUP_COMPLETION] = FST_CS_PVAL_STATE_SETUP_COMPLETION,
[FST_SESSION_STATE_TRANSITION_DONE] = FST_CS_PVAL_STATE_TRANSITION_DONE,
[FST_SESSION_STATE_TRANSITION_CONFIRMED] = FST_CS_PVAL_STATE_TRANSITION_CONFIRMED,
};
/* helpers */
const char *_fst_get_str_name(unsigned index, const char *names[],
size_t names_size)
{
if (index >= names_size || !names[index])
return FST_NAME_UNKNOWN;
return names[index];
}
int _fst_get_str_num(const char *name, const char *names[],
size_t names_size)
{
unsigned i;
for (i = 0; i < names_size; i++)
if (names[i] && !strncmp(name, names[i], strlen(names[i])))
return i;
return -1;
}
const char *fst_session_event_type_name(enum fst_event_type event)
{
return _fst_get_str_name(event, session_event_names,
ARRAY_SIZE(session_event_names));
}
int fst_session_event_num(const char *name)
{
return _fst_get_str_num(name, session_event_names,
ARRAY_SIZE(session_event_names));
}
const char *fst_reason_name(enum fst_reason reason)
{
return _fst_get_str_name(reason, reason_names, ARRAY_SIZE(reason_names));
}
int fst_reason_num(const char *name)
{
return _fst_get_str_num(name, reason_names, ARRAY_SIZE(reason_names));
}
const char *fst_session_state_name(enum fst_session_state state)
{
return _fst_get_str_name(state, session_state_names,
ARRAY_SIZE(session_state_names));
}
int fst_session_state_num(const char *name)
{
return _fst_get_str_num(name, session_state_names,
ARRAY_SIZE(session_state_names));
}

View File

@@ -0,0 +1,27 @@
The "inih" library is distributed under the New BSD license:
Copyright (c) 2009, Ben Hoyt
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Ben Hoyt nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,179 @@
/* inih -- simple .INI file parser
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
https://github.com/benhoyt/inih
*/
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "ini.h"
#include "utils/includes.h"
#include "utils/common.h"
#if !INI_USE_STACK
#include <stdlib.h>
#endif
#define MAX_SECTION 50
#define MAX_NAME 50
/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s)
{
char* p = s + strlen(s);
while (p > s && isspace((unsigned char)(*--p)))
*p = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s)
{
while (*s && isspace((unsigned char)(*s)))
s++;
return (char*)s;
}
/* Return pointer to first char c or ';' comment in given string, or pointer to
null at end of string if neither found. ';' must be prefixed by a whitespace
character to register as a comment. */
static char* find_char_or_comment(const char* s, char c)
{
int was_whitespace = 0;
while (*s && *s != c && !(was_whitespace && *s == ';')) {
was_whitespace = isspace((unsigned char)(*s));
s++;
}
return (char*)s;
}
/* See documentation in header file. */
int ini_parse_file(FILE* file,
int (*handler)(void*, const char*, const char*,
const char*),
void* user)
{
/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
char line[INI_MAX_LINE];
#else
char* line;
#endif
char section[MAX_SECTION] = "";
char prev_name[MAX_NAME] = "";
char* start;
char* end;
char* name;
char* value;
int lineno = 0;
int error = 0;
#if !INI_USE_STACK
line = (char*)malloc(INI_MAX_LINE);
if (!line) {
return -2;
}
#endif
/* Scan through file line by line */
while (fgets(line, INI_MAX_LINE, file) != NULL) {
lineno++;
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
(unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
start += 3;
}
#endif
start = lskip(rstrip(start));
if (*start == ';' || *start == '#') {
/* Per Python ConfigParser, allow '#' comments at start of line */
}
#if INI_ALLOW_MULTILINE
else if (*prev_name && *start && start > line) {
/* Non-black line with leading whitespace, treat as continuation
of previous name's value (as per Python ConfigParser). */
if (!handler(user, section, prev_name, start) && !error)
error = lineno;
}
#endif
else if (*start == '[') {
/* A "[section]" line */
end = find_char_or_comment(start + 1, ']');
if (*end == ']') {
*end = '\0';
os_strlcpy(section, start + 1, sizeof(section));
*prev_name = '\0';
}
else if (!error) {
/* No ']' found on section line */
error = lineno;
}
}
else if (*start && *start != ';') {
/* Not a comment, must be a name[=:]value pair */
end = find_char_or_comment(start, '=');
if (*end != '=') {
end = find_char_or_comment(start, ':');
}
if (*end == '=' || *end == ':') {
*end = '\0';
name = rstrip(start);
value = lskip(end + 1);
end = find_char_or_comment(value, '\0');
if (*end == ';')
*end = '\0';
rstrip(value);
/* Valid name[=:]value pair found, call handler */
os_strlcpy(prev_name, name, sizeof(prev_name));
if (!handler(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
/* No '=' or ':' found on name[=:]value line */
error = lineno;
}
}
#if INI_STOP_ON_FIRST_ERROR
if (error)
break;
#endif
}
#if !INI_USE_STACK
free(line);
#endif
return error;
}
/* See documentation in header file. */
int ini_parse(const char* filename,
int (*handler)(void*, const char*, const char*, const char*),
void* user)
{
FILE* file;
int error;
file = fopen(filename, "r");
if (!file)
return -1;
error = ini_parse_file(file, handler, user);
fclose(file);
return error;
}

View File

@@ -0,0 +1,77 @@
/* inih -- simple .INI file parser
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
https://github.com/benhoyt/inih
*/
#ifndef __INI_H__
#define __INI_H__
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's ConfigParser.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
ConfigParser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed. */
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 1
#endif
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file. See http://code.google.com/p/inih/issues/detail?id=21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
#endif
/* Nonzero to use stack, zero to use heap (malloc/free). */
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
#endif
/* Stop parsing on first error (default is to keep parsing). */
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 0
#endif
/* Maximum line length for any line in INI file. */
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 200
#endif
#ifdef __cplusplus
}
#endif
#endif /* __INI_H__ */

View File

@@ -0,0 +1,707 @@
/*
* OS specific functions for UNIX/POSIX systems
* Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include <time.h>
#include <sys/wait.h>
#ifdef ANDROID
#include <sys/capability.h>
#include <sys/prctl.h>
#include <cutils/android_filesystem_config.h>
#endif /* ANDROID */
#include "os.h"
#include "common.h"
#ifdef WPA_TRACE
#include "wpa_debug.h"
#include "trace.h"
#include "list.h"
static struct dl_list alloc_list;
#define ALLOC_MAGIC 0xa84ef1b2
#define FREED_MAGIC 0x67fd487a
struct os_alloc_trace {
unsigned int magic;
struct dl_list list;
size_t len;
WPA_TRACE_INFO
};
#endif /* WPA_TRACE */
void os_sleep(os_time_t sec, os_time_t usec)
{
if (sec)
sleep(sec);
if (usec)
usleep(usec);
}
int os_get_time(struct os_time *t)
{
int res;
struct timeval tv = {};
res = gettimeofday(&tv, NULL);
t->sec = tv.tv_sec;
t->usec = tv.tv_usec;
return res;
}
int os_get_reltime(struct os_reltime *t)
{
#if defined(CLOCK_BOOTTIME)
static clockid_t clock_id = CLOCK_BOOTTIME;
#elif defined(CLOCK_MONOTONIC)
static clockid_t clock_id = CLOCK_MONOTONIC;
#else
static clockid_t clock_id = CLOCK_REALTIME;
#endif
struct timespec ts;
int res;
while (1) {
res = clock_gettime(clock_id, &ts);
if (res == 0) {
t->sec = ts.tv_sec;
t->usec = ts.tv_nsec / 1000;
return 0;
}
switch (clock_id) {
#ifdef CLOCK_BOOTTIME
case CLOCK_BOOTTIME:
clock_id = CLOCK_MONOTONIC;
break;
#endif
#ifdef CLOCK_MONOTONIC
case CLOCK_MONOTONIC:
clock_id = CLOCK_REALTIME;
break;
#endif
case CLOCK_REALTIME:
return -1;
}
}
}
int os_mktime(int year, int month, int day, int hour, int min, int sec,
os_time_t *t)
{
struct tm tm, *tm1;
time_t t_local, t1, t2;
os_time_t tz_offset;
if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
sec > 60)
return -1;
memset(&tm, 0, sizeof(tm));
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = min;
tm.tm_sec = sec;
t_local = mktime(&tm);
/* figure out offset to UTC */
tm1 = localtime(&t_local);
if (tm1) {
t1 = mktime(tm1);
tm1 = gmtime(&t_local);
if (tm1) {
t2 = mktime(tm1);
tz_offset = t2 - t1;
} else
tz_offset = 0;
} else
tz_offset = 0;
*t = (os_time_t) t_local - tz_offset;
return 0;
}
int os_gmtime(os_time_t t, struct os_tm *tm)
{
struct tm *tm2;
time_t t2 = t;
tm2 = gmtime(&t2);
if (tm2 == NULL)
return -1;
tm->sec = tm2->tm_sec;
tm->min = tm2->tm_min;
tm->hour = tm2->tm_hour;
tm->day = tm2->tm_mday;
tm->month = tm2->tm_mon + 1;
tm->year = tm2->tm_year + 1900;
return 0;
}
#ifdef __APPLE__
#include <fcntl.h>
static int os_daemon(int nochdir, int noclose)
{
int devnull;
if (chdir("/") < 0)
return -1;
devnull = open("/dev/null", O_RDWR);
if (devnull < 0)
return -1;
if (dup2(devnull, STDIN_FILENO) < 0) {
close(devnull);
return -1;
}
if (dup2(devnull, STDOUT_FILENO) < 0) {
close(devnull);
return -1;
}
if (dup2(devnull, STDERR_FILENO) < 0) {
close(devnull);
return -1;
}
return 0;
}
#else /* __APPLE__ */
#define os_daemon daemon
#endif /* __APPLE__ */
int os_daemonize(const char *pid_file)
{
#if defined(__uClinux__) || defined(__sun__)
return -1;
#else /* defined(__uClinux__) || defined(__sun__) */
if (os_daemon(0, 0)) {
perror("daemon");
return -1;
}
if (pid_file) {
FILE *f = fopen(pid_file, "w");
if (f) {
fprintf(f, "%u\n", getpid());
fclose(f);
}
}
return -0;
#endif /* defined(__uClinux__) || defined(__sun__) */
}
void os_daemonize_terminate(const char *pid_file)
{
if (pid_file)
unlink(pid_file);
}
int os_get_random(unsigned char *buf, size_t len)
{
FILE *f;
size_t rc;
f = fopen("/dev/urandom", "rb");
if (f == NULL) {
printf("Could not open /dev/urandom.\n");
return -1;
}
rc = fread(buf, 1, len, f);
fclose(f);
return rc != len ? -1 : 0;
}
unsigned long os_random(void)
{
return random();
}
char * os_rel2abs_path(const char *rel_path)
{
char *buf = NULL, *cwd, *ret;
size_t len = 128, cwd_len, rel_len, ret_len;
int last_errno;
if (!rel_path)
return NULL;
if (rel_path[0] == '/')
return os_strdup(rel_path);
for (;;) {
buf = os_malloc(len);
if (buf == NULL)
return NULL;
cwd = getcwd(buf, len);
if (cwd == NULL) {
last_errno = errno;
os_free(buf);
if (last_errno != ERANGE)
return NULL;
len *= 2;
if (len > 2000)
return NULL;
} else {
buf[len - 1] = '\0';
break;
}
}
cwd_len = os_strlen(cwd);
rel_len = os_strlen(rel_path);
ret_len = cwd_len + 1 + rel_len + 1;
ret = os_malloc(ret_len);
if (ret) {
os_memcpy(ret, cwd, cwd_len);
ret[cwd_len] = '/';
os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
ret[ret_len - 1] = '\0';
}
os_free(buf);
return ret;
}
int os_program_init(void)
{
#ifdef ANDROID
/*
* We ignore errors here since errors are normal if we
* are already running as non-root.
*/
#ifdef ANDROID_SETGROUPS_OVERRIDE
gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
#else /* ANDROID_SETGROUPS_OVERRIDE */
gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
#endif /* ANDROID_SETGROUPS_OVERRIDE */
struct __user_cap_header_struct header;
struct __user_cap_data_struct cap;
setgroups(ARRAY_SIZE(groups), groups);
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
setgid(AID_WIFI);
setuid(AID_WIFI);
header.version = _LINUX_CAPABILITY_VERSION;
header.pid = 0;
cap.effective = cap.permitted =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
cap.inheritable = 0;
capset(&header, &cap);
#endif /* ANDROID */
#ifdef WPA_TRACE
dl_list_init(&alloc_list);
#endif /* WPA_TRACE */
return 0;
}
void os_program_deinit(void)
{
#ifdef WPA_TRACE
struct os_alloc_trace *a;
unsigned long total = 0;
dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
total += a->len;
if (a->magic != ALLOC_MAGIC) {
wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
"len %lu",
a, a->magic, (unsigned long) a->len);
continue;
}
wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
a, (unsigned long) a->len);
wpa_trace_dump("memleak", a);
}
if (total)
wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
(unsigned long) total);
#endif /* WPA_TRACE */
}
int os_setenv(const char *name, const char *value, int overwrite)
{
return setenv(name, value, overwrite);
}
int os_unsetenv(const char *name)
{
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
defined(__OpenBSD__)
unsetenv(name);
return 0;
#else
return unsetenv(name);
#endif
}
char * os_readfile(const char *name, size_t *len)
{
FILE *f;
char *buf;
long pos;
f = fopen(name, "rb");
if (f == NULL)
return NULL;
if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
fclose(f);
return NULL;
}
*len = pos;
if (fseek(f, 0, SEEK_SET) < 0) {
fclose(f);
return NULL;
}
buf = os_malloc(*len);
if (buf == NULL) {
fclose(f);
return NULL;
}
if (fread(buf, 1, *len, f) != *len) {
fclose(f);
os_free(buf);
return NULL;
}
fclose(f);
return buf;
}
int os_file_exists(const char *fname)
{
FILE *f = fopen(fname, "rb");
if (f == NULL)
return 0;
fclose(f);
return 1;
}
#ifndef WPA_TRACE
void * os_zalloc(size_t size)
{
return calloc(1, size);
}
#endif /* WPA_TRACE */
size_t os_strlcpy(char *dest, const char *src, size_t siz)
{
const char *s = src;
size_t left = siz;
if (left) {
/* Copy string up to the maximum size of the dest buffer */
while (--left != 0) {
if ((*dest++ = *s++) == '\0')
break;
}
}
if (left == 0) {
/* Not enough room for the string; force NUL-termination */
if (siz != 0)
*dest = '\0';
while (*s++)
; /* determine total src string length */
}
return s - src - 1;
}
int os_memcmp_const(const void *a, const void *b, size_t len)
{
const u8 *aa = a;
const u8 *bb = b;
size_t i;
u8 res;
for (res = 0, i = 0; i < len; i++)
res |= aa[i] ^ bb[i];
return res;
}
#ifdef WPA_TRACE
#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
char wpa_trace_fail_func[256] = { 0 };
unsigned int wpa_trace_fail_after;
static int testing_fail_alloc(void)
{
const char *func[WPA_TRACE_LEN];
size_t i, res, len;
char *pos, *next;
int match;
if (!wpa_trace_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++;
if (i < res && os_strcmp(func[i], "os_malloc") == 0)
i++;
if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
i++;
if (i < res && os_strcmp(func[i], "os_calloc") == 0)
i++;
if (i < res && os_strcmp(func[i], "os_realloc") == 0)
i++;
if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
i++;
if (i < res && os_strcmp(func[i], "os_strdup") == 0)
i++;
pos = wpa_trace_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_fail_after--;
if (wpa_trace_fail_after == 0) {
wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
wpa_trace_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)
{
return 0;
}
#endif
void * os_malloc(size_t size)
{
struct os_alloc_trace *a;
if (testing_fail_alloc())
return NULL;
a = malloc(sizeof(*a) + size);
if (a == NULL)
return NULL;
a->magic = ALLOC_MAGIC;
dl_list_add(&alloc_list, &a->list);
a->len = size;
wpa_trace_record(a);
return a + 1;
}
void * os_realloc(void *ptr, size_t size)
{
struct os_alloc_trace *a;
size_t copy_len;
void *n;
if (ptr == NULL)
return os_malloc(size);
a = (struct os_alloc_trace *) ptr - 1;
if (a->magic != ALLOC_MAGIC) {
wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
a, a->magic,
a->magic == FREED_MAGIC ? " (already freed)" : "");
wpa_trace_show("Invalid os_realloc() call");
abort();
}
n = os_malloc(size);
if (n == NULL)
return NULL;
copy_len = a->len;
if (copy_len > size)
copy_len = size;
os_memcpy(n, a + 1, copy_len);
os_free(ptr);
return n;
}
void os_free(void *ptr)
{
struct os_alloc_trace *a;
if (ptr == NULL)
return;
a = (struct os_alloc_trace *) ptr - 1;
if (a->magic != ALLOC_MAGIC) {
wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
a, a->magic,
a->magic == FREED_MAGIC ? " (already freed)" : "");
wpa_trace_show("Invalid os_free() call");
abort();
}
dl_list_del(&a->list);
a->magic = FREED_MAGIC;
wpa_trace_check_ref(ptr);
free(a);
}
void * os_zalloc(size_t size)
{
void *ptr = os_malloc(size);
if (ptr)
os_memset(ptr, 0, size);
return ptr;
}
char * os_strdup(const char *s)
{
size_t len;
char *d;
len = os_strlen(s);
d = os_malloc(len + 1);
if (d == NULL)
return NULL;
os_memcpy(d, s, len);
d[len] = '\0';
return d;
}
#endif /* WPA_TRACE */
int os_exec(const char *program, const char *arg, int wait_completion)
{
pid_t pid;
int pid_status;
pid = fork();
if (pid < 0) {
perror("fork");
return -1;
}
if (pid == 0) {
/* run the external command in the child process */
const int MAX_ARG = 30;
char *_program, *_arg, *pos;
char *argv[MAX_ARG + 1];
int i;
_program = os_strdup(program);
_arg = os_strdup(arg);
argv[0] = _program;
i = 1;
pos = _arg;
while (i < MAX_ARG && pos && *pos) {
while (*pos == ' ')
pos++;
if (*pos == '\0')
break;
argv[i++] = pos;
pos = os_strchr(pos, ' ');
if (pos)
*pos++ = '\0';
}
argv[i] = NULL;
execv(program, argv);
perror("execv");
os_free(_program);
os_free(_arg);
exit(0);
return -1;
}
if (wait_completion) {
/* wait for the child process to complete in the parent */
waitpid(pid, &pid_status, 0);
}
return 0;
}

View File

@@ -0,0 +1,579 @@
/*
* wpa_supplicant/hostapd / common helper functions, etc.
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef COMMON_H
#define COMMON_H
#include "os.h"
#if defined(__linux__) || defined(__GLIBC__)
#include <endian.h>
#include <byteswap.h>
#endif /* __linux__ */
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
defined(__OpenBSD__)
#include <sys/types.h>
#include <sys/endian.h>
#define __BYTE_ORDER _BYTE_ORDER
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
#define __BIG_ENDIAN _BIG_ENDIAN
#ifdef __OpenBSD__
#define bswap_16 swap16
#define bswap_32 swap32
#define bswap_64 swap64
#else /* __OpenBSD__ */
#define bswap_16 bswap16
#define bswap_32 bswap32
#define bswap_64 bswap64
#endif /* __OpenBSD__ */
#endif /* defined(__FreeBSD__) || defined(__NetBSD__) ||
* defined(__DragonFly__) || defined(__OpenBSD__) */
#ifdef __APPLE__
#include <sys/types.h>
#include <machine/endian.h>
#define __BYTE_ORDER _BYTE_ORDER
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
#define __BIG_ENDIAN _BIG_ENDIAN
static inline unsigned short bswap_16(unsigned short v)
{
return ((v & 0xff) << 8) | (v >> 8);
}
static inline unsigned int bswap_32(unsigned int v)
{
return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
((v & 0xff0000) >> 8) | (v >> 24);
}
#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>
typedef int socklen_t;
#ifndef MSG_DONTWAIT
#define MSG_DONTWAIT 0 /* not supported */
#endif
#endif /* CONFIG_NATIVE_WINDOWS */
#ifdef _MSC_VER
#define inline __inline
#undef vsnprintf
#define vsnprintf _vsnprintf
#undef close
#define close closesocket
#endif /* _MSC_VER */
/* Define platform specific integer types */
#ifdef _MSC_VER
typedef UINT64 u64;
typedef UINT32 u32;
typedef UINT16 u16;
typedef UINT8 u8;
typedef INT64 s64;
typedef INT32 s32;
typedef INT16 s16;
typedef INT8 s8;
#define WPA_TYPES_DEFINED
#endif /* _MSC_VER */
#ifdef __vxworks
typedef unsigned long long u64;
typedef UINT32 u32;
typedef UINT16 u16;
typedef UINT8 u8;
typedef long long s64;
typedef INT32 s32;
typedef INT16 s16;
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>
#else
#include <stdint.h>
#endif
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef int64_t s64;
typedef int32_t s32;
typedef int16_t s16;
typedef int8_t s8;
#define WPA_TYPES_DEFINED
#endif /* !WPA_TYPES_DEFINED */
/* Define platform specific byte swapping macros */
#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
static inline unsigned short wpa_swap_16(unsigned short v)
{
return ((v & 0xff) << 8) | (v >> 8);
}
static inline unsigned int wpa_swap_32(unsigned int v)
{
return ((v & 0xff) << 24) | ((v & 0xff00) << 8) |
((v & 0xff0000) >> 8) | (v >> 24);
}
#define le_to_host16(n) (n)
#define host_to_le16(n) (n)
#define be_to_host16(n) wpa_swap_16(n)
#define host_to_be16(n) wpa_swap_16(n)
#define le_to_host32(n) (n)
#define host_to_le32(n) (n)
#define be_to_host32(n) wpa_swap_32(n)
#define host_to_be32(n) wpa_swap_32(n)
#define WPA_BYTE_SWAP_DEFINED
#endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */
#ifndef WPA_BYTE_SWAP_DEFINED
#ifndef __BYTE_ORDER
#ifndef __LITTLE_ENDIAN
#ifndef __BIG_ENDIAN
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#if defined(sparc)
#define __BYTE_ORDER __BIG_ENDIAN
#endif
#endif /* __BIG_ENDIAN */
#endif /* __LITTLE_ENDIAN */
#endif /* __BYTE_ORDER */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define le_to_host16(n) ((__force u16) (le16) (n))
#define host_to_le16(n) ((__force le16) (u16) (n))
#define be_to_host16(n) bswap_16((__force u16) (be16) (n))
#define host_to_be16(n) ((__force be16) bswap_16((n)))
#define le_to_host32(n) ((__force u32) (le32) (n))
#define host_to_le32(n) ((__force le32) (u32) (n))
#define be_to_host32(n) bswap_32((__force u32) (be32) (n))
#define host_to_be32(n) ((__force be32) bswap_32((n)))
#define le_to_host64(n) ((__force u64) (le64) (n))
#define host_to_le64(n) ((__force le64) (u64) (n))
#define be_to_host64(n) bswap_64((__force u64) (be64) (n))
#define host_to_be64(n) ((__force be64) bswap_64((n)))
#elif __BYTE_ORDER == __BIG_ENDIAN
#define le_to_host16(n) bswap_16(n)
#define host_to_le16(n) bswap_16(n)
#define be_to_host16(n) (n)
#define host_to_be16(n) (n)
#define le_to_host32(n) bswap_32(n)
#define host_to_le32(n) bswap_32(n)
#define be_to_host32(n) (n)
#define host_to_be32(n) (n)
#define le_to_host64(n) bswap_64(n)
#define host_to_le64(n) bswap_64(n)
#define be_to_host64(n) (n)
#define host_to_be64(n) (n)
#ifndef WORDS_BIGENDIAN
#define WORDS_BIGENDIAN
#endif
#else
#error Could not determine CPU byte order
#endif
#define WPA_BYTE_SWAP_DEFINED
#endif /* !WPA_BYTE_SWAP_DEFINED */
/* Macros for handling unaligned memory accesses */
static inline u16 WPA_GET_BE16(const u8 *a)
{
return (a[0] << 8) | a[1];
}
static inline void WPA_PUT_BE16(u8 *a, u16 val)
{
a[0] = val >> 8;
a[1] = val & 0xff;
}
static inline u16 WPA_GET_LE16(const u8 *a)
{
return (a[1] << 8) | a[0];
}
static inline void WPA_PUT_LE16(u8 *a, u16 val)
{
a[1] = val >> 8;
a[0] = val & 0xff;
}
static inline u32 WPA_GET_BE24(const u8 *a)
{
return (a[0] << 16) | (a[1] << 8) | a[2];
}
static inline void WPA_PUT_BE24(u8 *a, u32 val)
{
a[0] = (val >> 16) & 0xff;
a[1] = (val >> 8) & 0xff;
a[2] = val & 0xff;
}
static inline u32 WPA_GET_BE32(const u8 *a)
{
return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
}
static inline void WPA_PUT_BE32(u8 *a, u32 val)
{
a[0] = (val >> 24) & 0xff;
a[1] = (val >> 16) & 0xff;
a[2] = (val >> 8) & 0xff;
a[3] = val & 0xff;
}
static inline u32 WPA_GET_LE32(const u8 *a)
{
return (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
}
static inline void WPA_PUT_LE32(u8 *a, u32 val)
{
a[3] = (val >> 24) & 0xff;
a[2] = (val >> 16) & 0xff;
a[1] = (val >> 8) & 0xff;
a[0] = val & 0xff;
}
static inline u64 WPA_GET_BE64(const u8 *a)
{
return (((u64) a[0]) << 56) | (((u64) a[1]) << 48) |
(((u64) a[2]) << 40) | (((u64) a[3]) << 32) |
(((u64) a[4]) << 24) | (((u64) a[5]) << 16) |
(((u64) a[6]) << 8) | ((u64) a[7]);
}
static inline void WPA_PUT_BE64(u8 *a, u64 val)
{
a[0] = val >> 56;
a[1] = val >> 48;
a[2] = val >> 40;
a[3] = val >> 32;
a[4] = val >> 24;
a[5] = val >> 16;
a[6] = val >> 8;
a[7] = val & 0xff;
}
static inline u64 WPA_GET_LE64(const u8 *a)
{
return (((u64) a[7]) << 56) | (((u64) a[6]) << 48) |
(((u64) a[5]) << 40) | (((u64) a[4]) << 32) |
(((u64) a[3]) << 24) | (((u64) a[2]) << 16) |
(((u64) a[1]) << 8) | ((u64) a[0]);
}
static inline void WPA_PUT_LE64(u8 *a, u64 val)
{
a[7] = val >> 56;
a[6] = val >> 48;
a[5] = val >> 40;
a[4] = val >> 32;
a[3] = val >> 24;
a[2] = val >> 16;
a[1] = val >> 8;
a[0] = val & 0xff;
}
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
#ifndef ETH_HLEN
#define ETH_HLEN 14
#endif
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
#endif
#ifndef ETH_P_ALL
#define ETH_P_ALL 0x0003
#endif
#ifndef ETH_P_80211_ENCAP
#define ETH_P_80211_ENCAP 0x890d /* TDLS comes under this category */
#endif
#ifndef ETH_P_PAE
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
#endif /* ETH_P_PAE */
#ifndef ETH_P_EAPOL
#define ETH_P_EAPOL ETH_P_PAE
#endif /* ETH_P_EAPOL */
#ifndef ETH_P_RSN_PREAUTH
#define ETH_P_RSN_PREAUTH 0x88c7
#endif /* ETH_P_RSN_PREAUTH */
#ifndef ETH_P_RRB
#define ETH_P_RRB 0x890D
#endif /* ETH_P_RRB */
#ifdef __GNUC__
#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b))))
#define STRUCT_PACKED __attribute__ ((packed))
#else
#define PRINTF_FORMAT(a,b)
#define STRUCT_PACKED
#endif
#ifdef CONFIG_ANSI_C_EXTRA
#if !defined(_MSC_VER) || _MSC_VER < 1400
/* snprintf - used in number of places; sprintf() is _not_ a good replacement
* due to possible buffer overflow; see, e.g.,
* http://www.ijs.si/software/snprintf/ for portable implementation of
* snprintf. */
int snprintf(char *str, size_t size, const char *format, ...);
/* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
#endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */
/* getopt - only used in main.c */
int getopt(int argc, char *const argv[], const char *optstring);
extern char *optarg;
extern int optind;
#ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF
#ifndef __socklen_t_defined
typedef int socklen_t;
#endif
#endif
/* inline - define as __inline or just define it to be empty, if needed */
#ifdef CONFIG_NO_INLINE
#define inline
#else
#define inline __inline
#endif
#ifndef __func__
#define __func__ "__func__ not defined"
#endif
#ifndef bswap_16
#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff))
#endif
#ifndef bswap_32
#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \
(((u32) (a) << 8) & 0xff0000) | \
(((u32) (a) >> 8) & 0xff00) | \
(((u32) (a) >> 24) & 0xff))
#endif
#ifndef MSG_DONTWAIT
#define MSG_DONTWAIT 0
#endif
#ifdef _WIN32_WCE
void perror(const char *s);
#endif /* _WIN32_WCE */
#endif /* CONFIG_ANSI_C_EXTRA */
#ifndef MAC2STR
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
/*
* Compact form for string representation of MAC address
* To be used, e.g., for constructing dbus paths for P2P Devices
*/
#define COMPACT_MACSTR "%02x%02x%02x%02x%02x%02x"
#endif
#ifndef BIT
#define BIT(x) (1 << (x))
#endif
/*
* Definitions for sparse validation
* (http://kernel.org/pub/linux/kernel/people/josh/sparse/)
*/
#ifdef __CHECKER__
#define __force __attribute__((force))
#define __bitwise __attribute__((bitwise))
#else
#define __force
#ifndef __bitwise
#define __bitwise
#endif
#endif
typedef u16 __bitwise be16;
typedef u16 __bitwise le16;
typedef u32 __bitwise be32;
typedef u32 __bitwise le32;
typedef u64 __bitwise be64;
typedef u64 __bitwise le64;
#ifndef __must_check
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#define __must_check __attribute__((__warn_unused_result__))
#else
#define __must_check
#endif /* __GNUC__ */
#endif /* __must_check */
#ifndef __maybe_unused
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#define __maybe_unused __attribute__((unused))
#else
#define __maybe_unused
#endif /* __GNUC__ */
#endif /* __must_check */
int hwaddr_aton(const char *txt, u8 *addr);
int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable);
int hwaddr_compact_aton(const char *txt, u8 *addr);
int hwaddr_aton2(const char *txt, u8 *addr);
int hex2byte(const char *hex);
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(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);
int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
#ifdef CONFIG_NATIVE_WINDOWS
void wpa_unicode2ascii_inplace(TCHAR *str);
TCHAR * wpa_strdup_tchar(const char *str);
#else /* CONFIG_NATIVE_WINDOWS */
#define wpa_unicode2ascii_inplace(s) do { } while (0)
#define wpa_strdup_tchar(s) strdup((s))
#endif /* CONFIG_NATIVE_WINDOWS */
void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len);
size_t printf_decode(u8 *buf, size_t maxlen, const char *str);
const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
char * wpa_config_parse_string(const char *value, size_t *len);
int is_hex(const u8 *data, size_t len);
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len);
char * dup_binstr(const void *src, size_t len);
static inline int is_zero_ether_addr(const u8 *a)
{
return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]);
}
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"
struct wpa_freq_range_list {
struct wpa_freq_range {
unsigned int min;
unsigned int max;
} *range;
unsigned int num;
};
int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value);
int freq_range_list_includes(const struct wpa_freq_range_list *list,
unsigned int freq);
char * freq_range_list_str(const struct wpa_freq_range_list *list);
int int_array_len(const int *a);
void int_array_concat(int **res, const int *a);
void int_array_sort_unique(int *a);
void int_array_add_unique(int **res, int a);
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
void str_clear_free(char *str);
void bin_clear_free(void *bin, size_t len);
int random_mac_addr(u8 *addr);
int random_mac_addr_keep_oui(u8 *addr);
char * str_token(char *str, const char *delim, char **context);
/*
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
* networking socket uses that do not really result in a real problem and
* cannot be easily avoided with union-based type-punning due to struct
* definitions including another struct in system header files. To avoid having
* to fully disable strict-aliasing warnings, provide a mechanism to hide the
* typecast from aliasing for now. A cleaner solution will hopefully be found
* in the future to handle these cases.
*/
void * __hide_aliasing_typecast(void *foo);
#define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a))
#ifdef CONFIG_VALGRIND
#include <valgrind/memcheck.h>
#define WPA_MEM_DEFINED(ptr, len) VALGRIND_MAKE_MEM_DEFINED((ptr), (len))
#else /* CONFIG_VALGRIND */
#define WPA_MEM_DEFINED(ptr, len) do { } while (0)
#endif /* CONFIG_VALGRIND */
#endif /* COMMON_H */

View File

@@ -0,0 +1,359 @@
/*
* Event loop
* Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*
* This file defines an event loop interface that supports processing events
* from registered timeouts (i.e., do something after N seconds), sockets
* (e.g., a new packet available for reading), and signals. eloop.c is an
* implementation of this interface using select() and sockets. This is
* suitable for most UNIX/POSIX systems. When porting to other operating
* systems, it may be necessary to replace that implementation with OS specific
* mechanisms.
*/
#ifndef ELOOP_H
#define ELOOP_H
/**
* ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts
*/
#define ELOOP_ALL_CTX (void *) -1
/**
* eloop_event_type - eloop socket event type for eloop_register_sock()
* @EVENT_TYPE_READ: Socket has data available for reading
* @EVENT_TYPE_WRITE: Socket has room for new data to be written
* @EVENT_TYPE_EXCEPTION: An exception has been reported
*/
typedef enum {
EVENT_TYPE_READ = 0,
EVENT_TYPE_WRITE,
EVENT_TYPE_EXCEPTION
} eloop_event_type;
/**
* eloop_sock_handler - eloop socket event callback type
* @sock: File descriptor number for the socket
* @eloop_ctx: Registered callback context data (eloop_data)
* @sock_ctx: Registered callback context data (user_data)
*/
typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx);
/**
* eloop_event_handler - eloop generic event callback type
* @eloop_ctx: Registered callback context data (eloop_data)
* @sock_ctx: Registered callback context data (user_data)
*/
typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx);
/**
* eloop_timeout_handler - eloop timeout event callback type
* @eloop_ctx: Registered callback context data (eloop_data)
* @sock_ctx: Registered callback context data (user_data)
*/
typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
/**
* eloop_signal_handler - eloop signal event callback type
* @sig: Signal number
* @signal_ctx: Registered callback context data (user_data from
* eloop_register_signal(), eloop_register_signal_terminate(), or
* eloop_register_signal_reconfig() call)
*/
typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
/**
* eloop_init() - Initialize global event loop data
* Returns: 0 on success, -1 on failure
*
* This function must be called before any other eloop_* function.
*/
int eloop_init(void);
/**
* eloop_register_read_sock - Register handler for read events
* @sock: File descriptor number for the socket
* @handler: Callback function to be called when data is available for reading
* @eloop_data: Callback context data (eloop_ctx)
* @user_data: Callback context data (sock_ctx)
* Returns: 0 on success, -1 on failure
*
* Register a read socket notifier for the given file descriptor. The handler
* function will be called whenever data is available for reading from the
* socket. The handler function is responsible for clearing the event after
* having processed it in order to avoid eloop from calling the handler again
* for the same event.
*/
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
void *eloop_data, void *user_data);
/**
* eloop_unregister_read_sock - Unregister handler for read events
* @sock: File descriptor number for the socket
*
* Unregister a read socket notifier that was previously registered with
* eloop_register_read_sock().
*/
void eloop_unregister_read_sock(int sock);
/**
* eloop_register_sock - Register handler for socket events
* @sock: File descriptor number for the socket
* @type: Type of event to wait for
* @handler: Callback function to be called when the event is triggered
* @eloop_data: Callback context data (eloop_ctx)
* @user_data: Callback context data (sock_ctx)
* Returns: 0 on success, -1 on failure
*
* Register an event notifier for the given socket's file descriptor. The
* handler function will be called whenever the that event is triggered for the
* socket. The handler function is responsible for clearing the event after
* having processed it in order to avoid eloop from calling the handler again
* for the same event.
*/
int eloop_register_sock(int sock, eloop_event_type type,
eloop_sock_handler handler,
void *eloop_data, void *user_data);
/**
* eloop_unregister_sock - Unregister handler for socket events
* @sock: File descriptor number for the socket
* @type: Type of event for which sock was registered
*
* Unregister a socket event notifier that was previously registered with
* eloop_register_sock().
*/
void eloop_unregister_sock(int sock, eloop_event_type type);
/**
* eloop_register_event - Register handler for generic events
* @event: Event to wait (eloop implementation specific)
* @event_size: Size of event data
* @handler: Callback function to be called when event is triggered
* @eloop_data: Callback context data (eloop_data)
* @user_data: Callback context data (user_data)
* Returns: 0 on success, -1 on failure
*
* Register an event handler for the given event. This function is used to
* register eloop implementation specific events which are mainly targeted for
* operating system specific code (driver interface and l2_packet) since the
* portable code will not be able to use such an OS-specific call. The handler
* function will be called whenever the event is triggered. The handler
* function is responsible for clearing the event after having processed it in
* order to avoid eloop from calling the handler again for the same event.
*
* In case of Windows implementation (eloop_win.c), event pointer is of HANDLE
* type, i.e., void*. The callers are likely to have 'HANDLE h' type variable,
* and they would call this function with eloop_register_event(h, sizeof(h),
* ...).
*/
int eloop_register_event(void *event, size_t event_size,
eloop_event_handler handler,
void *eloop_data, void *user_data);
/**
* eloop_unregister_event - Unregister handler for a generic event
* @event: Event to cancel (eloop implementation specific)
* @event_size: Size of event data
*
* Unregister a generic event notifier that was previously registered with
* eloop_register_event().
*/
void eloop_unregister_event(void *event, size_t event_size);
/**
* eloop_register_timeout - Register timeout
* @secs: Number of seconds to the timeout
* @usecs: Number of microseconds to the timeout
* @handler: Callback function to be called when timeout occurs
* @eloop_data: Callback context data (eloop_ctx)
* @user_data: Callback context data (sock_ctx)
* Returns: 0 on success, -1 on failure
*
* Register a timeout that will cause the handler function to be called after
* given time.
*/
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
eloop_timeout_handler handler,
void *eloop_data, void *user_data);
/**
* eloop_cancel_timeout - Cancel timeouts
* @handler: Matching callback function
* @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all
* @user_data: Matching user_data or %ELOOP_ALL_CTX to match all
* Returns: Number of cancelled timeouts
*
* Cancel matching <handler,eloop_data,user_data> timeouts registered with
* eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for
* cancelling all timeouts regardless of eloop_data/user_data.
*/
int eloop_cancel_timeout(eloop_timeout_handler handler,
void *eloop_data, void *user_data);
/**
* eloop_cancel_timeout_one - Cancel a single timeout
* @handler: Matching callback function
* @eloop_data: Matching eloop_data
* @user_data: Matching user_data
* @remaining: Time left on the cancelled timer
* Returns: Number of cancelled timeouts
*
* Cancel matching <handler,eloop_data,user_data> timeout registered with
* eloop_register_timeout() and return the remaining time left.
*/
int eloop_cancel_timeout_one(eloop_timeout_handler handler,
void *eloop_data, void *user_data,
struct os_reltime *remaining);
/**
* eloop_is_timeout_registered - Check if a timeout is already registered
* @handler: Matching callback function
* @eloop_data: Matching eloop_data
* @user_data: Matching user_data
* Returns: 1 if the timeout is registered, 0 if the timeout is not registered
*
* Determine if a matching <handler,eloop_data,user_data> timeout is registered
* with eloop_register_timeout().
*/
int eloop_is_timeout_registered(eloop_timeout_handler handler,
void *eloop_data, void *user_data);
/**
* eloop_deplete_timeout - Deplete a timeout that is already registered
* @req_secs: Requested number of seconds to the timeout
* @req_usecs: Requested number of microseconds to the timeout
* @handler: Matching callback function
* @eloop_data: Matching eloop_data
* @user_data: Matching user_data
* Returns: 1 if the timeout is depleted, 0 if no change is made, -1 if no
* timeout matched
*
* Find a registered matching <handler,eloop_data,user_data> timeout. If found,
* deplete the timeout if remaining time is more than the requested time.
*/
int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
eloop_timeout_handler handler, void *eloop_data,
void *user_data);
/**
* eloop_replenish_timeout - Replenish a timeout that is already registered
* @req_secs: Requested number of seconds to the timeout
* @req_usecs: Requested number of microseconds to the timeout
* @handler: Matching callback function
* @eloop_data: Matching eloop_data
* @user_data: Matching user_data
* Returns: 1 if the timeout is replenished, 0 if no change is made, -1 if no
* timeout matched
*
* Find a registered matching <handler,eloop_data,user_data> timeout. If found,
* replenish the timeout if remaining time is less than the requested time.
*/
int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
eloop_timeout_handler handler, void *eloop_data,
void *user_data);
/**
* eloop_register_signal - Register handler for signals
* @sig: Signal number (e.g., SIGHUP)
* @handler: Callback function to be called when the signal is received
* @user_data: Callback context data (signal_ctx)
* Returns: 0 on success, -1 on failure
*
* Register a callback function that will be called when a signal is received.
* The callback function is actually called only after the system signal
* handler has returned. This means that the normal limits for sighandlers
* (i.e., only "safe functions" allowed) do not apply for the registered
* callback.
*/
int eloop_register_signal(int sig, eloop_signal_handler handler,
void *user_data);
/**
* eloop_register_signal_terminate - Register handler for terminate signals
* @handler: Callback function to be called when the signal is received
* @user_data: Callback context data (signal_ctx)
* Returns: 0 on success, -1 on failure
*
* Register a callback function that will be called when a process termination
* signal is received. The callback function is actually called only after the
* system signal handler has returned. This means that the normal limits for
* sighandlers (i.e., only "safe functions" allowed) do not apply for the
* registered callback.
*
* This function is a more portable version of eloop_register_signal() since
* the knowledge of exact details of the signals is hidden in eloop
* implementation. In case of operating systems using signal(), this function
* registers handlers for SIGINT and SIGTERM.
*/
int eloop_register_signal_terminate(eloop_signal_handler handler,
void *user_data);
/**
* eloop_register_signal_reconfig - Register handler for reconfig signals
* @handler: Callback function to be called when the signal is received
* @user_data: Callback context data (signal_ctx)
* Returns: 0 on success, -1 on failure
*
* Register a callback function that will be called when a reconfiguration /
* hangup signal is received. The callback function is actually called only
* after the system signal handler has returned. This means that the normal
* limits for sighandlers (i.e., only "safe functions" allowed) do not apply
* for the registered callback.
*
* This function is a more portable version of eloop_register_signal() since
* the knowledge of exact details of the signals is hidden in eloop
* implementation. In case of operating systems using signal(), this function
* registers a handler for SIGHUP.
*/
int eloop_register_signal_reconfig(eloop_signal_handler handler,
void *user_data);
/**
* eloop_run - Start the event loop
*
* Start the event loop and continue running as long as there are any
* registered event handlers. This function is run after event loop has been
* initialized with event_init() and one or more events have been registered.
*/
void eloop_run(void);
/**
* eloop_terminate - Terminate event loop
*
* Terminate event loop even if there are registered events. This can be used
* to request the program to be terminated cleanly.
*/
void eloop_terminate(void);
/**
* eloop_destroy - Free any resources allocated for the event loop
*
* After calling eloop_destroy(), other eloop_* functions must not be called
* before re-running eloop_init().
*/
void eloop_destroy(void);
/**
* eloop_terminated - Check whether event loop has been terminated
* Returns: 1 = event loop terminate, 0 = event loop still running
*
* This function can be used to check whether eloop_terminate() has been called
* to request termination of the event loop. This is normally used to abort
* operations that may still be queued to be run when eloop_terminate() was
* called.
*/
int eloop_terminated(void);
/**
* eloop_wait_for_read_sock - Wait for a single reader
* @sock: File descriptor number for the socket
*
* Do a blocking wait for a single read socket.
*/
void eloop_wait_for_read_sock(int sock);
#endif /* ELOOP_H */

View File

@@ -0,0 +1,50 @@
/*
* wpa_supplicant/hostapd - Default include files
* Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*
* This header file is included into all C files so that commonly used header
* files can be selected with OS specific ifdef blocks in one place instead of
* having to have OS/C library specific selection in many files.
*/
#ifndef INCLUDES_H
#define INCLUDES_H
/* Include possible build time configuration before including anything else */
#include "build_config.h"
#include <stdlib.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>
#ifndef __vxworks
#include <sys/uio.h>
#include <sys/time.h>
#endif /* __vxworks */
#endif /* CONFIG_TI_COMPILER */
#endif /* CONFIG_NATIVE_WINDOWS */
#endif /* INCLUDES_H */

View File

@@ -0,0 +1,95 @@
/*
* Doubly-linked list
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef LIST_H
#define LIST_H
/**
* struct dl_list - Doubly-linked list
*/
struct dl_list {
struct dl_list *next;
struct dl_list *prev;
};
static inline void dl_list_init(struct dl_list *list)
{
list->next = list;
list->prev = list;
}
static inline void dl_list_add(struct dl_list *list, struct dl_list *item)
{
item->next = list->next;
item->prev = list;
list->next->prev = item;
list->next = item;
}
static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item)
{
dl_list_add(list->prev, item);
}
static inline void dl_list_del(struct dl_list *item)
{
item->next->prev = item->prev;
item->prev->next = item->next;
item->next = NULL;
item->prev = NULL;
}
static inline int dl_list_empty(struct dl_list *list)
{
return list->next == list;
}
static inline unsigned int dl_list_len(struct dl_list *list)
{
struct dl_list *item;
int count = 0;
for (item = list->next; item != list; item = item->next)
count++;
return count;
}
#ifndef offsetof
#define offsetof(type, member) ((long) &((type *) 0)->member)
#endif
#define dl_list_entry(item, type, member) \
((type *) ((char *) item - offsetof(type, member)))
#define dl_list_first(list, type, member) \
(dl_list_empty((list)) ? NULL : \
dl_list_entry((list)->next, type, member))
#define dl_list_last(list, type, member) \
(dl_list_empty((list)) ? NULL : \
dl_list_entry((list)->prev, type, member))
#define dl_list_for_each(item, list, type, member) \
for (item = dl_list_entry((list)->next, type, member); \
&item->member != (list); \
item = dl_list_entry(item->member.next, type, member))
#define dl_list_for_each_safe(item, n, list, type, member) \
for (item = dl_list_entry((list)->next, type, member), \
n = dl_list_entry(item->member.next, type, member); \
&item->member != (list); \
item = n, n = dl_list_entry(n->member.next, type, member))
#define dl_list_for_each_reverse(item, list, type, member) \
for (item = dl_list_entry((list)->prev, type, member); \
&item->member != (list); \
item = dl_list_entry(item->member.prev, type, member))
#define DEFINE_DL_LIST(name) \
struct dl_list name = { &(name), &(name) }
#endif /* LIST_H */

View File

@@ -0,0 +1,676 @@
/*
* OS specific functions
* Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef OS_H
#define OS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef long os_time_t;
/**
* os_sleep - Sleep (sec, usec)
* @sec: Number of seconds to sleep
* @usec: Number of microseconds to sleep
*/
void os_sleep(os_time_t sec, os_time_t usec);
struct os_time {
os_time_t sec;
os_time_t usec;
};
struct os_reltime {
os_time_t sec;
os_time_t usec;
};
/**
* os_get_time - Get current time (sec, usec)
* @t: Pointer to buffer for the time
* Returns: 0 on success, -1 on failure
*/
int os_get_time(struct os_time *t);
/**
* os_get_reltime - Get relative time (sec, usec)
* @t: Pointer to buffer for the time
* Returns: 0 on success, -1 on failure
*/
int os_get_reltime(struct os_reltime *t);
/* Helpers for handling struct os_time */
static inline int os_time_before(struct os_time *a, struct os_time *b)
{
return (a->sec < b->sec) ||
(a->sec == b->sec && a->usec < b->usec);
}
static inline void os_time_sub(struct os_time *a, struct os_time *b,
struct os_time *res)
{
res->sec = a->sec - b->sec;
res->usec = a->usec - b->usec;
if (res->usec < 0) {
res->sec--;
res->usec += 1000000;
}
}
/* Helpers for handling struct os_reltime */
static inline int os_reltime_before(struct os_reltime *a,
struct os_reltime *b)
{
return (a->sec < b->sec) ||
(a->sec == b->sec && a->usec < b->usec);
}
static inline void os_reltime_sub(struct os_reltime *a, struct os_reltime *b,
struct os_reltime *res)
{
res->sec = a->sec - b->sec;
res->usec = a->usec - b->usec;
if (res->usec < 0) {
res->sec--;
res->usec += 1000000;
}
}
static inline void os_reltime_age(struct os_reltime *start,
struct os_reltime *age)
{
struct os_reltime now;
os_get_reltime(&now);
os_reltime_sub(&now, start, age);
}
static inline int os_reltime_expired(struct os_reltime *now,
struct os_reltime *ts,
os_time_t timeout_secs)
{
struct os_reltime age;
os_reltime_sub(now, ts, &age);
return (age.sec > timeout_secs) ||
(age.sec == timeout_secs && age.usec > 0);
}
static inline int os_reltime_initialized(struct os_reltime *t)
{
return t->sec != 0 || t->usec != 0;
}
static inline size_t memscpy(void* dst, size_t dst_size,
const void* src, size_t src_size)
{
size_t copy_size = (dst_size <= src_size)? dst_size : src_size;
memcpy(dst, src, copy_size);
return copy_size;
}
static inline size_t memsmove(void *dst, size_t dst_size,
const void *src, size_t src_size)
{
size_t copy_size = (dst_size <= src_size)? dst_size : src_size;
memmove(dst, src, copy_size);
return copy_size;
}
/**
* os_mktime - Convert broken-down time into seconds since 1970-01-01
* @year: Four digit year
* @month: Month (1 .. 12)
* @day: Day of month (1 .. 31)
* @hour: Hour (0 .. 23)
* @min: Minute (0 .. 59)
* @sec: Second (0 .. 60)
* @t: Buffer for returning calendar time representation (seconds since
* 1970-01-01 00:00:00)
* Returns: 0 on success, -1 on failure
*
* Note: The result is in seconds from Epoch, i.e., in UTC, not in local time
* which is used by POSIX mktime().
*/
int os_mktime(int year, int month, int day, int hour, int min, int sec,
os_time_t *t);
struct os_tm {
int sec; /* 0..59 or 60 for leap seconds */
int min; /* 0..59 */
int hour; /* 0..23 */
int day; /* 1..31 */
int month; /* 1..12 */
int year; /* Four digit year */
};
int os_gmtime(os_time_t t, struct os_tm *tm);
/**
* os_daemonize - Run in the background (detach from the controlling terminal)
* @pid_file: File name to write the process ID to or %NULL to skip this
* Returns: 0 on success, -1 on failure
*/
int os_daemonize(const char *pid_file);
/**
* os_daemonize_terminate - Stop running in the background (remove pid file)
* @pid_file: File name to write the process ID to or %NULL to skip this
*/
void os_daemonize_terminate(const char *pid_file);
/**
* os_get_random - Get cryptographically strong pseudo random data
* @buf: Buffer for pseudo random data
* @len: Length of the buffer
* Returns: 0 on success, -1 on failure
*/
int os_get_random(unsigned char *buf, size_t len);
/**
* os_random - Get pseudo random value (not necessarily very strong)
* Returns: Pseudo random value
*/
unsigned long os_random(void);
/**
* os_rel2abs_path - Get an absolute path for a file
* @rel_path: Relative path to a file
* Returns: Absolute path for the file or %NULL on failure
*
* This function tries to convert a relative path of a file to an absolute path
* in order for the file to be found even if current working directory has
* changed. The returned value is allocated and caller is responsible for
* freeing it. It is acceptable to just return the same path in an allocated
* buffer, e.g., return strdup(rel_path). This function is only used to find
* configuration files when os_daemonize() may have changed the current working
* directory and relative path would be pointing to a different location.
*/
char * os_rel2abs_path(const char *rel_path);
/**
* os_program_init - Program initialization (called at start)
* Returns: 0 on success, -1 on failure
*
* This function is called when a programs starts. If there are any OS specific
* processing that is needed, it can be placed here. It is also acceptable to
* just return 0 if not special processing is needed.
*/
int os_program_init(void);
/**
* os_program_deinit - Program deinitialization (called just before exit)
*
* This function is called just before a program exists. If there are any OS
* specific processing, e.g., freeing resourced allocated in os_program_init(),
* it should be done here. It is also acceptable for this function to do
* nothing.
*/
void os_program_deinit(void);
/**
* os_setenv - Set environment variable
* @name: Name of the variable
* @value: Value to set to the variable
* @overwrite: Whether existing variable should be overwritten
* Returns: 0 on success, -1 on error
*
* This function is only used for wpa_cli action scripts. OS wrapper does not
* need to implement this if such functionality is not needed.
*/
int os_setenv(const char *name, const char *value, int overwrite);
/**
* os_unsetenv - Delete environent variable
* @name: Name of the variable
* Returns: 0 on success, -1 on error
*
* This function is only used for wpa_cli action scripts. OS wrapper does not
* need to implement this if such functionality is not needed.
*/
int os_unsetenv(const char *name);
/**
* os_readfile - Read a file to an allocated memory buffer
* @name: Name of the file to read
* @len: For returning the length of the allocated buffer
* Returns: Pointer to the allocated buffer or %NULL on failure
*
* This function allocates memory and reads the given file to this buffer. Both
* binary and text files can be read with this function. The caller is
* responsible for freeing the returned buffer with os_free().
*/
char * os_readfile(const char *name, size_t *len);
/**
* os_file_exists - Check whether the specified file exists
* @fname: Path and name of the file
* Returns: 1 if the file exists or 0 if not
*/
int os_file_exists(const char *fname);
/**
* os_zalloc - Allocate and zero memory
* @size: Number of bytes to allocate
* Returns: Pointer to allocated and zeroed memory or %NULL on failure
*
* Caller is responsible for freeing the returned buffer with os_free().
*/
void * os_zalloc(size_t size);
/**
* os_calloc - Allocate and zero memory for an array
* @nmemb: Number of members in the array
* @size: Number of bytes in each member
* Returns: Pointer to allocated and zeroed memory or %NULL on failure
*
* This function can be used as a wrapper for os_zalloc(nmemb * size) when an
* allocation is used for an array. The main benefit over os_zalloc() is in
* having an extra check to catch integer overflows in multiplication.
*
* Caller is responsible for freeing the returned buffer with os_free().
*/
static inline void * os_calloc(size_t nmemb, size_t size)
{
if (size && nmemb > (~(size_t) 0) / size)
return NULL;
return os_zalloc(nmemb * size);
}
/*
* The following functions are wrapper for standard ANSI C or POSIX functions.
* By default, they are just defined to use the standard function name and no
* os_*.c implementation is needed for them. This avoids extra function calls
* by allowing the C pre-processor take care of the function name mapping.
*
* If the target system uses a C library that does not provide these functions,
* build_config.h can be used to define the wrappers to use a different
* function name. This can be done on function-by-function basis since the
* defines here are only used if build_config.h does not define the os_* name.
* If needed, os_*.c file can be used to implement the functions that are not
* included in the C library on the target system. Alternatively,
* OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case
* these functions need to be implemented in os_*.c file for the target system.
*/
#ifdef OS_NO_C_LIB_DEFINES
/**
* os_malloc - Allocate dynamic memory
* @size: Size of the buffer to allocate
* Returns: Allocated buffer or %NULL on failure
*
* Caller is responsible for freeing the returned buffer with os_free().
*/
void * os_malloc(size_t size);
/**
* os_realloc - Re-allocate dynamic memory
* @ptr: Old buffer from os_malloc() or os_realloc()
* @size: Size of the new buffer
* Returns: Allocated buffer or %NULL on failure
*
* Caller is responsible for freeing the returned buffer with os_free().
* If re-allocation fails, %NULL is returned and the original buffer (ptr) is
* not freed and caller is still responsible for freeing it.
*/
void * os_realloc(void *ptr, size_t size);
/**
* os_free - Free dynamic memory
* @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL
*/
void os_free(void *ptr);
/**
* os_memcpy - Copy memory area
* @dest: Destination
* @src: Source
* @n: Number of bytes to copy
* Returns: dest
*
* The memory areas src and dst must not overlap. os_memmove() can be used with
* overlapping memory.
*/
void * os_memcpy(void *dest, const void *src, size_t n);
/**
* os_memmove - Copy memory area
* @dest: Destination
* @src: Source
* @n: Number of bytes to copy
* Returns: dest
*
* The memory areas src and dst may overlap.
*/
void * os_memmove(void *dest, const void *src, size_t n);
/**
* os_memset - Fill memory with a constant byte
* @s: Memory area to be filled
* @c: Constant byte
* @n: Number of bytes started from s to fill with c
* Returns: s
*/
void * os_memset(void *s, int c, size_t n);
/**
* os_memcmp - Compare memory areas
* @s1: First buffer
* @s2: Second buffer
* @n: Maximum numbers of octets to compare
* Returns: An integer less than, equal to, or greater than zero if s1 is
* found to be less than, to match, or be greater than s2. Only first n
* characters will be compared.
*/
int os_memcmp(const void *s1, const void *s2, size_t n);
/**
* os_strdup - Duplicate a string
* @s: Source string
* Returns: Allocated buffer with the string copied into it or %NULL on failure
*
* Caller is responsible for freeing the returned buffer with os_free().
*/
char * os_strdup(const char *s);
/**
* os_strlen - Calculate the length of a string
* @s: '\0' terminated string
* Returns: Number of characters in s (not counting the '\0' terminator)
*/
size_t os_strlen(const char *s);
/**
* os_strcasecmp - Compare two strings ignoring case
* @s1: First string
* @s2: Second string
* Returns: An integer less than, equal to, or greater than zero if s1 is
* found to be less than, to match, or be greatred than s2
*/
int os_strcasecmp(const char *s1, const char *s2);
/**
* os_strncasecmp - Compare two strings ignoring case
* @s1: First string
* @s2: Second string
* @n: Maximum numbers of characters to compare
* Returns: An integer less than, equal to, or greater than zero if s1 is
* found to be less than, to match, or be greater than s2. Only first n
* characters will be compared.
*/
int os_strncasecmp(const char *s1, const char *s2, size_t n);
/**
* os_strchr - Locate the first occurrence of a character in string
* @s: String
* @c: Character to search for
* Returns: Pointer to the matched character or %NULL if not found
*/
char * os_strchr(const char *s, int c);
/**
* os_strrchr - Locate the last occurrence of a character in string
* @s: String
* @c: Character to search for
* Returns: Pointer to the matched character or %NULL if not found
*/
char * os_strrchr(const char *s, int c);
/**
* os_strcmp - Compare two strings
* @s1: First string
* @s2: Second string
* Returns: An integer less than, equal to, or greater than zero if s1 is
* found to be less than, to match, or be greatred than s2
*/
int os_strcmp(const char *s1, const char *s2);
/**
* os_strncmp - Compare two strings
* @s1: First string
* @s2: Second string
* @n: Maximum numbers of characters to compare
* Returns: An integer less than, equal to, or greater than zero if s1 is
* found to be less than, to match, or be greater than s2. Only first n
* characters will be compared.
*/
int os_strncmp(const char *s1, const char *s2, size_t n);
/**
* os_strstr - Locate a substring
* @haystack: String (haystack) to search from
* @needle: Needle to search from haystack
* Returns: Pointer to the beginning of the substring or %NULL if not found
*/
char * os_strstr(const char *haystack, const char *needle);
/**
* os_snprintf - Print to a memory buffer
* @str: Memory buffer to print into
* @size: Maximum length of the str buffer
* @format: printf format
* Returns: Number of characters printed (not including trailing '\0').
*
* If the output buffer is truncated, number of characters which would have
* been written is returned. Since some C libraries return -1 in such a case,
* the caller must be prepared on that value, too, to indicate truncation.
*
* Note: Some C library implementations of snprintf() may not guarantee null
* termination in case the output is truncated. The OS wrapper function of
* os_snprintf() should provide this guarantee, i.e., to null terminate the
* output buffer if a C library version of the function is used and if that
* function does not guarantee null termination.
*
* If the target system does not include snprintf(), see, e.g.,
* http://www.ijs.si/software/snprintf/ for an example of a portable
* implementation of snprintf.
*/
int os_snprintf(char *str, size_t size, const char *format, ...);
#else /* OS_NO_C_LIB_DEFINES */
#ifdef WPA_TRACE
void * os_malloc(size_t size);
void * os_realloc(void *ptr, size_t size);
void os_free(void *ptr);
char * os_strdup(const char *s);
#else /* WPA_TRACE */
#ifndef os_malloc
#define os_malloc(s) malloc((s))
#endif
#ifndef os_realloc
#define os_realloc(p, s) realloc((p), (s))
#endif
#ifndef os_free
#define os_free(p) free((p))
#endif
#ifndef os_strdup
#ifdef _MSC_VER
#define os_strdup(s) _strdup(s)
#else
#define os_strdup(s) strdup(s)
#endif
#endif
#endif /* WPA_TRACE */
#ifndef os_memcpy
#define os_memcpy(d, s, n) memscpy((d), (n), (s), (n))
#endif
#ifndef os_memmove
#define os_memmove(d, s, n) memsmove((d), (n), (s), (n))
#endif
#ifndef os_memset
#define os_memset(s, c, n) memset(s, c, n)
#endif
#ifndef os_memcmp
#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n))
#endif
#ifndef os_strlen
#define os_strlen(s) strlen(s)
#endif
#ifndef os_strcasecmp
#ifdef _MSC_VER
#define os_strcasecmp(s1, s2) _stricmp((s1), (s2))
#else
#define os_strcasecmp(s1, s2) strcasecmp((s1), (s2))
#endif
#endif
#ifndef os_strncasecmp
#ifdef _MSC_VER
#define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n))
#else
#define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n))
#endif
#endif
#ifndef os_strchr
#define os_strchr(s, c) strchr((s), (c))
#endif
#ifndef os_strcmp
#define os_strcmp(s1, s2) strcmp((s1), (s2))
#endif
#ifndef os_strncmp
#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
#endif
#ifndef os_strrchr
#define os_strrchr(s, c) strrchr((s), (c))
#endif
#ifndef os_strstr
#define os_strstr(h, n) strstr((h), (n))
#endif
#ifndef os_snprintf
#ifdef _MSC_VER
#define os_snprintf _snprintf
#else
#define os_snprintf snprintf
#endif
#endif
#endif /* OS_NO_C_LIB_DEFINES */
static inline int os_snprintf_error(size_t size, int res)
{
return res < 0 || (unsigned int) res >= size;
}
static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size)
{
if (size && nmemb > (~(size_t) 0) / size)
return NULL;
return os_realloc(ptr, nmemb * size);
}
/**
* os_remove_in_array - Remove a member from an array by index
* @ptr: Pointer to the array
* @nmemb: Current member count of the array
* @size: The size per member of the array
* @idx: Index of the member to be removed
*/
static inline void os_remove_in_array(void *ptr, size_t nmemb, size_t size,
size_t idx)
{
if (idx < nmemb - 1)
os_memmove(((unsigned char *) ptr) + idx * size,
((unsigned char *) ptr) + (idx + 1) * size,
(nmemb - idx - 1) * size);
}
/**
* os_strlcpy - Copy a string with size bound and NUL-termination
* @dest: Destination
* @src: Source
* @siz: Size of the target buffer
* Returns: Total length of the target string (length of src) (not including
* NUL-termination)
*
* This function matches in behavior with the strlcpy(3) function in OpenBSD.
*/
size_t os_strlcpy(char *dest, const char *src, size_t siz);
/**
* os_memcmp_const - Constant time memory comparison
* @a: First buffer to compare
* @b: Second buffer to compare
* @len: Number of octets to compare
* Returns: 0 if buffers are equal, non-zero if not
*
* This function is meant for comparing passwords or hash values where
* difference in execution time could provide external observer information
* about the location of the difference in the memory buffers. The return value
* does not behave like os_memcmp(), i.e., os_memcmp_const() cannot be used to
* sort items into a defined order. Unlike os_memcmp(), execution time of
* os_memcmp_const() does not depend on the contents of the compared memory
* buffers, but only on the total compared length.
*/
int os_memcmp_const(const void *a, const void *b, size_t len);
/**
* os_exec - Execute an external program
* @program: Path to the program
* @arg: Command line argument string
* @wait_completion: Whether to wait until the program execution completes
* Returns: 0 on success, -1 on error
*/
int os_exec(const char *program, const char *arg, int wait_completion);
#ifdef OS_REJECT_C_LIB_FUNCTIONS
#define malloc OS_DO_NOT_USE_malloc
#define realloc OS_DO_NOT_USE_realloc
#define free OS_DO_NOT_USE_free
#define memcpy OS_DO_NOT_USE_memcpy
#define memmove OS_DO_NOT_USE_memmove
#define memset OS_DO_NOT_USE_memset
#define memcmp OS_DO_NOT_USE_memcmp
#undef strdup
#define strdup OS_DO_NOT_USE_strdup
#define strlen OS_DO_NOT_USE_strlen
#define strcasecmp OS_DO_NOT_USE_strcasecmp
#define strncasecmp OS_DO_NOT_USE_strncasecmp
#undef strchr
#define strchr OS_DO_NOT_USE_strchr
#undef strcmp
#define strcmp OS_DO_NOT_USE_strcmp
#undef strncmp
#define strncmp OS_DO_NOT_USE_strncmp
#undef strncpy
#define strncpy OS_DO_NOT_USE_strncpy
#define strrchr OS_DO_NOT_USE_strrchr
#define strstr OS_DO_NOT_USE_strstr
#undef snprintf
#define snprintf OS_DO_NOT_USE_snprintf
#define strcpy OS_DO_NOT_USE_strcpy
#endif /* OS_REJECT_C_LIB_FUNCTIONS */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* OS_H */

View File

@@ -0,0 +1,69 @@
/*
* Backtrace debugging
* Copyright (c) 2009, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef TRACE_H
#define TRACE_H
#define WPA_TRACE_LEN 16
#ifdef WPA_TRACE
#include <execinfo.h>
#include "list.h"
#define WPA_TRACE_INFO void *btrace[WPA_TRACE_LEN]; int btrace_num;
struct wpa_trace_ref {
struct dl_list list;
const void *addr;
WPA_TRACE_INFO
};
#define WPA_TRACE_REF(name) struct wpa_trace_ref wpa_trace_ref_##name
#define wpa_trace_dump(title, ptr) \
wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num)
void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num);
#define wpa_trace_record(ptr) \
(ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN)
void wpa_trace_show(const char *title);
#define wpa_trace_add_ref(ptr, name, addr) \
wpa_trace_add_ref_func(&(ptr)->wpa_trace_ref_##name, (addr))
void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr);
#define wpa_trace_remove_ref(ptr, name, addr) \
do { \
if ((addr)) \
dl_list_del(&(ptr)->wpa_trace_ref_##name.list); \
} while (0)
void wpa_trace_check_ref(const void *addr);
size_t wpa_trace_calling_func(const char *buf[], size_t len);
#else /* WPA_TRACE */
#define WPA_TRACE_INFO
#define WPA_TRACE_REF(n)
#define wpa_trace_dump(title, ptr) do { } while (0)
#define wpa_trace_record(ptr) do { } while (0)
#define wpa_trace_show(title) do { } while (0)
#define wpa_trace_add_ref(ptr, name, addr) do { } while (0)
#define wpa_trace_remove_ref(ptr, name, addr) do { } while (0)
#define wpa_trace_check_ref(addr) do { } while (0)
#endif /* WPA_TRACE */
#ifdef WPA_TRACE_BFD
void wpa_trace_dump_funcname(const char *title, void *pc);
#else /* WPA_TRACE_BFD */
#define wpa_trace_dump_funcname(title, pc) do { } while (0)
#endif /* WPA_TRACE_BFD */
#endif /* TRACE_H */

View File

@@ -0,0 +1,375 @@
/*
* wpa_supplicant/hostapd / Debug prints
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_DEBUG_H
#define WPA_DEBUG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "wpabuf.h"
extern int wpa_debug_level;
extern int wpa_debug_show_keys;
extern int wpa_debug_timestamp;
/* Debugging function - conditional printf and hex dump. Driver wrappers can
* use these for debugging purposes. */
enum {
MSG_EXCESSIVE, MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR
};
#ifdef CONFIG_NO_STDOUT_DEBUG
#define wpa_debug_print_timestamp() do { } while (0)
#define wpa_printf(args...) do { } while (0)
#define wpa_hexdump(l,t,b,le) do { } while (0)
#define wpa_hexdump_buf(l,t,b) do { } while (0)
#define wpa_hexdump_key(l,t,b,le) do { } while (0)
#define wpa_hexdump_buf_key(l,t,b) do { } while (0)
#define wpa_hexdump_ascii(l,t,b,le) do { } while (0)
#define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0)
#define wpa_debug_open_file(p) do { } while (0)
#define wpa_debug_close_file() do { } while (0)
#define wpa_debug_setup_stdout() do { } while (0)
#define wpa_dbg(args...) do { } while (0)
static inline int wpa_debug_reopen_file(void)
{
return 0;
}
#else /* CONFIG_NO_STDOUT_DEBUG */
int wpa_debug_open_file(const char *path);
int wpa_debug_reopen_file(void);
void wpa_debug_close_file(void);
void wpa_debug_setup_stdout(void);
/**
* wpa_debug_printf_timestamp - Print timestamp for debug output
*
* This function prints a timestamp in seconds_from_1970.microsoconds
* format if debug output has been configured to include timestamps in debug
* messages.
*/
void wpa_debug_print_timestamp(void);
/**
* wpa_printf - conditional printf
* @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. The
* output may be directed to stdout, stderr, and/or syslog based on
* configuration.
*
* Note: New line '\n' is added to the end of the text when printing to stdout.
*/
void wpa_printf(int level, const char *fmt, ...)
PRINTF_FORMAT(2, 3);
/**
* wpa_hexdump - conditional hex dump
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
* @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
* configuration. The contents of buf is printed out has hex dump.
*/
void wpa_hexdump(int level, const char *title, const void *buf, size_t len);
static inline void wpa_hexdump_buf(int level, const char *title,
const struct wpabuf *buf)
{
wpa_hexdump(level, title, buf ? wpabuf_head(buf) : NULL,
buf ? wpabuf_len(buf) : 0);
}
/**
* wpa_hexdump_key - conditional hex dump, hide keys
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
* @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
* configuration. The contents of buf is printed out has hex dump. This works
* like wpa_hexdump(), but by default, does not include secret keys (passwords,
* etc.) in debug output.
*/
void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len);
static inline void wpa_hexdump_buf_key(int level, const char *title,
const struct wpabuf *buf)
{
wpa_hexdump_key(level, title, buf ? wpabuf_head(buf) : NULL,
buf ? wpabuf_len(buf) : 0);
}
/**
* wpa_hexdump_ascii - conditional hex dump
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
* @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
* configuration. The contents of buf is printed out has hex dump with both
* the hex numbers and ASCII characters (for printable range) are shown. 16
* bytes per line will be shown.
*/
void wpa_hexdump_ascii(int level, const char *title, const void *buf,
size_t len);
/**
* wpa_hexdump_ascii_key - conditional hex dump, hide keys
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
* @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
* configuration. The contents of buf is printed out has hex dump with both
* the hex numbers and ASCII characters (for printable range) are shown. 16
* bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
* default, does not include secret keys (passwords, etc.) in debug output.
*/
void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
size_t len);
/*
* wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce
* binary size. As such, it should be used with debugging messages that are not
* needed in the control interface while wpa_msg() has to be used for anything
* that needs to shown to control interface monitors.
*/
#define wpa_dbg(args...) wpa_msg(args)
#endif /* CONFIG_NO_STDOUT_DEBUG */
#ifdef CONFIG_NO_WPA_MSG
#define wpa_msg(args...) do { } while (0)
#define wpa_msg_ctrl(args...) do { } while (0)
#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 */
/**
* wpa_msg - Conditional printf for default target and 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. The
* output may be directed to stdout, stderr, and/or syslog based on
* configuration. This function is like wpa_printf(), but it also sends the
* same message to all attached ctrl_iface monitors.
*
* Note: New line '\n' is added to the end of the text when printing to stdout.
*/
void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
/**
* wpa_msg_ctrl - 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(), but it sends the output only to the
* attached ctrl_iface monitors. In other words, it can be used for frequent
* events that do not need to be sent to syslog.
*/
void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
PRINTF_FORMAT(3, 4);
/**
* wpa_msg_global - Global 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(), but it sends the output as a global event,
* i.e., without being specific to an interface. For backwards compatibility,
* an old style event is also delivered on one of the interfaces (the one
* specified by the context data).
*/
void wpa_msg_global(void *ctx, int level, const char *fmt, ...)
PRINTF_FORMAT(3, 4);
/**
* wpa_msg_global_ctrl - Conditional global 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 to the
* attached global ctrl_iface monitors. In other words, it can be used for
* frequent events that do not need to be sent to syslog.
*/
void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...)
PRINTF_FORMAT(3, 4);
/**
* wpa_msg_no_global - 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(), but it does not send the output as a global
* event.
*/
void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...)
PRINTF_FORMAT(3, 4);
/**
* 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);
/**
* wpa_msg_register_cb - Register callback function for wpa_msg() messages
* @func: Callback function (%NULL to unregister)
*/
void wpa_msg_register_cb(wpa_msg_cb_func func);
typedef const char * (*wpa_msg_get_ifname_func)(void *ctx);
void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func);
#endif /* CONFIG_NO_WPA_MSG */
#ifdef CONFIG_NO_HOSTAPD_LOGGER
#define hostapd_logger(args...) do { } while (0)
#define hostapd_logger_register_cb(f) do { } while (0)
#else /* CONFIG_NO_HOSTAPD_LOGGER */
void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
const char *fmt, ...) PRINTF_FORMAT(5, 6);
typedef void (*hostapd_logger_cb_func)(void *ctx, const u8 *addr,
unsigned int module, int level,
const char *txt, size_t len);
/**
* hostapd_logger_register_cb - Register callback function for hostapd_logger()
* @func: Callback function (%NULL to unregister)
*/
void hostapd_logger_register_cb(hostapd_logger_cb_func func);
#endif /* CONFIG_NO_HOSTAPD_LOGGER */
#define HOSTAPD_MODULE_IEEE80211 0x00000001
#define HOSTAPD_MODULE_IEEE8021X 0x00000002
#define HOSTAPD_MODULE_RADIUS 0x00000004
#define HOSTAPD_MODULE_WPA 0x00000008
#define HOSTAPD_MODULE_DRIVER 0x00000010
#define HOSTAPD_MODULE_IAPP 0x00000020
#define HOSTAPD_MODULE_MLME 0x00000040
enum hostapd_logger_level {
HOSTAPD_LEVEL_DEBUG_VERBOSE = 0,
HOSTAPD_LEVEL_DEBUG = 1,
HOSTAPD_LEVEL_INFO = 2,
HOSTAPD_LEVEL_NOTICE = 3,
HOSTAPD_LEVEL_WARNING = 4
};
#ifdef CONFIG_DEBUG_SYSLOG
void wpa_debug_open_syslog(void);
void wpa_debug_close_syslog(void);
#else /* CONFIG_DEBUG_SYSLOG */
static inline void wpa_debug_open_syslog(void)
{
}
static inline void wpa_debug_close_syslog(void)
{
}
#endif /* CONFIG_DEBUG_SYSLOG */
#ifdef CONFIG_DEBUG_LINUX_TRACING
int wpa_debug_open_linux_tracing(void);
void wpa_debug_close_linux_tracing(void);
#else /* CONFIG_DEBUG_LINUX_TRACING */
static inline int wpa_debug_open_linux_tracing(void)
{
return 0;
}
static inline void wpa_debug_close_linux_tracing(void)
{
}
#endif /* CONFIG_DEBUG_LINUX_TRACING */
#ifdef EAPOL_TEST
#define WPA_ASSERT(a) \
do { \
if (!(a)) { \
printf("WPA_ASSERT FAILED '" #a "' " \
"%s %s:%d\n", \
__FUNCTION__, __FILE__, __LINE__); \
exit(1); \
} \
} while (0)
#else
#define WPA_ASSERT(a) do { } while (0)
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WPA_DEBUG_H */

View File

@@ -0,0 +1,163 @@
/*
* Dynamic data buffer
* Copyright (c) 2007-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPABUF_H
#define WPABUF_H
/* wpabuf::buf is a pointer to external data */
#define WPABUF_FLAG_EXT_DATA BIT(0)
/*
* Internal data structure for wpabuf. Please do not touch this directly from
* elsewhere. This is only defined in header file to allow inline functions
* from this file to access data.
*/
struct wpabuf {
size_t size; /* total size of the allocated buffer */
size_t used; /* length of data in the buffer */
u8 *buf; /* pointer to the head of the buffer */
unsigned int flags;
/* optionally followed by the allocated buffer */
};
int wpabuf_resize(struct wpabuf **buf, size_t add_len);
struct wpabuf * wpabuf_alloc(size_t len);
struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len);
struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len);
struct wpabuf * wpabuf_dup(const struct wpabuf *src);
void wpabuf_free(struct wpabuf *buf);
void wpabuf_clear_free(struct wpabuf *buf);
void * wpabuf_put(struct wpabuf *buf, size_t len);
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len);
void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3);
/**
* wpabuf_size - Get the currently allocated size of a wpabuf buffer
* @buf: wpabuf buffer
* Returns: Currently allocated size of the buffer
*/
static inline size_t wpabuf_size(const struct wpabuf *buf)
{
return buf->size;
}
/**
* wpabuf_len - Get the current length of a wpabuf buffer data
* @buf: wpabuf buffer
* Returns: Currently used length of the buffer
*/
static inline size_t wpabuf_len(const struct wpabuf *buf)
{
return buf->used;
}
/**
* wpabuf_tailroom - Get size of available tail room in the end of the buffer
* @buf: wpabuf buffer
* Returns: Tail room (in bytes) of available space in the end of the buffer
*/
static inline size_t wpabuf_tailroom(const struct wpabuf *buf)
{
return buf->size - buf->used;
}
/**
* wpabuf_head - Get pointer to the head of the buffer data
* @buf: wpabuf buffer
* Returns: Pointer to the head of the buffer data
*/
static inline const void * wpabuf_head(const struct wpabuf *buf)
{
return buf->buf;
}
static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf)
{
return (const u8 *)wpabuf_head(buf);
}
/**
* wpabuf_mhead - Get modifiable pointer to the head of the buffer data
* @buf: wpabuf buffer
* Returns: Pointer to the head of the buffer data
*/
static inline void * wpabuf_mhead(struct wpabuf *buf)
{
return buf->buf;
}
static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf)
{
return (u8 *)wpabuf_mhead(buf);
}
static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data)
{
u8 *pos = (u8 *)wpabuf_put(buf, 1);
*pos = data;
}
static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data)
{
u8 *pos = (u8 *)wpabuf_put(buf, 2);
WPA_PUT_LE16(pos, data);
}
static inline void wpabuf_put_le32(struct wpabuf *buf, u32 data)
{
u8 *pos = (u8 *)wpabuf_put(buf, 4);
WPA_PUT_LE32(pos, data);
}
static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data)
{
u8 *pos = (u8 *)wpabuf_put(buf, 2);
WPA_PUT_BE16(pos, data);
}
static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data)
{
u8 *pos = (u8 *)wpabuf_put(buf, 3);
WPA_PUT_BE24(pos, data);
}
static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data)
{
u8 *pos = (u8 *)wpabuf_put(buf, 4);
WPA_PUT_BE32(pos, data);
}
static inline void wpabuf_put_data(struct wpabuf *buf, const void *data,
size_t len)
{
if (data)
os_memcpy(wpabuf_put(buf, len), data, len);
}
static inline void wpabuf_put_buf(struct wpabuf *dst,
const struct wpabuf *src)
{
wpabuf_put_data(dst, wpabuf_head(src), wpabuf_len(src));
}
static inline void wpabuf_set(struct wpabuf *buf, const void *data, size_t len)
{
buf->buf = (u8 *) data;
buf->flags = WPABUF_FLAG_EXT_DATA;
buf->size = buf->used = len;
}
static inline void wpabuf_put_str(struct wpabuf *dst, const char *str)
{
wpabuf_put_data(dst, str, os_strlen(str));
}
#endif /* WPABUF_H */

View File

@@ -0,0 +1,733 @@
/*
* wpa_supplicant/hostapd control interface library
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#ifdef CONFIG_CTRL_IFACE
#ifdef CONFIG_CTRL_IFACE_UNIX
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
#include <netdb.h>
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#ifdef ANDROID
#include <dirent.h>
#include <sys/stat.h>
#include <cutils/sockets.h>
#include "cutils/android_filesystem_config.h"
#endif /* ANDROID */
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
#include <net/if.h>
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
#include "wpa_ctrl.h"
#include "common.h"
#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
#define CTRL_IFACE_SOCKET
#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
/**
* struct wpa_ctrl - Internal structure for control interface library
*
* This structure is used by the wpa_supplicant/hostapd control interface
* library to store internal data. Programs using the library should not touch
* this data directly. They can only use the pointer to the data structure as
* an identifier for the control interface connection and use this as one of
* the arguments for most of the control interface library functions.
*/
struct wpa_ctrl {
#ifdef CONFIG_CTRL_IFACE_UDP
int s;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 local;
struct sockaddr_in6 dest;
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in local;
struct sockaddr_in dest;
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
char *cookie;
char *remote_ifname;
char *remote_ip;
#endif /* CONFIG_CTRL_IFACE_UDP */
#ifdef CONFIG_CTRL_IFACE_UNIX
int s;
struct sockaddr_un local;
struct sockaddr_un dest;
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
HANDLE pipe;
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
};
#ifdef CONFIG_CTRL_IFACE_UNIX
#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
#define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
#endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
#endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
struct wpa_ctrl *ctrl;
static int counter = 0;
int ret;
size_t res;
int tries = 0;
int flags;
if (ctrl_path == NULL)
return NULL;
ctrl = os_zalloc(sizeof(*ctrl));
if (ctrl == NULL)
return NULL;
ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (ctrl->s < 0) {
os_free(ctrl);
return NULL;
}
ctrl->local.sun_family = AF_UNIX;
counter++;
try_again:
ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
CONFIG_CTRL_IFACE_CLIENT_DIR "/"
CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
(int) getpid(), counter);
if (os_snprintf_error(sizeof(ctrl->local.sun_path), ret)) {
close(ctrl->s);
os_free(ctrl);
return NULL;
}
tries++;
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
sizeof(ctrl->local)) < 0) {
if (errno == EADDRINUSE && tries < 2) {
/*
* getpid() returns unique identifier for this instance
* of wpa_ctrl, so the existing socket file must have
* been left by unclean termination of an earlier run.
* Remove the file and try again.
*/
unlink(ctrl->local.sun_path);
goto try_again;
}
close(ctrl->s);
os_free(ctrl);
return NULL;
}
#ifdef ANDROID
chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
if (os_strncmp(ctrl_path, "@android:", 9) == 0) {
if (socket_local_client_connect(
ctrl->s, ctrl_path + 9,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_DGRAM) < 0) {
close(ctrl->s);
unlink(ctrl->local.sun_path);
os_free(ctrl);
return NULL;
}
return ctrl;
}
/*
* If the ctrl_path isn't an absolute pathname, assume that
* it's the name of a socket in the Android reserved namespace.
* Otherwise, it's a normal UNIX domain socket appearing in the
* filesystem.
*/
if (*ctrl_path != '/') {
char buf[21];
os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
if (socket_local_client_connect(
ctrl->s, buf,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_DGRAM) < 0) {
close(ctrl->s);
unlink(ctrl->local.sun_path);
os_free(ctrl);
return NULL;
}
return ctrl;
}
#endif /* ANDROID */
ctrl->dest.sun_family = AF_UNIX;
if (os_strncmp(ctrl_path, "@abstract:", 10) == 0) {
ctrl->dest.sun_path[0] = '\0';
os_strlcpy(ctrl->dest.sun_path + 1, ctrl_path + 10,
sizeof(ctrl->dest.sun_path) - 1);
} else {
res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
sizeof(ctrl->dest.sun_path));
if (res >= sizeof(ctrl->dest.sun_path)) {
close(ctrl->s);
os_free(ctrl);
return NULL;
}
}
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
close(ctrl->s);
unlink(ctrl->local.sun_path);
os_free(ctrl);
return NULL;
}
/*
* Make socket non-blocking so that we don't hang forever if
* target dies unexpectedly.
*/
flags = fcntl(ctrl->s, F_GETFL);
if (flags >= 0) {
flags |= O_NONBLOCK;
if (fcntl(ctrl->s, F_SETFL, flags) < 0) {
perror("fcntl(ctrl->s, O_NONBLOCK)");
/* Not fatal, continue on.*/
}
}
return ctrl;
}
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
if (ctrl == NULL)
return;
unlink(ctrl->local.sun_path);
if (ctrl->s >= 0)
close(ctrl->s);
os_free(ctrl);
}
#ifdef ANDROID
/**
* wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
* may be left over from clients that were previously connected to
* wpa_supplicant. This keeps these files from being orphaned in the
* event of crashes that prevented them from being removed as part
* of the normal orderly shutdown.
*/
void wpa_ctrl_cleanup(void)
{
DIR *dir;
struct dirent entry;
struct dirent *result;
size_t dirnamelen;
size_t maxcopy;
char pathname[PATH_MAX];
char *namep;
if ((dir = opendir(CONFIG_CTRL_IFACE_CLIENT_DIR)) == NULL)
return;
dirnamelen = (size_t) os_snprintf(pathname, sizeof(pathname), "%s/",
CONFIG_CTRL_IFACE_CLIENT_DIR);
if (dirnamelen >= sizeof(pathname)) {
closedir(dir);
return;
}
namep = pathname + dirnamelen;
maxcopy = PATH_MAX - dirnamelen;
while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
if (os_strlcpy(namep, entry.d_name, maxcopy) < maxcopy)
unlink(pathname);
}
closedir(dir);
}
#endif /* ANDROID */
#else /* CONFIG_CTRL_IFACE_UNIX */
#ifdef ANDROID
void wpa_ctrl_cleanup(void)
{
}
#endif /* ANDROID */
#endif /* CONFIG_CTRL_IFACE_UNIX */
#ifdef CONFIG_CTRL_IFACE_UDP
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
struct wpa_ctrl *ctrl;
char buf[128];
size_t len;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
struct hostent *h;
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
ctrl = os_zalloc(sizeof(*ctrl));
if (ctrl == NULL)
return NULL;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (ctrl->s < 0) {
perror("socket");
os_free(ctrl);
return NULL;
}
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
ctrl->local.sin6_family = AF_INET6;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
ctrl->local.sin6_addr = in6addr_any;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
inet_pton(AF_INET6, "::1", &ctrl->local.sin6_addr);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
ctrl->local.sin_family = AF_INET;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
ctrl->local.sin_addr.s_addr = INADDR_ANY;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
sizeof(ctrl->local)) < 0) {
close(ctrl->s);
os_free(ctrl);
return NULL;
}
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
ctrl->dest.sin6_family = AF_INET6;
inet_pton(AF_INET6, "::1", &ctrl->dest.sin6_addr);
ctrl->dest.sin6_port = htons(WPA_CTRL_IFACE_PORT);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
ctrl->dest.sin_family = AF_INET;
ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
if (ctrl_path) {
char *port, *name;
int port_id;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
char *scope;
int scope_id = 0;
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
name = os_strdup(ctrl_path);
if (name == NULL) {
close(ctrl->s);
os_free(ctrl);
return NULL;
}
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
port = os_strchr(name, ',');
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
port = os_strchr(name, ':');
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (port) {
port_id = atoi(&port[1]);
port[0] = '\0';
} else
port_id = WPA_CTRL_IFACE_PORT;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
scope = os_strchr(name, '%');
if (scope) {
scope_id = if_nametoindex(&scope[1]);
scope[0] = '\0';
}
h = gethostbyname2(name, AF_INET6);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
h = gethostbyname(name);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
ctrl->remote_ip = os_strdup(name);
os_free(name);
if (h == NULL) {
perror("gethostbyname");
close(ctrl->s);
os_free(ctrl->remote_ip);
os_free(ctrl);
return NULL;
}
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
ctrl->dest.sin6_scope_id = scope_id;
ctrl->dest.sin6_port = htons(port_id);
os_memcpy(&ctrl->dest.sin6_addr, h->h_addr, h->h_length);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
ctrl->dest.sin_port = htons(port_id);
os_memcpy(&ctrl->dest.sin_addr.s_addr, h->h_addr, h->h_length);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
} else
ctrl->remote_ip = os_strdup("localhost");
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
char addr[INET6_ADDRSTRLEN];
wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s",
inet_ntop(AF_INET6, &ctrl->dest.sin6_addr, addr,
sizeof(ctrl->dest)),
ntohs(ctrl->dest.sin6_port),
strerror(errno));
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s",
inet_ntoa(ctrl->dest.sin_addr),
ntohs(ctrl->dest.sin_port),
strerror(errno));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
close(ctrl->s);
os_free(ctrl->remote_ip);
os_free(ctrl);
return NULL;
}
len = sizeof(buf) - 1;
if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
buf[len] = '\0';
ctrl->cookie = os_strdup(buf);
}
if (wpa_ctrl_request(ctrl, "IFNAME", 6, buf, &len, NULL) == 0) {
buf[len] = '\0';
ctrl->remote_ifname = os_strdup(buf);
}
return ctrl;
}
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl)
{
#define WPA_CTRL_MAX_PS_NAME 100
static char ps[WPA_CTRL_MAX_PS_NAME] = {};
os_snprintf(ps, WPA_CTRL_MAX_PS_NAME, "%s/%s",
ctrl->remote_ip, ctrl->remote_ifname);
return ps;
}
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
close(ctrl->s);
os_free(ctrl->cookie);
os_free(ctrl->remote_ifname);
os_free(ctrl->remote_ip);
os_free(ctrl);
}
#endif /* CONFIG_CTRL_IFACE_UDP */
#ifdef CTRL_IFACE_SOCKET
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len))
{
struct timeval tv;
struct os_reltime started_at;
int res;
fd_set rfds;
const char *_cmd;
char *cmd_buf = NULL;
size_t _cmd_len;
#ifdef CONFIG_CTRL_IFACE_UDP
if (ctrl->cookie) {
char *pos;
_cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
cmd_buf = os_malloc(_cmd_len);
if (cmd_buf == NULL)
return -1;
_cmd = cmd_buf;
pos = cmd_buf;
os_strlcpy(pos, ctrl->cookie, _cmd_len);
pos += os_strlen(ctrl->cookie);
*pos++ = ' ';
os_memcpy(pos, cmd, cmd_len);
} else
#endif /* CONFIG_CTRL_IFACE_UDP */
{
_cmd = cmd;
_cmd_len = cmd_len;
}
errno = 0;
started_at.sec = 0;
started_at.usec = 0;
retry_send:
if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
if (errno == EAGAIN || errno == EBUSY || errno == EWOULDBLOCK)
{
/*
* Must be a non-blocking socket... Try for a bit
* longer before giving up.
*/
if (started_at.sec == 0)
os_get_reltime(&started_at);
else {
struct os_reltime n;
os_get_reltime(&n);
/* Try for a few seconds. */
if (os_reltime_expired(&n, &started_at, 5))
goto send_err;
}
os_sleep(1, 0);
goto retry_send;
}
send_err:
os_free(cmd_buf);
return -1;
}
os_free(cmd_buf);
for (;;) {
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
if (res < 0)
return res;
if (FD_ISSET(ctrl->s, &rfds)) {
res = recv(ctrl->s, reply, *reply_len, 0);
if (res < 0)
return res;
if (res > 0 && reply[0] == '<') {
/* This is an unsolicited message from
* wpa_supplicant, not the reply to the
* request. Use msg_cb to report this to the
* caller. */
if (msg_cb) {
/* Make sure the message is nul
* terminated. */
if ((size_t) res == *reply_len)
res = (*reply_len) - 1;
reply[res] = '\0';
msg_cb(reply, res);
}
continue;
}
*reply_len = res;
break;
} else {
return -2;
}
}
return 0;
}
#endif /* CTRL_IFACE_SOCKET */
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
{
char buf[10];
int ret;
size_t len = 10;
ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
buf, &len, NULL);
if (ret < 0)
return ret;
if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
return 0;
return -1;
}
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
{
return wpa_ctrl_attach_helper(ctrl, 1);
}
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
{
return wpa_ctrl_attach_helper(ctrl, 0);
}
#ifdef CTRL_IFACE_SOCKET
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
{
int res;
res = recv(ctrl->s, reply, *reply_len, 0);
if (res < 0)
return res;
*reply_len = res;
return 0;
}
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
{
struct timeval tv;
fd_set rfds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
return FD_ISSET(ctrl->s, &rfds);
}
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
{
return ctrl->s;
}
#endif /* CTRL_IFACE_SOCKET */
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
#ifndef WPA_SUPPLICANT_NAMED_PIPE
#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
#endif
#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
struct wpa_ctrl *ctrl;
DWORD mode;
TCHAR name[256];
int i, ret;
ctrl = os_malloc(sizeof(*ctrl));
if (ctrl == NULL)
return NULL;
os_memset(ctrl, 0, sizeof(*ctrl));
#ifdef UNICODE
if (ctrl_path == NULL)
ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
else
ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
ctrl_path);
#else /* UNICODE */
if (ctrl_path == NULL)
ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
else
ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
ctrl_path);
#endif /* UNICODE */
if (os_snprintf_error(256, ret)) {
os_free(ctrl);
return NULL;
}
for (i = 0; i < 10; i++) {
ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, NULL);
/*
* Current named pipe server side in wpa_supplicant is
* re-opening the pipe for new clients only after the previous
* one is taken into use. This leaves a small window for race
* conditions when two connections are being opened at almost
* the same time. Retry if that was the case.
*/
if (ctrl->pipe != INVALID_HANDLE_VALUE ||
GetLastError() != ERROR_PIPE_BUSY)
break;
WaitNamedPipe(name, 1000);
}
if (ctrl->pipe == INVALID_HANDLE_VALUE) {
os_free(ctrl);
return NULL;
}
mode = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
CloseHandle(ctrl->pipe);
os_free(ctrl);
return NULL;
}
return ctrl;
}
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
CloseHandle(ctrl->pipe);
os_free(ctrl);
}
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len))
{
DWORD written;
DWORD readlen = *reply_len;
if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
return -1;
if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
return -1;
*reply_len = readlen;
return 0;
}
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
{
DWORD len = *reply_len;
if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
return -1;
*reply_len = len;
return 0;
}
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
{
DWORD left;
if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
return -1;
return left ? 1 : 0;
}
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
{
return -1;
}
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
#endif /* CONFIG_CTRL_IFACE */

View File

@@ -0,0 +1,819 @@
/*
* wpa_supplicant/hostapd / Debug prints
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#ifdef CONFIG_DEBUG_SYSLOG
#include <syslog.h>
static int wpa_debug_syslog = 0;
#endif /* CONFIG_DEBUG_SYSLOG */
#ifdef CONFIG_DEBUG_LINUX_TRACING
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
static FILE *wpa_debug_tracing_file = NULL;
#define WPAS_TRACE_PFX "wpas <%d>: "
#endif /* CONFIG_DEBUG_LINUX_TRACING */
int wpa_debug_level = MSG_INFO;
int wpa_debug_show_keys = 0;
int wpa_debug_timestamp = 0;
#ifdef CONFIG_ANDROID_LOG
#include <android/log.h>
#ifndef ANDROID_LOG_NAME
#define ANDROID_LOG_NAME "wpa_supplicant"
#endif /* ANDROID_LOG_NAME */
static int wpa_to_android_level(int level)
{
if (level == MSG_ERROR)
return ANDROID_LOG_ERROR;
if (level == MSG_WARNING)
return ANDROID_LOG_WARN;
if (level == MSG_INFO)
return ANDROID_LOG_INFO;
return ANDROID_LOG_DEBUG;
}
#endif /* CONFIG_ANDROID_LOG */
#ifndef CONFIG_NO_STDOUT_DEBUG
#ifdef CONFIG_DEBUG_FILE
static FILE *out_file = NULL;
#endif /* CONFIG_DEBUG_FILE */
void wpa_debug_print_timestamp(void)
{
#ifndef CONFIG_ANDROID_LOG
struct os_time tv;
if (!wpa_debug_timestamp)
return;
os_get_time(&tv);
#ifdef CONFIG_DEBUG_FILE
if (out_file) {
fprintf(out_file, "%ld.%06u: ", (long) tv.sec,
(unsigned int) tv.usec);
} else
#endif /* CONFIG_DEBUG_FILE */
printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
#endif /* CONFIG_ANDROID_LOG */
}
#ifdef CONFIG_DEBUG_SYSLOG
#ifndef LOG_HOSTAPD
#define LOG_HOSTAPD LOG_DAEMON
#endif /* LOG_HOSTAPD */
void wpa_debug_open_syslog(void)
{
openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD);
wpa_debug_syslog++;
}
void wpa_debug_close_syslog(void)
{
if (wpa_debug_syslog)
closelog();
}
static int syslog_priority(int level)
{
switch (level) {
case MSG_MSGDUMP:
case MSG_DEBUG:
return LOG_DEBUG;
case MSG_INFO:
return LOG_NOTICE;
case MSG_WARNING:
return LOG_WARNING;
case MSG_ERROR:
return LOG_ERR;
}
return LOG_INFO;
}
#endif /* CONFIG_DEBUG_SYSLOG */
#ifdef CONFIG_DEBUG_LINUX_TRACING
int wpa_debug_open_linux_tracing(void)
{
int mounts, trace_fd;
char buf[4096] = {};
ssize_t buflen;
char *line, *tmp1, *path = NULL;
mounts = open("/proc/mounts", O_RDONLY);
if (mounts < 0) {
printf("no /proc/mounts\n");
return -1;
}
buflen = read(mounts, buf, sizeof(buf) - 1);
close(mounts);
if (buflen < 0) {
printf("failed to read /proc/mounts\n");
return -1;
}
line = strtok_r(buf, "\n", &tmp1);
while (line) {
char *tmp2, *tmp_path, *fstype;
/* "<dev> <mountpoint> <fs type> ..." */
strtok_r(line, " ", &tmp2);
tmp_path = strtok_r(NULL, " ", &tmp2);
fstype = strtok_r(NULL, " ", &tmp2);
if (strcmp(fstype, "debugfs") == 0) {
path = tmp_path;
break;
}
line = strtok_r(NULL, "\n", &tmp1);
}
if (path == NULL) {
printf("debugfs mountpoint not found\n");
return -1;
}
snprintf(buf, sizeof(buf) - 1, "%s/tracing/trace_marker", path);
trace_fd = open(buf, O_WRONLY);
if (trace_fd < 0) {
printf("failed to open trace_marker file\n");
return -1;
}
wpa_debug_tracing_file = fdopen(trace_fd, "w");
if (wpa_debug_tracing_file == NULL) {
close(trace_fd);
printf("failed to fdopen()\n");
return -1;
}
return 0;
}
void wpa_debug_close_linux_tracing(void)
{
if (wpa_debug_tracing_file == NULL)
return;
fclose(wpa_debug_tracing_file);
wpa_debug_tracing_file = NULL;
}
#endif /* CONFIG_DEBUG_LINUX_TRACING */
/**
* wpa_printf - conditional printf
* @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. The
* output may be directed to stdout, stderr, and/or syslog based on
* configuration.
*
* Note: New line '\n' is added to the end of the text when printing to stdout.
*/
void wpa_printf(int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (level >= wpa_debug_level) {
#ifdef CONFIG_ANDROID_LOG
__android_log_vprint(wpa_to_android_level(level),
ANDROID_LOG_NAME, fmt, ap);
#else /* CONFIG_ANDROID_LOG */
#ifdef CONFIG_DEBUG_SYSLOG
if (wpa_debug_syslog) {
vsyslog(syslog_priority(level), fmt, ap);
} else {
#endif /* CONFIG_DEBUG_SYSLOG */
wpa_debug_print_timestamp();
#ifdef CONFIG_DEBUG_FILE
if (out_file) {
vfprintf(out_file, fmt, ap);
fprintf(out_file, "\n");
} else {
#endif /* CONFIG_DEBUG_FILE */
vprintf(fmt, ap);
printf("\n");
#ifdef CONFIG_DEBUG_FILE
}
#endif /* CONFIG_DEBUG_FILE */
#ifdef CONFIG_DEBUG_SYSLOG
}
#endif /* CONFIG_DEBUG_SYSLOG */
#endif /* CONFIG_ANDROID_LOG */
}
va_end(ap);
#ifdef CONFIG_DEBUG_LINUX_TRACING
if (wpa_debug_tracing_file != NULL) {
va_start(ap, fmt);
fprintf(wpa_debug_tracing_file, WPAS_TRACE_PFX, level);
vfprintf(wpa_debug_tracing_file, fmt, ap);
fprintf(wpa_debug_tracing_file, "\n");
fflush(wpa_debug_tracing_file);
va_end(ap);
}
#endif /* CONFIG_DEBUG_LINUX_TRACING */
}
static void _wpa_hexdump(int level, const char *title, const u8 *buf,
size_t len, int show)
{
size_t i;
#ifdef CONFIG_DEBUG_LINUX_TRACING
if (wpa_debug_tracing_file != NULL) {
fprintf(wpa_debug_tracing_file,
WPAS_TRACE_PFX "%s - hexdump(len=%lu):",
level, title, (unsigned long) len);
if (buf == NULL) {
fprintf(wpa_debug_tracing_file, " [NULL]\n");
} else if (!show) {
fprintf(wpa_debug_tracing_file, " [REMOVED]\n");
} else {
for (i = 0; i < len; i++)
fprintf(wpa_debug_tracing_file,
" %02x", buf[i]);
}
fflush(wpa_debug_tracing_file);
}
#endif /* CONFIG_DEBUG_LINUX_TRACING */
if (level < wpa_debug_level)
return;
#ifdef CONFIG_ANDROID_LOG
{
const char *display;
char *strbuf = NULL;
size_t slen = len;
if (buf == NULL) {
display = " [NULL]";
} else if (len == 0) {
display = "";
} else if (show && len) {
/* Limit debug message length for Android log */
if (slen > 32)
slen = 32;
strbuf = os_malloc(1 + 3 * slen);
if (strbuf == NULL) {
wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to "
"allocate message buffer");
return;
}
for (i = 0; i < slen; i++)
os_snprintf(&strbuf[i * 3], 4, " %02x",
buf[i]);
display = strbuf;
} else {
display = " [REMOVED]";
}
__android_log_print(wpa_to_android_level(level),
ANDROID_LOG_NAME,
"%s - hexdump(len=%lu):%s%s",
title, (long unsigned int) len, display,
len > slen ? " ..." : "");
os_free(strbuf);
return;
}
#else /* CONFIG_ANDROID_LOG */
#ifdef CONFIG_DEBUG_SYSLOG
if (wpa_debug_syslog) {
const char *display;
char *strbuf = NULL;
if (buf == NULL) {
display = " [NULL]";
} else if (len == 0) {
display = "";
} else if (show && len) {
strbuf = os_malloc(1 + 3 * len);
if (strbuf == NULL) {
wpa_printf(MSG_ERROR, "wpa_hexdump: Failed to "
"allocate message buffer");
return;
}
for (i = 0; i < len; i++)
os_snprintf(&strbuf[i * 3], 4, " %02x",
buf[i]);
display = strbuf;
} else {
display = " [REMOVED]";
}
syslog(syslog_priority(level), "%s - hexdump(len=%lu):%s",
title, (unsigned long) len, display);
os_free(strbuf);
return;
}
#endif /* CONFIG_DEBUG_SYSLOG */
wpa_debug_print_timestamp();
#ifdef CONFIG_DEBUG_FILE
if (out_file) {
fprintf(out_file, "%s - hexdump(len=%lu):",
title, (unsigned long) len);
if (buf == NULL) {
fprintf(out_file, " [NULL]");
} else if (show) {
for (i = 0; i < len; i++)
fprintf(out_file, " %02x", buf[i]);
} else {
fprintf(out_file, " [REMOVED]");
}
fprintf(out_file, "\n");
} else {
#endif /* CONFIG_DEBUG_FILE */
printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
if (buf == NULL) {
printf(" [NULL]");
} else if (show) {
for (i = 0; i < len; i++)
printf(" %02x", buf[i]);
} else {
printf(" [REMOVED]");
}
printf("\n");
#ifdef CONFIG_DEBUG_FILE
}
#endif /* CONFIG_DEBUG_FILE */
#endif /* CONFIG_ANDROID_LOG */
}
void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
{
_wpa_hexdump(level, title, buf, len, 1);
}
void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len)
{
_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
}
static void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
size_t len, int show)
{
size_t i, llen;
const u8 *pos = buf;
const size_t line_len = 16;
#ifdef CONFIG_DEBUG_LINUX_TRACING
if (wpa_debug_tracing_file != NULL) {
fprintf(wpa_debug_tracing_file,
WPAS_TRACE_PFX "%s - hexdump_ascii(len=%lu):",
level, title, (unsigned long) len);
if (buf == NULL) {
fprintf(wpa_debug_tracing_file, " [NULL]\n");
} else if (!show) {
fprintf(wpa_debug_tracing_file, " [REMOVED]\n");
} else {
/* can do ascii processing in userspace */
for (i = 0; i < len; i++)
fprintf(wpa_debug_tracing_file,
" %02x", pos[i]);
}
fflush(wpa_debug_tracing_file);
}
#endif /* CONFIG_DEBUG_LINUX_TRACING */
if (level < wpa_debug_level)
return;
#ifdef CONFIG_ANDROID_LOG
_wpa_hexdump(level, title, buf, len, show);
#else /* CONFIG_ANDROID_LOG */
wpa_debug_print_timestamp();
#ifdef CONFIG_DEBUG_FILE
if (out_file) {
if (!show) {
fprintf(out_file,
"%s - hexdump_ascii(len=%lu): [REMOVED]\n",
title, (unsigned long) len);
return;
}
if (buf == NULL) {
fprintf(out_file,
"%s - hexdump_ascii(len=%lu): [NULL]\n",
title, (unsigned long) len);
return;
}
fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n",
title, (unsigned long) len);
while (len) {
llen = len > line_len ? line_len : len;
fprintf(out_file, " ");
for (i = 0; i < llen; i++)
fprintf(out_file, " %02x", pos[i]);
for (i = llen; i < line_len; i++)
fprintf(out_file, " ");
fprintf(out_file, " ");
for (i = 0; i < llen; i++) {
if (isprint(pos[i]))
fprintf(out_file, "%c", pos[i]);
else
fprintf(out_file, "_");
}
for (i = llen; i < line_len; i++)
fprintf(out_file, " ");
fprintf(out_file, "\n");
pos += llen;
len -= llen;
}
} else {
#endif /* CONFIG_DEBUG_FILE */
if (!show) {
printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n",
title, (unsigned long) len);
return;
}
if (buf == NULL) {
printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
title, (unsigned long) len);
return;
}
printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
while (len) {
llen = len > line_len ? line_len : len;
printf(" ");
for (i = 0; i < llen; i++)
printf(" %02x", pos[i]);
for (i = llen; i < line_len; i++)
printf(" ");
printf(" ");
for (i = 0; i < llen; i++) {
if (isprint(pos[i]))
printf("%c", pos[i]);
else
printf("_");
}
for (i = llen; i < line_len; i++)
printf(" ");
printf("\n");
pos += llen;
len -= llen;
}
#ifdef CONFIG_DEBUG_FILE
}
#endif /* CONFIG_DEBUG_FILE */
#endif /* CONFIG_ANDROID_LOG */
}
void wpa_hexdump_ascii(int level, const char *title, const void *buf,
size_t len)
{
_wpa_hexdump_ascii(level, title, buf, len, 1);
}
void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
size_t len)
{
_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
}
#ifdef CONFIG_DEBUG_FILE
static char *last_path = NULL;
#endif /* CONFIG_DEBUG_FILE */
int wpa_debug_reopen_file(void)
{
#ifdef CONFIG_DEBUG_FILE
int rv;
if (last_path) {
char *tmp = os_strdup(last_path);
wpa_debug_close_file();
rv = wpa_debug_open_file(tmp);
os_free(tmp);
} else {
wpa_printf(MSG_ERROR, "Last-path was not set, cannot "
"re-open log file.");
rv = -1;
}
return rv;
#else /* CONFIG_DEBUG_FILE */
return 0;
#endif /* CONFIG_DEBUG_FILE */
}
int wpa_debug_open_file(const char *path)
{
#ifdef CONFIG_DEBUG_FILE
if (!path)
return 0;
if (last_path == NULL || os_strcmp(last_path, path) != 0) {
/* Save our path to enable re-open */
os_free(last_path);
last_path = os_strdup(path);
}
out_file = fopen(path, "a");
if (out_file == NULL) {
wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
"output file, using standard output");
return -1;
}
#ifndef _WIN32
setvbuf(out_file, NULL, _IOLBF, 0);
#endif /* _WIN32 */
#else /* CONFIG_DEBUG_FILE */
(void)path;
#endif /* CONFIG_DEBUG_FILE */
return 0;
}
void wpa_debug_close_file(void)
{
#ifdef CONFIG_DEBUG_FILE
if (!out_file)
return;
fclose(out_file);
out_file = NULL;
os_free(last_path);
last_path = NULL;
#endif /* CONFIG_DEBUG_FILE */
}
void wpa_debug_setup_stdout(void)
{
#ifndef _WIN32
setvbuf(stdout, NULL, _IOLBF, 0);
#endif /* _WIN32 */
}
#endif /* CONFIG_NO_STDOUT_DEBUG */
#ifndef CONFIG_NO_WPA_MSG
static wpa_msg_cb_func wpa_msg_cb = NULL;
void wpa_msg_register_cb(wpa_msg_cb_func func)
{
wpa_msg_cb = func;
}
static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL;
void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func)
{
wpa_msg_ifname_cb = func;
}
void wpa_msg(void *ctx, int level, const char *fmt, ...)
{
va_list ap;
char *buf;
int buflen;
int len;
char prefix[130];
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, "wpa_msg: Failed to allocate message "
"buffer");
return;
}
va_start(ap, fmt);
prefix[0] = '\0';
if (wpa_msg_ifname_cb) {
const char *ifname = wpa_msg_ifname_cb(ctx);
if (ifname) {
int res = os_snprintf(prefix, sizeof(prefix), "%s: ",
ifname);
if (os_snprintf_error(sizeof(prefix), res))
prefix[0] = '\0';
}
}
len = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
wpa_printf(level, "%s%s", prefix, buf);
if (wpa_msg_cb)
wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len);
os_free(buf);
}
void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
{
va_list ap;
char *buf;
int buflen;
int len;
if (!wpa_msg_cb)
return;
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, "wpa_msg_ctrl: Failed to allocate "
"message buffer");
return;
}
va_start(ap, fmt);
len = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
wpa_msg_cb(ctx, level, WPA_MSG_PER_INTERFACE, buf, len);
os_free(buf);
}
void wpa_msg_global(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, "wpa_msg_global: Failed to allocate "
"message buffer");
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_GLOBAL, buf, len);
os_free(buf);
}
void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...)
{
va_list ap;
char *buf;
int buflen;
int len;
if (!wpa_msg_cb)
return;
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,
"wpa_msg_global_ctrl: Failed to allocate message buffer");
return;
}
va_start(ap, fmt);
len = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
wpa_msg_cb(ctx, level, WPA_MSG_GLOBAL, buf, len);
os_free(buf);
}
void wpa_msg_no_global(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, "wpa_msg_no_global: Failed to allocate "
"message buffer");
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_NO_GLOBAL, buf, len);
os_free(buf);
}
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, "wpa_msg_no_global: Failed to allocate "
"message buffer");
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);
}
#endif /* CONFIG_NO_WPA_MSG */
#ifndef CONFIG_NO_HOSTAPD_LOGGER
static hostapd_logger_cb_func hostapd_logger_cb = NULL;
void hostapd_logger_register_cb(hostapd_logger_cb_func func)
{
hostapd_logger_cb = func;
}
void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, 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, "hostapd_logger: Failed to allocate "
"message buffer");
return;
}
va_start(ap, fmt);
len = vsnprintf(buf, buflen, fmt, ap);
va_end(ap);
if (hostapd_logger_cb)
hostapd_logger_cb(ctx, addr, module, level, buf, len);
else if (addr)
wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s",
MAC2STR(addr), buf);
else
wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
os_free(buf);
}
#endif /* CONFIG_NO_HOSTAPD_LOGGER */