diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 699a56f18..016b697d2 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -3100,7 +3100,38 @@ enum wpa_event_type { * with the specified client (for example, max client reached, etc.) in * AP mode. */ - EVENT_CONNECT_FAILED_REASON + EVENT_CONNECT_FAILED_REASON, + + /** + * EVENT_RADAR_DETECTED - Notify of radar detection + * + * A radar has been detected on the supplied frequency, hostapd should + * react accordingly (e.g., change channel). + */ + EVENT_DFS_RADAR_DETECTED, + + /** + * EVENT_CAC_FINISHED - Notify that channel availability check has been completed + * + * After a successful CAC, the channel can be marked clear and used. + */ + EVENT_DFS_CAC_FINISHED, + + /** + * EVENT_CAC_ABORTED - Notify that channel availability check has been aborted + * + * The CAC was not successful, and the channel remains in the previous + * state. This may happen due to a radar beeing detected or other + * external influences. + */ + EVENT_DFS_CAC_ABORTED, + + /** + * EVENT_DFS_CAC_NOP_FINISHED - Notify that non-occupancy period is over + * + * The channel which was previously unavailable is now available again. + */ + EVENT_DFS_NOP_FINISHED }; @@ -3738,6 +3769,14 @@ union wpa_event_data { BLOCKED_CLIENT } code; } connect_failed_reason; + + /** + * struct dfs_event - Data for radar detected events + * @freq: Frequency of the channel in MHz + */ + struct dfs_event { + int freq; + } dfs_event; }; /** diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 565a01bdb..12ccc142b 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -80,6 +80,10 @@ const char * event_to_string(enum wpa_event_type event) E2S(CH_SWITCH); E2S(WNM); E2S(CONNECT_FAILED_REASON); + E2S(DFS_RADAR_DETECTED); + E2S(DFS_CAC_FINISHED); + E2S(DFS_CAC_ABORTED); + E2S(DFS_NOP_FINISHED); } return "UNKNOWN"; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 48b0c2efb..0a1cac6e7 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2234,6 +2234,43 @@ static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv, } +static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv, + struct nlattr **tb) +{ + union wpa_event_data data; + enum nl80211_radar_event event_type; + + if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT]) + return; + + os_memset(&data, 0, sizeof(data)); + data.dfs_event.freq = nla_get_u16(tb[NL80211_ATTR_WIPHY_FREQ]); + event_type = nla_get_u8(tb[NL80211_ATTR_RADAR_EVENT]); + + wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz", + data.dfs_event.freq); + + switch (event_type) { + case NL80211_RADAR_DETECTED: + wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data); + break; + case NL80211_RADAR_CAC_FINISHED: + wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data); + break; + case NL80211_RADAR_CAC_ABORTED: + wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data); + break; + case NL80211_RADAR_NOP_FINISHED: + wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data); + break; + default: + wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d " + "received", event_type); + break; + } +} + + static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb, int wds) { @@ -2378,6 +2415,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, case NL80211_CMD_FT_EVENT: mlme_event_ft_event(drv, tb); break; + case NL80211_CMD_RADAR_DETECT: + nl80211_radar_event(drv, tb); + break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd);