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