1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "supp_events.h"
8 
9 #include "includes.h"
10 #include "common.h"
11 
12 #define MAC_STR_FORMAT "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
13 
14 static const char * const supplicant_event_map[] = {
15 	"CTRL-EVENT-CONNECTED",
16 	"CTRL-EVENT-DISCONNECTED",
17 	"CTRL-EVENT-ASSOC-REJECT",
18 	"CTRL-EVENT-AUTH-REJECT",
19 	"CTRL-EVENT-TERMINATING",
20 	"CTRL-EVENT-SSID-TEMP-DISABLED",
21 	"CTRL-EVENT-SSID-REENABLED",
22 	"CTRL-EVENT-SCAN-STARTED",
23 	"CTRL-EVENT-SCAN-RESULTS",
24 	"CTRL-EVENT-SCAN-FAILED",
25 	"CTRL-EVENT-BSS-ADDED",
26 	"CTRL-EVENT-BSS-REMOVED",
27 	"CTRL-EVENT-NETWORK-NOT-FOUND",
28 	"CTRL-EVENT-NETWORK-ADDED",
29 	"CTRL-EVENT-NETWORK-REMOVED",
30 	"CTRL-EVENT-DSCP-POLICY",
31 };
32 
supplicant_process_status(struct supplicant_int_event_data * event_data,char * supplicant_status)33 static int supplicant_process_status(struct supplicant_int_event_data *event_data,
34 				     char *supplicant_status)
35 {
36 	int ret = 1; /* For cases where parsing is not being done*/
37 	int event = -1;
38 	int i;
39 	unsigned char *mac;
40 	union supplicant_event_data *data;
41 
42 	data = (union supplicant_event_data *)event_data->data;
43 
44 	for (i = 0; i < ARRAY_SIZE(supplicant_event_map); i++) {
45 		if (strncmp(supplicant_status, supplicant_event_map[i],
46 		    strlen(supplicant_event_map[i])) == 0) {
47 			event = i;
48 			break;
49 		}
50 	}
51 
52 	if (i >= ARRAY_SIZE(supplicant_event_map)) {
53 		wpa_printf(MSG_ERROR, "Event not supported: %s\n", supplicant_status);
54 		return -ENOTSUP;
55 	}
56 
57 	event_data->event = event;
58 
59 	switch (event_data->event) {
60 	case SUPPLICANT_EVENT_CONNECTED:
61 		mac = data->connected.bssid;
62 		ret = sscanf(supplicant_status +
63 			     sizeof("CTRL-EVENT-CONNECTED - Connection to") - 1,
64 			     MAC_STR_FORMAT,
65 			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
66 		event_data->data_len = sizeof(data->connected);
67 		break;
68 	case SUPPLICANT_EVENT_DISCONNECTED:
69 		mac = data->disconnected.bssid;
70 		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-DISCONNECTED bssid=") - 1,
71 			     MAC_STR_FORMAT" reason=%d", &mac[0], &mac[1], &mac[2],
72 			     &mac[3], &mac[4], &mac[5], &data->disconnected.reason_code);
73 		event_data->data_len = sizeof(data->disconnected);
74 		break;
75 	case SUPPLICANT_EVENT_ASSOC_REJECT:
76 		/* TODO */
77 		break;
78 	case SUPPLICANT_EVENT_AUTH_REJECT:
79 		mac = data->auth_reject.bssid;
80 		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-AUTH-REJECT ") - 1,
81 			     MAC_STR_FORMAT
82 			     " auth_type=%u auth_transaction=%u status_code=%u",
83 			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5],
84 			     &data->auth_reject.auth_type,
85 			     &data->auth_reject.auth_transaction,
86 			     &data->auth_reject.status_code);
87 		event_data->data_len = sizeof(data->auth_reject);
88 		break;
89 	case SUPPLICANT_EVENT_SSID_TEMP_DISABLED:
90 		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-SSID-TEMP-DISABLED ") - 1,
91 			     "id=%d ssid=%s auth_failures=%u duration=%d reason=%s",
92 			     &data->temp_disabled.id, data->temp_disabled.ssid,
93 			     &data->temp_disabled.auth_failures,
94 			     &data->temp_disabled.duration,
95 			     data->temp_disabled.reason_code);
96 		event_data->data_len = sizeof(data->temp_disabled);
97 		break;
98 	case SUPPLICANT_EVENT_SSID_REENABLED:
99 		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-SSID-REENABLED ") - 1,
100 			     "id=%d ssid=%s", &data->reenabled.id,
101 			     data->reenabled.ssid);
102 		event_data->data_len = sizeof(data->reenabled);
103 		break;
104 	case SUPPLICANT_EVENT_BSS_ADDED:
105 		mac = data->bss_added.bssid;
106 		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-BSS-ADDED ") - 1,
107 			     "%u "MAC_STR_FORMAT,
108 			     &data->bss_added.id,
109 			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
110 		event_data->data_len = sizeof(data->bss_added);
111 		break;
112 	case SUPPLICANT_EVENT_BSS_REMOVED:
113 		mac = data->bss_removed.bssid;
114 		ret = sscanf(supplicant_status + sizeof("CTRL-EVENT-BSS-REMOVED ") - 1,
115 			     "%u "MAC_STR_FORMAT,
116 			     &data->bss_removed.id,
117 			     &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
118 		event_data->data_len = sizeof(data->bss_removed);
119 		break;
120 	case SUPPLICANT_EVENT_TERMINATING:
121 	case SUPPLICANT_EVENT_SCAN_STARTED:
122 	case SUPPLICANT_EVENT_SCAN_FAILED:
123 	case SUPPLICANT_EVENT_NETWORK_NOT_FOUND:
124 	case SUPPLICANT_EVENT_NETWORK_ADDED:
125 	case SUPPLICANT_EVENT_NETWORK_REMOVED:
126 		strncpy(data->supplicant_event_str, supplicant_event_map[event],
127 			sizeof(data->supplicant_event_str));
128 		event_data->data_len = strlen(data->supplicant_event_str) + 1;
129 	case SUPPLICANT_EVENT_DSCP_POLICY:
130 		/* TODO */
131 		break;
132 	default:
133 		break;
134 	}
135 
136 	if (ret <= 0) {
137 		wpa_printf(MSG_ERROR, "%s Parse failed: %s",
138 			   supplicant_event_map[event_data->event], strerror(errno));
139 	}
140 
141 	return ret;
142 }
143 
supplicant_send_wifi_mgmt_event(const char * ifname,enum net_event_wifi_cmd event,void * supplicant_status,size_t len)144 int supplicant_send_wifi_mgmt_event(const char *ifname, enum net_event_wifi_cmd event,
145 				    void *supplicant_status, size_t len)
146 {
147 	struct net_if *iface = net_if_get_by_index(net_if_get_by_name(ifname));
148 	union supplicant_event_data data;
149 	struct supplicant_int_event_data event_data;
150 
151 	if (!iface) {
152 		wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname);
153 		return -ENODEV;
154 	}
155 
156 	switch (event) {
157 	case NET_EVENT_WIFI_CMD_CONNECT_RESULT:
158 		wifi_mgmt_raise_connect_result_event(iface, *(int *)supplicant_status);
159 		break;
160 	case NET_EVENT_WIFI_CMD_DISCONNECT_RESULT:
161 		wifi_mgmt_raise_disconnect_result_event(iface, *(int *)supplicant_status);
162 		break;
163 	case NET_EVENT_SUPPLICANT_CMD_INT_EVENT:
164 		event_data.data = &data;
165 		if (supplicant_process_status(&event_data, (char *)supplicant_status) > 0) {
166 			net_mgmt_event_notify_with_info(NET_EVENT_SUPPLICANT_INT_EVENT,
167 						iface, &event_data, sizeof(event_data));
168 		}
169 		break;
170 	default:
171 		wpa_printf(MSG_ERROR, "Unsupported event %d", event);
172 		return -EINVAL;
173 	}
174 
175 	return 0;
176 }
177 
supplicant_generate_state_event(const char * ifname,enum net_event_supplicant_cmd event,int status)178 int supplicant_generate_state_event(const char *ifname,
179 				    enum net_event_supplicant_cmd event,
180 				    int status)
181 {
182 	struct net_if *iface;
183 
184 	iface = net_if_get_by_index(net_if_get_by_name(ifname));
185 	if (!iface) {
186 		wpa_printf(MSG_ERROR, "Could not find iface for %s", ifname);
187 		return -ENODEV;
188 	}
189 
190 	switch (event) {
191 	case NET_EVENT_SUPPLICANT_CMD_READY:
192 		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_READY, iface);
193 		break;
194 	case NET_EVENT_SUPPLICANT_CMD_NOT_READY:
195 		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_NOT_READY, iface);
196 		break;
197 	case NET_EVENT_SUPPLICANT_CMD_IFACE_ADDED:
198 		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_IFACE_ADDED, iface);
199 		break;
200 	case NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVING:
201 		net_mgmt_event_notify(NET_EVENT_SUPPLICANT_IFACE_REMOVING, iface);
202 		break;
203 	case NET_EVENT_SUPPLICANT_CMD_IFACE_REMOVED:
204 		net_mgmt_event_notify_with_info(NET_EVENT_SUPPLICANT_IFACE_REMOVED,
205 						iface, &status, sizeof(status));
206 		break;
207 	default:
208 		wpa_printf(MSG_ERROR, "Unsupported event %d", event);
209 		return -EINVAL;
210 	}
211 
212 	return 0;
213 }
214