return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id);
}
+
+
+static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ u8 bssid[ETH_ALEN];
+
+ if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: PASN_DEAUTH without valid BSSID");
+ return -1;
+ }
+
+ return wpas_pasn_deauthenticate(wpa_s, bssid);
+}
+
#endif /* CONFIG_PASN */
wpas_pasn_auth_stop(wpa_s);
} else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
+ } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) {
+ if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0)
+ reply_len = -1;
#endif /* CONFIG_PASN */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
return 0;
}
+
+
+int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+ struct wpa_bss *bss;
+ struct wpabuf *buf;
+ struct ieee80211_mgmt *deauth;
+ int ret;
+
+ if (os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Cannot deauthenticate from current BSS");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "PASN: deauth: Flushing all PTKSA entries for "
+ MACSTR, MAC2STR(bssid));
+ ptksa_cache_flush(wpa_s->ptksa, bssid, WPA_CIPHER_NONE);
+
+ bss = wpa_bss_get_bssid(wpa_s, bssid);
+ if (!bss) {
+ wpa_printf(MSG_DEBUG, "PASN: deauth: BSS not found");
+ return -1;
+ }
+
+ buf = wpabuf_alloc(64);
+ if (!buf) {
+ wpa_printf(MSG_DEBUG, "PASN: deauth: Failed wpabuf allocate");
+ return -1;
+ }
+
+ deauth = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
+ u.deauth.variable));
+
+ deauth->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+ (WLAN_FC_STYPE_DEAUTH << 4));
+
+ os_memcpy(deauth->da, bssid, ETH_ALEN);
+ os_memcpy(deauth->sa, wpa_s->own_addr, ETH_ALEN);
+ os_memcpy(deauth->bssid, bssid, ETH_ALEN);
+ deauth->u.deauth.reason_code =
+ host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+ /*
+ * Since we do not expect any response from the AP, implement the
+ * Deauthentication frame transmission using direct call to the driver
+ * without a radio work.
+ */
+ ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
+ bss->freq, 0);
+
+ wpabuf_free(buf);
+ wpa_printf(MSG_DEBUG, "PASN: deauth: send_mlme ret=%d", ret);
+
+ return ret;
+}
return wpa_cli_cmd(ctrl, "PTKSA_CACHE_LIST", 0, argc, argv);
}
+
+static int wpa_cli_cmd_pasn_deauth(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "PASN_DEAUTH", 1, argc, argv);
+}
+
#endif /* CONFIG_PASN */
{ "ptksa_cache_list", wpa_cli_cmd_ptksa_cache_list, NULL,
cli_cmd_flag_none,
"= Get the PTKSA Cache" },
+ { "pasn_deauth", wpa_cli_cmd_pasn_deauth, NULL,
+ cli_cmd_flag_none,
+ "bssid=<BSSID> = Remove PASN PTKSA state" },
#endif /* CONFIG_PASN */
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len);
+int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *bssid);
+
#endif /* WPA_SUPPLICANT_I_H */