wlantest: Add support for injecting (Re)Association Request frames
authorJouni Malinen <jouni.malinen@atheros.com>
Fri, 19 Nov 2010 15:09:02 +0000 (17:09 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 19 Nov 2010 15:09:02 +0000 (17:09 +0200)
wlantest/ctrl.c
wlantest/rx_mgmt.c
wlantest/sta.c
wlantest/wlantest.h

index d5cea99..6cbac0a 100644 (file)
@@ -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;
index 45a0053..e9ab330 100644 (file)
@@ -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);
 }
 
index f3517e7..f264d36 100644 (file)
@@ -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);
 }
 
index 7dd0109..9f91b75 100644 (file)
@@ -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 {