blob: 3fd6c2cb7005990c8d8984c522c727fb2f8dcd1a [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "supp_events.h"
#include "includes.h"
#include "common.h"
#define MAC_STR_FORMAT "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
static const char * const supplicant_event_map[] = {
"CTRL-EVENT-CONNECTED",
"CTRL-EVENT-DISCONNECTED",
"CTRL-EVENT-ASSOC-REJECT",
"CTRL-EVENT-AUTH-REJECT",
"CTRL-EVENT-TERMINATING",
"CTRL-EVENT-SSID-TEMP-DISABLED",
"CTRL-EVENT-SSID-REENABLED",
"CTRL-EVENT-SCAN-STARTED",
"CTRL-EVENT-SCAN-RESULTS",
"CTRL-EVENT-SCAN-FAILED",
"CTRL-EVENT-BSS-ADDED",
"CTRL-EVENT-BSS-REMOVED",
"CTRL-EVENT-NETWORK-NOT-FOUND",
"CTRL-EVENT-NETWORK-ADDED",
"CTRL-EVENT-NETWORK-REMOVED",
"CTRL-EVENT-DSCP-POLICY",
};
static int supplicant_process_status(struct supplicant_int_event_data *event_data,
char *supplicant_status)
{
int ret = 1; /* For cases where parsing is not being done*/
int event = -1;
int i;
unsigned char *mac;
union supplicant_event_data *data;
data = (union supplicant_event_data *)event_data->data;
for (i = 0; i < ARRAY_SIZE(supplicant_event_map); i++) {
if (strncmp(supplicant_status, supplicant_event_map[i],
strlen(supplicant_event_map[i])) == 0) {
event = i;
break;
}
}
if (i >= ARRAY_SIZE(supplicant_event_map)) {
wpa_printf(MSG_ERROR, "Event not supported: %s\n", supplicant_status);
return -ENOTSUP;
}
event_data->event = event;
switch (event_data->event) {
case SUPPLICANT_EVENT_CONNECTED:
mac = data->connected.bssid;
ret = sscanf(supplicant_status +
sizeof("CTRL-EVENT-CONNECTED - Connection to") - 1,
MAC_STR_FORMAT,
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
event_data->data_len = sizeof(data->connected);
break;
case SUPPLICANT_EVENT_DISCONNECTED:
mac = data->disconnected.bssid;
ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-DISCONNECTED bssid=") - 1,
MAC_STR_FORMAT" reason=%d", &mac[0], &mac[1], &mac[2],
&mac[3], &mac[4], &mac[5], &data->disconnected.reason_code);
event_data->data_len = sizeof(data->disconnected);
break;
case SUPPLICANT_EVENT_ASSOC_REJECT:
/* TODO */
break;
case SUPPLICANT_EVENT_AUTH_REJECT:
mac = data->auth_reject.bssid;
ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-AUTH-REJECT ") - 1,
MAC_STR_FORMAT
" auth_type=%u auth_transaction=%u status_code=%u",
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5],
&data->auth_reject.auth_type,
&data->auth_reject.auth_transaction,
&data->auth_reject.status_code);
event_data->data_len = sizeof(data->auth_reject);
break;
case SUPPLICANT_EVENT_SSID_TEMP_DISABLED:
ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-SSID-TEMP-DISABLED ") - 1,
"id=%d ssid=%s auth_failures=%u duration=%d reason=%s",
&data->temp_disabled.id, data->temp_disabled.ssid,
&data->temp_disabled.auth_failures,
&data->temp_disabled.duration,
data->temp_disabled.reason_code);
event_data->data_len = sizeof(data->temp_disabled);
break;
case SUPPLICANT_EVENT_SSID_REENABLED:
ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-SSID-REENABLED ") - 1,
"id=%d ssid=%s", &data->reenabled.id,
data->reenabled.ssid);
event_data->data_len = sizeof(data->reenabled);
break;
case SUPPLICANT_EVENT_BSS_ADDED:
mac = data->bss_added.bssid;
ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-BSS-ADDED ") - 1,
"%u "MAC_STR_FORMAT,
&data->bss_added.id,
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
event_data->data_len = sizeof(data->bss_added);
break;
case SUPPLICANT_EVENT_BSS_REMOVED:
mac = data->bss_removed.bssid;
ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-BSS-REMOVED ") - 1,
"%u "MAC_STR_FORMAT,
&data->bss_removed.id,
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
event_data->data_len = sizeof(data->bss_removed);
break;
case SUPPLICANT_EVENT_TERMINATING:
case SUPPLICANT_EVENT_SCAN_STARTED:
case SUPPLICANT_EVENT_SCAN_FAILED:
case SUPPLICANT_EVENT_NETWORK_NOT_FOUND:
case SUPPLICANT_EVENT_NETWORK_ADDED:
case SUPPLICANT_EVENT_NETWORK_REMOVED:
strncpy(data->supplicant_event_str, supplicant_event_map[event],
sizeof(data->supplicant_event_str));
event_data->data_len = strlen(data->supplicant_event_str) + 1;
case SUPPLICANT_EVENT_DSCP_POLICY:
/* TODO */
break;
default:
break;
}
if (ret <= 0) {
wpa_printf(MSG_ERROR, "%s Parse failed: %s",
supplicant_event_map[event_data->event], strerror(errno));
}
return ret;
}
int supplicant_send_wifi_mgmt_event(const char *ifname, enum net_event_wifi_cmd event,
void *supplicant_status, size_t len)
{
struct net_if *iface = net_if_get_by_index(net_if_get_by_name(ifname));
union supplicant_event_data data;
struct supplicant_int_event_data event_data;
if (!iface) {
wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname);
return -ENODEV;
}
switch (event) {
case NET_EVENT_WIFI_CMD_CONNECT_RESULT:
wifi_mgmt_raise_connect_result_event(iface, *(int *)supplicant_status);
break;
case NET_EVENT_WIFI_CMD_DISCONNECT_RESULT:
wifi_mgmt_raise_disconnect_result_event(iface, *(int *)supplicant_status);
break;
case NET_EVENT_SUPPLICANT_CMD_INT_EVENT:
event_data.data = &data;
if (supplicant_process_status(&event_data, (char *)supplicant_status) > 0) {
net_mgmt_event_notify_with_info(NET_EVENT_SUPPLICANT_INT_EVENT,
iface, &event_data, sizeof(event_data));
}
break;
default:
wpa_printf(MSG_ERROR, "Unsupported event %d", event);
return -EINVAL;
}
return 0;
}
int supplicant_generate_state_event(const char *ifname,
enum net_event_supplicant_cmd event,
int status)
{
struct net_if *iface;
iface = net_if_get_by_index(net_if_get_by_name(ifname));
if (!iface) {
wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname);
return -ENODEV;
}
switch (event) {
case NET_EVENT_SUPPLICANT_CMD_READY:
net_mgmt_event_notify(NET_EVENT_SUPPLICANT_READY, iface);
break;
case NET_EVENT_SUPPLICANT_CMD_NOT_READY:
net_mgmt_event_notify(NET_EVENT_SUPPLICANT_NOT_READY, iface);
break;
case NET_EVENT_SUPPLICANT_CMD_IFACE_ADDED:
net_mgmt_event_notify(NET_EVENT_SUPPLICANT_IFACE_ADDED, iface);
break;
case NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVING:
net_mgmt_event_notify(NET_EVENT_SUPPLICANT_IFACE_REMOVING, iface);
break;
case NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED:
net_mgmt_event_notify_with_info(NET_EVENT_SUPPLICANT_IFACE_REMOVED,
iface, &status, sizeof(status));
break;
default:
wpa_printf(MSG_ERROR, "Unsupported event %d", event);
return -EINVAL;
}
return 0;
}