#ifdef CONFIG_WNM_AP
-static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
- const char *cmd)
-{
- u8 addr[ETH_ALEN];
- int disassoc_timer;
- struct sta_info *sta;
-
- if (hwaddr_aton(cmd, addr))
- return -1;
- if (cmd[17] != ' ')
- return -1;
- disassoc_timer = atoi(cmd + 17);
-
- sta = ap_get_sta(hapd, addr);
- if (sta == NULL) {
- wpa_printf(MSG_DEBUG, "Station " MACSTR
- " not found for disassociation imminent message",
- MAC2STR(addr));
- return -1;
- }
-
- return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
-}
-
-
-static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
- const char *cmd)
-{
- u8 addr[ETH_ALEN];
- const char *url, *timerstr;
- int disassoc_timer;
- struct sta_info *sta;
-
- if (hwaddr_aton(cmd, addr))
- return -1;
-
- sta = ap_get_sta(hapd, addr);
- if (sta == NULL) {
- wpa_printf(MSG_DEBUG, "Station " MACSTR
- " not found for ESS disassociation imminent message",
- MAC2STR(addr));
- return -1;
- }
-
- timerstr = cmd + 17;
- if (*timerstr != ' ')
- return -1;
- timerstr++;
- disassoc_timer = atoi(timerstr);
- if (disassoc_timer < 0 || disassoc_timer > 65535)
- return -1;
-
- url = os_strchr(timerstr, ' ');
- if (url == NULL)
- return -1;
- url++;
-
- return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
-}
-
-
-static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
- const char *cmd)
-{
- u8 addr[ETH_ALEN];
- const char *pos, *end;
- int disassoc_timer = 0;
- struct sta_info *sta;
- u8 req_mode = 0, valid_int = 0x01, dialog_token = 0x01;
- u8 bss_term_dur[12];
- char *url = NULL;
- int ret;
- u8 nei_rep[1000];
- int nei_len;
- u8 mbo[10];
- size_t mbo_len = 0;
-
- if (hwaddr_aton(cmd, addr)) {
- wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
- return -1;
- }
-
- sta = ap_get_sta(hapd, addr);
- if (sta == NULL) {
- wpa_printf(MSG_DEBUG, "Station " MACSTR
- " not found for BSS TM Request message",
- MAC2STR(addr));
- return -1;
- }
-
- pos = os_strstr(cmd, " disassoc_timer=");
- if (pos) {
- pos += 16;
- disassoc_timer = atoi(pos);
- if (disassoc_timer < 0 || disassoc_timer > 65535) {
- wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
- return -1;
- }
- }
-
- pos = os_strstr(cmd, " valid_int=");
- if (pos) {
- pos += 11;
- valid_int = atoi(pos);
- }
-
- pos = os_strstr(cmd, " dialog_token=");
- if (pos) {
- pos += 14;
- dialog_token = atoi(pos);
- }
-
- pos = os_strstr(cmd, " bss_term=");
- if (pos) {
- pos += 10;
- req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
- /* TODO: TSF configurable/learnable */
- bss_term_dur[0] = 4; /* Subelement ID */
- bss_term_dur[1] = 10; /* Length */
- os_memset(&bss_term_dur[2], 0, 8);
- end = os_strchr(pos, ',');
- if (end == NULL) {
- wpa_printf(MSG_DEBUG, "Invalid bss_term data");
- return -1;
- }
- end++;
- WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
- }
-
- nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep,
- sizeof(nei_rep));
- if (nei_len < 0)
- return -1;
-
- pos = os_strstr(cmd, " url=");
- if (pos) {
- size_t len;
- pos += 5;
- end = os_strchr(pos, ' ');
- if (end)
- len = end - pos;
- else
- len = os_strlen(pos);
- url = os_malloc(len + 1);
- if (url == NULL)
- return -1;
- os_memcpy(url, pos, len);
- url[len] = '\0';
- req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
- }
-
- if (os_strstr(cmd, " pref=1"))
- req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
- if (os_strstr(cmd, " abridged=1"))
- req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
- if (os_strstr(cmd, " disassoc_imminent=1"))
- req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
-
-#ifdef CONFIG_MBO
- pos = os_strstr(cmd, "mbo=");
- if (pos) {
- unsigned int mbo_reason, cell_pref, reassoc_delay;
- u8 *mbo_pos = mbo;
-
- ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
- &reassoc_delay, &cell_pref);
- if (ret != 3) {
- wpa_printf(MSG_DEBUG,
- "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
- ret = -1;
- goto fail;
- }
-
- if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
- wpa_printf(MSG_DEBUG,
- "Invalid MBO transition reason code %u",
- mbo_reason);
- ret = -1;
- goto fail;
- }
-
- /* Valid values for Cellular preference are: 0, 1, 255 */
- if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
- wpa_printf(MSG_DEBUG,
- "Invalid MBO cellular capability %u",
- cell_pref);
- ret = -1;
- goto fail;
- }
-
- if (reassoc_delay > 65535 ||
- (reassoc_delay &&
- !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
- wpa_printf(MSG_DEBUG,
- "MBO: Assoc retry delay is only valid in disassoc imminent mode");
- ret = -1;
- goto fail;
- }
-
- *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
- *mbo_pos++ = 1;
- *mbo_pos++ = mbo_reason;
- *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
- *mbo_pos++ = 1;
- *mbo_pos++ = cell_pref;
-
- if (reassoc_delay) {
- *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
- *mbo_pos++ = 2;
- WPA_PUT_LE16(mbo_pos, reassoc_delay);
- mbo_pos += 2;
- }
-
- mbo_len = mbo_pos - mbo;
- }
-#endif /* CONFIG_MBO */
-
- ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
- valid_int, bss_term_dur, dialog_token, url,
- nei_len ? nei_rep : NULL, nei_len,
- mbo_len ? mbo : NULL, mbo_len);
-#ifdef CONFIG_MBO
-fail:
-#endif /* CONFIG_MBO */
- os_free(url);
- return ret;
-}
-
-
static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd,
const char *cmd)
{
#include "ap_drv_ops.h"
#include "mbo_ap.h"
#include "taxonomy.h"
+#include "wnm_ap.h"
static size_t hostapd_write_ht_mcs_bitmask(char *buf, size_t buflen,
#endif /* CONFIG_MESH */
#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+
+#ifdef CONFIG_WNM_AP
+
+int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ int disassoc_timer;
+ struct sta_info *sta;
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+ if (cmd[17] != ' ')
+ return -1;
+ disassoc_timer = atoi(cmd + 17);
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for disassociation imminent message",
+ MAC2STR(addr));
+ return -1;
+ }
+
+ return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
+}
+
+
+int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ const char *url, *timerstr;
+ int disassoc_timer;
+ struct sta_info *sta;
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for ESS disassociation imminent message",
+ MAC2STR(addr));
+ return -1;
+ }
+
+ timerstr = cmd + 17;
+ if (*timerstr != ' ')
+ return -1;
+ timerstr++;
+ disassoc_timer = atoi(timerstr);
+ if (disassoc_timer < 0 || disassoc_timer > 65535)
+ return -1;
+
+ url = os_strchr(timerstr, ' ');
+ if (url == NULL)
+ return -1;
+ url++;
+
+ return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
+}
+
+
+int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ const char *pos, *end;
+ int disassoc_timer = 0;
+ struct sta_info *sta;
+ u8 req_mode = 0, valid_int = 0x01, dialog_token = 0x01;
+ u8 bss_term_dur[12];
+ char *url = NULL;
+ int ret;
+ u8 nei_rep[1000];
+ int nei_len;
+ u8 mbo[10];
+ size_t mbo_len = 0;
+
+ if (hwaddr_aton(cmd, addr)) {
+ wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
+ return -1;
+ }
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for BSS TM Request message",
+ MAC2STR(addr));
+ return -1;
+ }
+
+ pos = os_strstr(cmd, " disassoc_timer=");
+ if (pos) {
+ pos += 16;
+ disassoc_timer = atoi(pos);
+ if (disassoc_timer < 0 || disassoc_timer > 65535) {
+ wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
+ return -1;
+ }
+ }
+
+ pos = os_strstr(cmd, " valid_int=");
+ if (pos) {
+ pos += 11;
+ valid_int = atoi(pos);
+ }
+
+ pos = os_strstr(cmd, " dialog_token=");
+ if (pos) {
+ pos += 14;
+ dialog_token = atoi(pos);
+ }
+
+ pos = os_strstr(cmd, " bss_term=");
+ if (pos) {
+ pos += 10;
+ req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
+ /* TODO: TSF configurable/learnable */
+ bss_term_dur[0] = 4; /* Subelement ID */
+ bss_term_dur[1] = 10; /* Length */
+ os_memset(&bss_term_dur[2], 0, 8);
+ end = os_strchr(pos, ',');
+ if (end == NULL) {
+ wpa_printf(MSG_DEBUG, "Invalid bss_term data");
+ return -1;
+ }
+ end++;
+ WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
+ }
+
+ nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep,
+ sizeof(nei_rep));
+ if (nei_len < 0)
+ return -1;
+
+ pos = os_strstr(cmd, " url=");
+ if (pos) {
+ size_t len;
+ pos += 5;
+ end = os_strchr(pos, ' ');
+ if (end)
+ len = end - pos;
+ else
+ len = os_strlen(pos);
+ url = os_malloc(len + 1);
+ if (url == NULL)
+ return -1;
+ os_memcpy(url, pos, len);
+ url[len] = '\0';
+ req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
+ }
+
+ if (os_strstr(cmd, " pref=1"))
+ req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
+ if (os_strstr(cmd, " abridged=1"))
+ req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
+ if (os_strstr(cmd, " disassoc_imminent=1"))
+ req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+
+#ifdef CONFIG_MBO
+ pos = os_strstr(cmd, "mbo=");
+ if (pos) {
+ unsigned int mbo_reason, cell_pref, reassoc_delay;
+ u8 *mbo_pos = mbo;
+
+ ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
+ &reassoc_delay, &cell_pref);
+ if (ret != 3) {
+ wpa_printf(MSG_DEBUG,
+ "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
+ ret = -1;
+ goto fail;
+ }
+
+ if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid MBO transition reason code %u",
+ mbo_reason);
+ ret = -1;
+ goto fail;
+ }
+
+ /* Valid values for Cellular preference are: 0, 1, 255 */
+ if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid MBO cellular capability %u",
+ cell_pref);
+ ret = -1;
+ goto fail;
+ }
+
+ if (reassoc_delay > 65535 ||
+ (reassoc_delay &&
+ !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
+ wpa_printf(MSG_DEBUG,
+ "MBO: Assoc retry delay is only valid in disassoc imminent mode");
+ ret = -1;
+ goto fail;
+ }
+
+ *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = mbo_reason;
+ *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = cell_pref;
+
+ if (reassoc_delay) {
+ *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
+ *mbo_pos++ = 2;
+ WPA_PUT_LE16(mbo_pos, reassoc_delay);
+ mbo_pos += 2;
+ }
+
+ mbo_len = mbo_pos - mbo;
+ }
+#endif /* CONFIG_MBO */
+
+ ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
+ valid_int, bss_term_dur, dialog_token, url,
+ nei_len ? nei_rep : NULL, nei_len,
+ mbo_len ? mbo : NULL, mbo_len);
+#ifdef CONFIG_MBO
+fail:
+#endif /* CONFIG_MBO */
+ os_free(url);
+ return ret;
+}
+
+#endif /* CONFIG_WNM_AP */
const u8 *addr, char *buf, size_t len);
void * hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd);
+int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
+ const char *cmd);
+int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
+ const char *cmd);
+int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+ const char *cmd);
+
#endif /* CTRL_IFACE_AP_H */