nl80211: Add preliminary implementation of FT Action send

This is a step in adding FT support with nl80211-based drivers.
driver_nl80211.c is now registering to handle the FT Action frames
and is able to transmit FT Request frame. Received FT Action frames
are not yet indicated as driver events.
This commit is contained in:
Jouni Malinen 2010-03-07 22:47:39 +02:00
parent 1b484d60e5
commit 7b90c16aa9

View file

@ -1338,6 +1338,14 @@ static int nl80211_register_action_frames(struct wpa_driver_nl80211_data *drv)
/* Public Action frames */
return nl80211_register_action_frame(drv, (u8 *) "\x04", 1);
}
/* FT Action frames */
if (nl80211_register_action_frame(drv, (u8 *) "\x06", 1) < 0)
return -1;
else
drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
return 0;
}
@ -1369,8 +1377,15 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
1, IF_OPER_DORMANT);
#endif /* HOSTAPD */
if (nl80211_register_action_frames(drv) < 0)
return -1;
if (nl80211_register_action_frames(drv) < 0) {
wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
"frame processing - ignore for now");
/*
* Older kernel versions did not support this, so ignore the
* error for now. Some functionality may not be available
* because of this.
*/
}
return 0;
}
@ -5083,6 +5098,56 @@ static void wpa_driver_nl80211_resume(void *priv)
}
static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
const u8 *ies, size_t ies_len)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
int ret;
u8 *data, *pos;
size_t data_len;
u8 own_addr[ETH_ALEN];
if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr) < 0)
return -1;
if (action != 1) {
wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action "
"action %d", action);
return -1;
}
/*
* Action frame payload:
* Category[1] = 6 (Fast BSS Transition)
* Action[1] = 1 (Fast BSS Transition Request)
* STA Address
* Target AP Address
* FT IEs
*/
data_len = ies_len;
data = os_malloc(2 + 2 * ETH_ALEN + data_len);
if (data == NULL)
return -1;
pos = data;
*pos++ = 0x06; /* FT Action category */
*pos++ = action;
os_memcpy(pos, own_addr, ETH_ALEN);
pos += ETH_ALEN;
os_memcpy(pos, target_ap, ETH_ALEN);
pos += ETH_ALEN;
os_memcpy(pos, ies, ies_len);
ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, drv->bssid,
own_addr, drv->bssid,
data, data_len);
os_free(data);
return ret;
}
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@ -5141,4 +5206,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.disable_11b_rates = wpa_driver_nl80211_disable_11b_rates,
.deinit_ap = wpa_driver_nl80211_deinit_ap,
.resume = wpa_driver_nl80211_resume,
.send_ft_action = nl80211_send_ft_action,
};