diff --git a/wlantest/ctrl.c b/wlantest/ctrl.c index d5cea99b4..6cbac0a7c 100644 --- a/wlantest/ctrl.c +++ b/wlantest/ctrl.c @@ -403,6 +403,99 @@ static int ctrl_inject_auth(struct wlantest *wt, struct wlantest_bss *bss, } +static int ctrl_inject_assocreq(struct wlantest *wt, struct wlantest_bss *bss, + struct wlantest_sta *sta, int sender_ap, + enum wlantest_inject_protection prot) +{ + u8 *buf; + struct ieee80211_mgmt *mgmt; + int ret; + + if (prot != WLANTEST_INJECT_NORMAL && + prot != WLANTEST_INJECT_UNPROTECTED) + return -1; /* Association Request frame is never protected */ + if (sta == NULL) + return -1; /* No broadcast Association Request frames */ + if (sender_ap) + return -1; /* No Association Request frame sent by AP */ + if (sta->assocreq_ies == NULL) { + wpa_printf(MSG_INFO, "INJECT: No previous (Re)Association " + "Request available for " MACSTR, + MAC2STR(sta->addr)); + return -1; + } + + wpa_printf(MSG_INFO, "INJECT: AssocReq " MACSTR " -> " MACSTR, + MAC2STR(sta->addr), MAC2STR(bss->bssid)); + buf = os_malloc(sizeof(*mgmt) + sta->assocreq_ies_len); + if (buf == NULL) + return -1; + mgmt = (struct ieee80211_mgmt *) buf; + + build_mgmt_hdr(mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_ASSOC_REQ); + + mgmt->u.assoc_req.capab_info = host_to_le16(sta->assocreq_capab_info); + mgmt->u.assoc_req.listen_interval = + host_to_le16(sta->assocreq_listen_int); + os_memcpy(mgmt->u.assoc_req.variable, sta->assocreq_ies, + sta->assocreq_ies_len); + + ret = wlantest_inject(wt, bss, sta, buf, + 24 + 4 + sta->assocreq_ies_len, + WLANTEST_INJECT_UNPROTECTED); + os_free(buf); + return ret; +} + + +static int ctrl_inject_reassocreq(struct wlantest *wt, + struct wlantest_bss *bss, + struct wlantest_sta *sta, int sender_ap, + enum wlantest_inject_protection prot) +{ + u8 *buf; + struct ieee80211_mgmt *mgmt; + int ret; + + if (prot != WLANTEST_INJECT_NORMAL && + prot != WLANTEST_INJECT_UNPROTECTED) + return -1; /* Reassociation Request frame is never protected */ + if (sta == NULL) + return -1; /* No broadcast Reassociation Request frames */ + if (sender_ap) + return -1; /* No Reassociation Request frame sent by AP */ + if (sta->assocreq_ies == NULL) { + wpa_printf(MSG_INFO, "INJECT: No previous (Re)Association " + "Request available for " MACSTR, + MAC2STR(sta->addr)); + return -1; + } + + wpa_printf(MSG_INFO, "INJECT: ReassocReq " MACSTR " -> " MACSTR, + MAC2STR(sta->addr), MAC2STR(bss->bssid)); + buf = os_malloc(sizeof(*mgmt) + sta->assocreq_ies_len); + if (buf == NULL) + return -1; + mgmt = (struct ieee80211_mgmt *) buf; + + build_mgmt_hdr(mgmt, bss, sta, sender_ap, WLAN_FC_STYPE_REASSOC_REQ); + + mgmt->u.reassoc_req.capab_info = + host_to_le16(sta->assocreq_capab_info); + mgmt->u.reassoc_req.listen_interval = + host_to_le16(sta->assocreq_listen_int); + os_memcpy(mgmt->u.reassoc_req.current_ap, bss->bssid, ETH_ALEN); + os_memcpy(mgmt->u.reassoc_req.variable, sta->assocreq_ies, + sta->assocreq_ies_len); + + ret = wlantest_inject(wt, bss, sta, buf, + 24 + 10 + sta->assocreq_ies_len, + WLANTEST_INJECT_UNPROTECTED); + os_free(buf); + return ret; +} + + static int ctrl_inject_deauth(struct wlantest *wt, struct wlantest_bss *bss, struct wlantest_sta *sta, int sender_ap, enum wlantest_inject_protection prot) @@ -531,6 +624,12 @@ static void ctrl_inject(struct wlantest *wt, int sock, u8 *cmd, size_t clen) case WLANTEST_FRAME_AUTH: ret = ctrl_inject_auth(wt, bss, sta, sender_ap, prot); break; + case WLANTEST_FRAME_ASSOCREQ: + ret = ctrl_inject_assocreq(wt, bss, sta, sender_ap, prot); + break; + case WLANTEST_FRAME_REASSOCREQ: + ret = ctrl_inject_reassocreq(wt, bss, sta, sender_ap, prot); + break; case WLANTEST_FRAME_DEAUTH: ret = ctrl_inject_deauth(wt, bss, sta, sender_ap, prot); break; diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 45a0053ea..e9ab33035 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -246,6 +246,16 @@ static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len) return; } + sta->assocreq_capab_info = le_to_host16(mgmt->u.assoc_req.capab_info); + sta->assocreq_listen_int = + le_to_host16(mgmt->u.assoc_req.listen_interval); + os_free(sta->assocreq_ies); + sta->assocreq_ies_len = len - (mgmt->u.assoc_req.variable - data); + sta->assocreq_ies = os_malloc(sta->assocreq_ies_len); + if (sta->assocreq_ies) + os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable, + sta->assocreq_ies_len); + sta_update_assoc(sta, &elems); } @@ -343,6 +353,17 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, return; } + sta->assocreq_capab_info = + le_to_host16(mgmt->u.reassoc_req.capab_info); + sta->assocreq_listen_int = + le_to_host16(mgmt->u.reassoc_req.listen_interval); + os_free(sta->assocreq_ies); + sta->assocreq_ies_len = len - (mgmt->u.reassoc_req.variable - data); + sta->assocreq_ies = os_malloc(sta->assocreq_ies_len); + if (sta->assocreq_ies) + os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable, + sta->assocreq_ies_len); + sta_update_assoc(sta, &elems); } diff --git a/wlantest/sta.c b/wlantest/sta.c index f3517e7a1..f264d36ee 100644 --- a/wlantest/sta.c +++ b/wlantest/sta.c @@ -47,6 +47,7 @@ struct wlantest_sta * sta_get(struct wlantest_bss *bss, const u8 *addr) void sta_deinit(struct wlantest_sta *sta) { dl_list_del(&sta->list); + os_free(sta->assocreq_ies); os_free(sta); } diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 7dd010939..9f91b754a 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -69,6 +69,10 @@ struct wlantest_sta { u8 ap_sa_query_tr[2]; u8 sta_sa_query_tr[2]; u32 counters[NUM_WLANTEST_STA_COUNTER]; + u16 assocreq_capab_info; + u16 assocreq_listen_int; + u8 *assocreq_ies; + size_t assocreq_ies_len; }; struct wlantest_bss {