@@ -1488,6 +1488,64 @@ static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
}
+static int hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ void *ctx)
+{
+ struct hostapd_wpa_psk *psk;
+ const u8 *pmk;
+ int pmk_len;
+ int pmk_match;
+ int sta_match;
+ int bss_match;
+ int reason;
+
+ pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len);
+
+ for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) {
+ pmk_match = PMK_LEN == pmk_len && !os_memcmp(psk->psk, pmk, pmk_len);
+ sta_match = psk->group == 0 && !os_memcmp(sta->addr, psk->addr, ETH_ALEN);
+ bss_match = psk->group == 1;
+
+ if (pmk_match && (sta_match || bss_match))
+ return 0;
+ }
+
+ wpa_printf(MSG_INFO, "STA " MACSTR " password no longer valid, kicking", MAC2STR(sta->addr));
+ reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
+ hostapd_drv_sta_deauth(hapd, sta->addr, reason);
+ ap_sta_deauthenticate(hapd, sta, reason);
+
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd)
+{
+ struct hostapd_bss_config *conf = hapd->conf;
+ struct hostapd_wpa_psk *psk, *next;
+ int err;
+
+ for (psk = conf->ssid.wpa_psk; psk; psk = next) {
+ next = psk->next;
+ os_free(psk);
+ }
+ conf->ssid.wpa_psk = NULL;
+
+ err = hostapd_setup_wpa_psk(conf);
+ if (err < 0) {
+ wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d", err);
+ return -1;
+ }
+
+ ap_for_each_sta(hapd,
+ hostapd_ctrl_iface_kick_mismatch_psk_sta_iter,
+ NULL);
+
+ return 0;
+}
+
+
#ifdef CONFIG_TESTING_OPTIONS
static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
@@ -3013,6 +3071,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
if (hostapd_ctrl_iface_enable(hapd->iface))
reply_len = -1;
+ } else if (os_strncmp(buf, "RELOAD_WPA_PSK", 14) == 0) {
+ if (hostapd_ctrl_iface_reload_wpa_psk(hapd))
+ reply_len = -1;
} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
if (hostapd_ctrl_iface_reload(hapd->iface))
reply_len = -1;
@@ -903,6 +903,13 @@ static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
}
+static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "RELOAD_WPA_PSK");
+}
+
+
static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
hostapd_cli_quit = 1;
@@ -1651,6 +1658,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"=Add/Delete/Show/Clear deny MAC ACL" },
{ "poll_sta", hostapd_cli_cmd_poll_sta, hostapd_complete_stations,
"<addr> = poll a STA to check connectivity with a QoS null frame" },
+ { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
+ "=reload wpa_psk_file only" },
{ NULL, NULL, NULL, NULL }
};