|
5 | 5 | * SPDX-License-Identifier: Apache-2.0 |
6 | 6 | */ |
7 | 7 |
|
| 8 | +#undef _POSIX_C_SOURCE |
| 9 | +#define _POSIX_C_SOURCE 200809L /* For strnlen() */ |
| 10 | + |
8 | 11 | #include <zephyr/logging/log.h> |
9 | 12 | LOG_MODULE_REGISTER(net_wifi_mgmt, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL); |
10 | 13 |
|
11 | 14 | #include <errno.h> |
12 | 15 | #include <string.h> |
13 | | - |
| 16 | +#include <stdio.h> |
14 | 17 | #include <zephyr/net/net_core.h> |
15 | 18 | #include <zephyr/net/net_if.h> |
16 | 19 | #include <zephyr/net/wifi_mgmt.h> |
@@ -1009,3 +1012,238 @@ void wifi_mgmt_raise_ap_sta_disconnected_event(struct net_if *iface, |
1009 | 1012 | iface, sta_info, |
1010 | 1013 | sizeof(struct wifi_ap_sta_info)); |
1011 | 1014 | } |
| 1015 | + |
| 1016 | +#ifdef CONFIG_WIFI_CREDENTIALS_CONNECT_STORED |
| 1017 | + |
| 1018 | +#include <zephyr/net/wifi_credentials.h> |
| 1019 | + |
| 1020 | +#if defined(CONFIG_WIFI_CREDENTIALS_STATIC) |
| 1021 | +BUILD_ASSERT(sizeof(CONFIG_WIFI_CREDENTIALS_STATIC_SSID) != 1, |
| 1022 | + "CONFIG_WIFI_CREDENTIALS_STATIC_SSID required"); |
| 1023 | +#endif /* defined(CONFIG_WIFI_CREDENTIALS_STATIC) */ |
| 1024 | + |
| 1025 | +static int __stored_creds_to_params(struct wifi_credentials_personal *creds, |
| 1026 | + struct wifi_connect_req_params *params) |
| 1027 | +{ |
| 1028 | + char *ssid = NULL; |
| 1029 | + char *psk = NULL; |
| 1030 | + int ret; |
| 1031 | + |
| 1032 | + /* SSID */ |
| 1033 | + ssid = (char *)k_malloc(creds->header.ssid_len + 1); |
| 1034 | + if (!ssid) { |
| 1035 | + LOG_ERR("Failed to allocate memory for SSID\n"); |
| 1036 | + ret = -ENOMEM; |
| 1037 | + goto err_out; |
| 1038 | + } |
| 1039 | + |
| 1040 | + memset(ssid, 0, creds->header.ssid_len + 1); |
| 1041 | + ret = snprintf(ssid, creds->header.ssid_len + 1, "%s", creds->header.ssid); |
| 1042 | + if (ret > creds->header.ssid_len) { |
| 1043 | + LOG_ERR("SSID string truncated\n"); |
| 1044 | + ret = -EINVAL; |
| 1045 | + goto err_out; |
| 1046 | + } |
| 1047 | + |
| 1048 | + params->ssid = ssid; |
| 1049 | + params->ssid_length = creds->header.ssid_len; |
| 1050 | + |
| 1051 | + /* PSK (optional) */ |
| 1052 | + if (creds->password_len > 0) { |
| 1053 | + psk = (char *)k_malloc(creds->password_len + 1); |
| 1054 | + if (!psk) { |
| 1055 | + LOG_ERR("Failed to allocate memory for PSK\n"); |
| 1056 | + ret = -ENOMEM; |
| 1057 | + goto err_out; |
| 1058 | + } |
| 1059 | + |
| 1060 | + memset(psk, 0, creds->password_len + 1); |
| 1061 | + ret = snprintf(psk, creds->password_len + 1, "%s", creds->password); |
| 1062 | + if (ret > creds->password_len) { |
| 1063 | + LOG_ERR("PSK string truncated\n"); |
| 1064 | + ret = -EINVAL; |
| 1065 | + goto err_out; |
| 1066 | + } |
| 1067 | + |
| 1068 | + params->psk = psk; |
| 1069 | + params->psk_length = creds->password_len; |
| 1070 | + } |
| 1071 | + |
| 1072 | + /* Defaults */ |
| 1073 | + params->security = creds->header.type; |
| 1074 | + |
| 1075 | + /* If channel is set to 0 we default to ANY. 0 is not a valid Wi-Fi channel. */ |
| 1076 | + params->channel = (creds->header.channel != 0) ? creds->header.channel : WIFI_CHANNEL_ANY; |
| 1077 | + params->timeout = (creds->header.timeout != 0) |
| 1078 | + ? creds->header.timeout |
| 1079 | + : CONFIG_WIFI_CREDENTIALS_CONNECT_STORED_CONNECTION_TIMEOUT; |
| 1080 | + |
| 1081 | + /* Security type (optional) */ |
| 1082 | + if (creds->header.type > WIFI_SECURITY_TYPE_MAX) { |
| 1083 | + params->security = WIFI_SECURITY_TYPE_NONE; |
| 1084 | + } |
| 1085 | + |
| 1086 | + if (creds->header.flags & WIFI_CREDENTIALS_FLAG_2_4GHz) { |
| 1087 | + params->band = WIFI_FREQ_BAND_2_4_GHZ; |
| 1088 | + } else if (creds->header.flags & WIFI_CREDENTIALS_FLAG_5GHz) { |
| 1089 | + params->band = WIFI_FREQ_BAND_5_GHZ; |
| 1090 | + } else { |
| 1091 | + params->band = WIFI_FREQ_BAND_UNKNOWN; |
| 1092 | + } |
| 1093 | + |
| 1094 | + /* MFP setting (default: optional) */ |
| 1095 | + if (creds->header.flags & WIFI_CREDENTIALS_FLAG_MFP_DISABLED) { |
| 1096 | + params->mfp = WIFI_MFP_DISABLE; |
| 1097 | + } else if (creds->header.flags & WIFI_CREDENTIALS_FLAG_MFP_REQUIRED) { |
| 1098 | + params->mfp = WIFI_MFP_REQUIRED; |
| 1099 | + } else { |
| 1100 | + params->mfp = WIFI_MFP_OPTIONAL; |
| 1101 | + } |
| 1102 | + |
| 1103 | + return 0; |
| 1104 | +err_out: |
| 1105 | + if (ssid) { |
| 1106 | + k_free(ssid); |
| 1107 | + ssid = NULL; |
| 1108 | + } |
| 1109 | + |
| 1110 | + if (psk) { |
| 1111 | + k_free(psk); |
| 1112 | + psk = NULL; |
| 1113 | + } |
| 1114 | + |
| 1115 | + return ret; |
| 1116 | +} |
| 1117 | + |
| 1118 | +static inline const char *wpa_supp_security_txt(enum wifi_security_type security) |
| 1119 | +{ |
| 1120 | + switch (security) { |
| 1121 | + case WIFI_SECURITY_TYPE_NONE: |
| 1122 | + return "NONE"; |
| 1123 | + case WIFI_SECURITY_TYPE_PSK: |
| 1124 | + return "WPA-PSK"; |
| 1125 | + case WIFI_SECURITY_TYPE_PSK_SHA256: |
| 1126 | + return "WPA-PSK-SHA256"; |
| 1127 | + case WIFI_SECURITY_TYPE_SAE: |
| 1128 | + return "SAE"; |
| 1129 | + case WIFI_SECURITY_TYPE_UNKNOWN: |
| 1130 | + default: |
| 1131 | + return "UNKNOWN"; |
| 1132 | + } |
| 1133 | +} |
| 1134 | + |
| 1135 | +static int add_network_from_credentials_struct_personal(struct wifi_credentials_personal *creds, |
| 1136 | + struct net_if *iface) |
| 1137 | +{ |
| 1138 | + int ret = 0; |
| 1139 | + struct wifi_connect_req_params cnx_params = {0}; |
| 1140 | + |
| 1141 | + if (__stored_creds_to_params(creds, &cnx_params)) { |
| 1142 | + ret = -ENOEXEC; |
| 1143 | + goto out; |
| 1144 | + } |
| 1145 | + |
| 1146 | + if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, &cnx_params, |
| 1147 | + sizeof(struct wifi_connect_req_params))) { |
| 1148 | + LOG_ERR("Connection request failed\n"); |
| 1149 | + |
| 1150 | + return -ENOEXEC; |
| 1151 | + } |
| 1152 | + |
| 1153 | + LOG_INF("Connection requested"); |
| 1154 | + |
| 1155 | +out: |
| 1156 | + if (cnx_params.psk) { |
| 1157 | + k_free((void *)cnx_params.psk); |
| 1158 | + } |
| 1159 | + |
| 1160 | + if (cnx_params.ssid) { |
| 1161 | + k_free((void *)cnx_params.ssid); |
| 1162 | + } |
| 1163 | + |
| 1164 | + return ret; |
| 1165 | +} |
| 1166 | + |
| 1167 | +static void add_stored_network(void *cb_arg, const char *ssid, size_t ssid_len) |
| 1168 | +{ |
| 1169 | + int ret = 0; |
| 1170 | + struct wifi_credentials_personal creds; |
| 1171 | + |
| 1172 | + /* load stored data */ |
| 1173 | + ret = wifi_credentials_get_by_ssid_personal_struct(ssid, ssid_len, &creds); |
| 1174 | + |
| 1175 | + if (ret) { |
| 1176 | + LOG_ERR("Loading WiFi credentials failed for SSID [%.*s], len: %d, err: %d", |
| 1177 | + ssid_len, ssid, ssid_len, ret); |
| 1178 | + return; |
| 1179 | + } |
| 1180 | + |
| 1181 | + add_network_from_credentials_struct_personal(&creds, (struct net_if *)cb_arg); |
| 1182 | +} |
| 1183 | + |
| 1184 | +static int add_static_network_config(struct net_if *iface) |
| 1185 | +{ |
| 1186 | +#if defined(CONFIG_WIFI_CREDENTIALS_STATIC) |
| 1187 | + |
| 1188 | + struct wifi_credentials_personal creds = { |
| 1189 | + .header = { |
| 1190 | + .ssid_len = strlen(CONFIG_WIFI_CREDENTIALS_STATIC_SSID), |
| 1191 | + }, |
| 1192 | + .password_len = strlen(CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD), |
| 1193 | + }; |
| 1194 | + |
| 1195 | + int ret = wifi_credentials_get_by_ssid_personal_struct( |
| 1196 | + CONFIG_WIFI_CREDENTIALS_STATIC_SSID, strlen(CONFIG_WIFI_CREDENTIALS_STATIC_SSID), |
| 1197 | + &creds); |
| 1198 | + |
| 1199 | + if (!ret) { |
| 1200 | + LOG_WRN("Statically configured WiFi network was overridden by storage."); |
| 1201 | + return 0; |
| 1202 | + } |
| 1203 | + |
| 1204 | +#if defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_OPEN) |
| 1205 | + creds.header.type = WIFI_SECURITY_TYPE_NONE; |
| 1206 | +#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_PSK) |
| 1207 | + creds.header.type = WIFI_SECURITY_TYPE_PSK; |
| 1208 | +#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_PSK_SHA256) |
| 1209 | + creds.header.type = WIFI_SECURITY_TYPE_PSK_SHA256; |
| 1210 | +#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_SAE) |
| 1211 | + creds.header.type = WIFI_SECURITY_TYPE_SAE; |
| 1212 | +#elif defined(CONFIG_WIFI_CREDENTIALS_STATIC_TYPE_WPA_PSK) |
| 1213 | + creds.header.type = WIFI_SECURITY_TYPE_WPA_PSK; |
| 1214 | +#else |
| 1215 | +#error "invalid CONFIG_WIFI_CREDENTIALS_STATIC_TYPE" |
| 1216 | +#endif |
| 1217 | + |
| 1218 | + memcpy(creds.header.ssid, CONFIG_WIFI_CREDENTIALS_STATIC_SSID, |
| 1219 | + strlen(CONFIG_WIFI_CREDENTIALS_STATIC_SSID)); |
| 1220 | + memcpy(creds.password, CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD, |
| 1221 | + strlen(CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD)); |
| 1222 | + |
| 1223 | + LOG_DBG("Adding statically configured WiFi network [%s] to internal list.", |
| 1224 | + creds.header.ssid); |
| 1225 | + |
| 1226 | + return add_network_from_credentials_struct_personal(&creds, iface); |
| 1227 | +#else |
| 1228 | + return 0; |
| 1229 | +#endif /* defined(CONFIG_WIFI_CREDENTIALS_STATIC) */ |
| 1230 | +} |
| 1231 | + |
| 1232 | +static int connect_stored_command(uint32_t mgmt_request, struct net_if *iface, void *data, |
| 1233 | + size_t len) |
| 1234 | +{ |
| 1235 | + int ret = 0; |
| 1236 | + |
| 1237 | + ret = add_static_network_config(iface); |
| 1238 | + if (ret) { |
| 1239 | + return ret; |
| 1240 | + } |
| 1241 | + |
| 1242 | + wifi_credentials_for_each_ssid(add_stored_network, iface); |
| 1243 | + |
| 1244 | + return ret; |
| 1245 | +}; |
| 1246 | + |
| 1247 | +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT_STORED, connect_stored_command); |
| 1248 | + |
| 1249 | +#endif /* CONFIG_WIFI_CREDENTIALS_CONNECT_STORED */ |
0 commit comments