diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 36c000b86..64c9c2001 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -601,6 +601,16 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, } +int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, + const u8 *peer, u8 *buf, u16 *buf_len) +{ + if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL) + return 0; + return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf, + buf_len); +} + + int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, unsigned int wait, const u8 *dst, const u8 *data, size_t len) diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 169c91b79..9c53b99d8 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -101,6 +101,10 @@ int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, #include "drivers/driver.h" +int hostapd_drv_wnm_oper(struct hostapd_data *hapd, + enum wnm_oper oper, const u8 *peer, + u8 *buf, u16 *buf_len); + static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd, int enabled) { diff --git a/src/drivers/driver.h b/src/drivers/driver.h index d51088239..82b72cdfb 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -999,6 +999,23 @@ enum tdls_oper { TDLS_DISABLE }; +enum wnm_oper { + WNM_SLEEP_ENTER_CONFIRM, + WNM_SLEEP_ENTER_FAIL, + WNM_SLEEP_EXIT_CONFIRM, + WNM_SLEEP_EXIT_FAIL, + WNM_SLEEP_TFS_REQ_IE_ADD, /* STA requests driver to add TFS req IE */ + WNM_SLEEP_TFS_REQ_IE_NONE, /* STA requests empty TFS req IE */ + WNM_SLEEP_TFS_REQ_IE_SET, /* AP requests driver to set TFS req IE for + * a STA */ + WNM_SLEEP_TFS_RESP_IE_ADD, /* AP requests driver to add TFS resp IE + * for a STA */ + WNM_SLEEP_TFS_RESP_IE_NONE, /* AP requests empty TFS resp IE */ + WNM_SLEEP_TFS_RESP_IE_SET, /* AP requests driver to set TFS resp IE + * for a STA */ + WNM_SLEEP_TFS_IE_DEL /* AP delete the TFS IE */ +}; + /** * struct wpa_signal_info - Information about channel signal quality */ @@ -2414,6 +2431,18 @@ struct wpa_driver_ops { */ int (*tdls_oper)(void *priv, enum tdls_oper oper, const u8 *peer); + /** + * wnm_oper - Notify driver of the WNM frame reception + * @priv: Private driver interface data + * @oper: WNM operation. See %enum wnm_oper + * @peer: Destination (peer) MAC address + * @buf: Buffer for the driver to fill in (for getting IE) + * @buf_len: Return the len of buf + * Returns: 0 on success, negative (<0) on failure + */ + int (*wnm_oper)(void *priv, enum wnm_oper oper, const u8 *peer, + u8 *buf, u16 *buf_len); + /** * signal_poll - Get current connection information * @priv: Private driver interface data @@ -3011,7 +3040,14 @@ enum wpa_event_type { * * Described in wpa_event_data.ch_switch * */ - EVENT_CH_SWITCH + EVENT_CH_SWITCH, + + /** + * EVENT_WNM - Request WNM operation + * + * This event can be used to request a WNM operation to be performed. + */ + EVENT_WNM }; @@ -3213,6 +3249,24 @@ union wpa_event_data { u16 reason_code; /* for teardown */ } tdls; + /** + * struct wnm - Data for EVENT_WNM + */ + struct wnm { + u8 addr[ETH_ALEN]; + enum { + WNM_OPER_SLEEP, + } oper; + enum { + WNM_SLEEP_ENTER, + WNM_SLEEP_EXIT + } sleep_action; + int sleep_intval; + u16 reason_code; + u8 *buf; + u16 buf_len; + } wnm; + /** * struct ft_ies - FT information elements (EVENT_FT_RESPONSE) * diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 81856aa94..418cf1a06 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -78,6 +78,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(DRIVER_CLIENT_POLL_OK); E2S(EAPOL_TX_STATUS); E2S(CH_SWITCH); + E2S(WNM); } return "UNKNOWN"; diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 2ab455beb..ac0936a70 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -680,4 +680,14 @@ static inline int wpa_drv_switch_channel(struct wpa_supplicant *wpa_s, return wpa_s->driver->switch_channel(wpa_s->drv_priv, freq); } +static inline int wpa_drv_wnm_oper(struct wpa_supplicant *wpa_s, + enum wnm_oper oper, const u8 *peer, + u8 *buf, u16 *buf_len) +{ + if (!wpa_s->driver->wnm_oper) + return -1; + return wpa_s->driver->wnm_oper(wpa_s->drv_priv, oper, peer, buf, + buf_len); +} + #endif /* DRIVER_I_H */