From 88b4b4246d5d2a21f197359d7b5907a895bb3b14 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 30 Dec 2008 18:04:29 +0200 Subject: [PATCH] Added ctrl_interface command for sending a SA Query request This can be useful for testing IEEE 802.11w functionality, so provide means for manual request to send a SA Query request. --- hostapd/ctrl_iface.c | 25 +++++++++++++++++++++++++ hostapd/hostapd_cli.c | 22 ++++++++++++++++++++++ hostapd/ieee802_11.c | 25 +++++++++++++++++++++++++ hostapd/ieee802_11.h | 2 ++ hostapd/sta_info.c | 24 ------------------------ 5 files changed, 74 insertions(+), 24 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index f8b3a1dbc..7afd85962 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -218,6 +218,26 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, } +#ifdef CONFIG_IEEE80211W +static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, + const char *txtaddr) +{ + u8 addr[ETH_ALEN]; + u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + return -1; + + os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); + ieee802_11_send_sa_query_req(hapd, addr, trans_id); + + return 0; +} +#endif /* CONFIG_IEEE80211W */ + + #ifdef CONFIG_WPS static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) { @@ -313,6 +333,11 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) reply_len = -1; +#ifdef CONFIG_IEEE80211W + } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { + if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) + reply_len = -1; +#endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index e5285ae83..68ff091cf 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -83,6 +83,9 @@ static const char *commands_help = " sta get MIB variables for one station\n" " all_sta get MIB variables for all stations\n" " new_sta add a new station\n" +#ifdef CONFIG_IEEE80211W +" sa_query send SA Query to a station\n" +#endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS " wps_pin add WPS Enrollee PIN (Device Password)\n" " wps_pbc indicate button pushed to initiate PBC\n" @@ -234,6 +237,22 @@ static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc, } +#ifdef CONFIG_IEEE80211W +static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[64]; + if (argc != 1) { + printf("Invalid 'sa_query' command - exactly one argument, " + "STA address, is required.\n"); + return -1; + } + snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]); + return wpa_ctrl_command(ctrl, buf); +} +#endif /* CONFIG_IEEE80211W */ + + #ifdef CONFIG_WPS static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) @@ -405,6 +424,9 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = { { "sta", hostapd_cli_cmd_sta }, { "all_sta", hostapd_cli_cmd_all_sta }, { "new_sta", hostapd_cli_cmd_new_sta }, +#ifdef CONFIG_IEEE80211W + { "sa_query", hostapd_cli_cmd_sa_query }, +#endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS { "wps_pin", hostapd_cli_cmd_wps_pin }, { "wps_pbc", hostapd_cli_cmd_wps_pbc }, diff --git a/hostapd/ieee802_11.c b/hostapd/ieee802_11.c index 904b789c3..dc79a9121 100644 --- a/hostapd/ieee802_11.c +++ b/hostapd/ieee802_11.c @@ -1250,6 +1250,31 @@ static void handle_beacon(struct hostapd_data *hapd, #ifdef CONFIG_IEEE80211W + +/* MLME-SAQuery.request */ +void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, + const u8 *addr, const u8 *trans_id) +{ + struct ieee80211_mgmt mgmt; + u8 *end; + + os_memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(mgmt.da, addr, ETH_ALEN); + os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); + mgmt.u.action.category = WLAN_ACTION_SA_QUERY; + mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; + os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; + if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + + end - (u8 *) &mgmt, 0) < 0) + perror("ieee802_11_send_sa_query_req: send"); +} + + static void hostapd_sa_query_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, size_t len) { diff --git a/hostapd/ieee802_11.h b/hostapd/ieee802_11.h index bb88ede78..ca8ef93c0 100644 --- a/hostapd/ieee802_11.h +++ b/hostapd/ieee802_11.h @@ -50,5 +50,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid); int hostapd_ht_operation_update(struct hostapd_iface *iface); +void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, + const u8 *addr, const u8 *trans_id); #endif /* IEEE802_11_H */ diff --git a/hostapd/sta_info.c b/hostapd/sta_info.c index df1190135..55745e85e 100644 --- a/hostapd/sta_info.c +++ b/hostapd/sta_info.c @@ -613,30 +613,6 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, #ifdef CONFIG_IEEE80211W -/* MLME-SAQuery.request */ -static void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, - const u8 *addr, const u8 *trans_id) -{ - struct ieee80211_mgmt mgmt; - u8 *end; - - os_memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(mgmt.da, addr, ETH_ALEN); - os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.action.category = WLAN_ACTION_SA_QUERY; - mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; - os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, - WLAN_SA_QUERY_TR_ID_LEN); - end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + - end - (u8 *) &mgmt, 0) < 0) - perror("ieee802_11_send_sa_query_req: send"); -} - - int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) { u32 tu;