netdev: Add netdev_reassociate
netdev_reassociate transitions to another BSS without FT. Similar to netdev_connect but uses reassociation instead of association and requires and an existing connection.
This commit is contained in:
parent
bb350a3b8e
commit
c8b251a475
68
src/netdev.c
68
src/netdev.c
|
@ -1857,7 +1857,8 @@ static void netdev_cmd_connect_cb(struct l_genl_msg *msg, void *user_data)
|
||||||
|
|
||||||
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
||||||
struct scan_bss *bss,
|
struct scan_bss *bss,
|
||||||
struct handshake_state *hs)
|
struct handshake_state *hs,
|
||||||
|
const uint8_t *prev_bssid)
|
||||||
{
|
{
|
||||||
uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
|
uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
|
||||||
struct l_genl_msg *msg;
|
struct l_genl_msg *msg;
|
||||||
|
@ -1874,6 +1875,10 @@ static struct l_genl_msg *netdev_build_cmd_connect(struct netdev *netdev,
|
||||||
bss->ssid_len, bss->ssid);
|
bss->ssid_len, bss->ssid);
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
|
l_genl_msg_append_attr(msg, NL80211_ATTR_AUTH_TYPE, 4, &auth_type);
|
||||||
|
|
||||||
|
if (prev_bssid)
|
||||||
|
l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
|
||||||
|
prev_bssid);
|
||||||
|
|
||||||
if (bss->capability & IE_BSS_CAP_PRIVACY)
|
if (bss->capability & IE_BSS_CAP_PRIVACY)
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
|
l_genl_msg_append_attr(msg, NL80211_ATTR_PRIVACY, 0, NULL);
|
||||||
|
|
||||||
|
@ -1979,7 +1984,7 @@ int netdev_connect(struct netdev *netdev, struct scan_bss *bss,
|
||||||
if (netdev->connected)
|
if (netdev->connected)
|
||||||
return -EISCONN;
|
return -EISCONN;
|
||||||
|
|
||||||
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs);
|
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs, NULL);
|
||||||
if (!cmd_connect)
|
if (!cmd_connect)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -2008,7 +2013,7 @@ int netdev_connect_wsc(struct netdev *netdev, struct scan_bss *bss,
|
||||||
if (netdev->connected)
|
if (netdev->connected)
|
||||||
return -EISCONN;
|
return -EISCONN;
|
||||||
|
|
||||||
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs);
|
cmd_connect = netdev_build_cmd_connect(netdev, bss, hs, NULL);
|
||||||
if (!cmd_connect)
|
if (!cmd_connect)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -2077,6 +2082,63 @@ int netdev_disconnect(struct netdev *netdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int netdev_reassociate(struct netdev *netdev, struct scan_bss *target_bss,
|
||||||
|
struct handshake_state *hs, netdev_connect_cb_t cb)
|
||||||
|
{
|
||||||
|
struct l_genl_msg *cmd_connect;
|
||||||
|
struct handshake_state *old_hs;
|
||||||
|
struct eapol_sm *sm = NULL, *old_sm;
|
||||||
|
bool is_rsn = hs->own_ie != NULL;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!netdev->operational)
|
||||||
|
return -ENOTCONN;
|
||||||
|
|
||||||
|
cmd_connect = netdev_build_cmd_connect(netdev, target_bss, hs,
|
||||||
|
netdev->handshake->aa);
|
||||||
|
if (!cmd_connect)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (is_rsn)
|
||||||
|
sm = eapol_sm_new(hs);
|
||||||
|
|
||||||
|
old_sm = netdev->sm;
|
||||||
|
old_hs = netdev->handshake;
|
||||||
|
|
||||||
|
err = netdev_connect_common(netdev, cmd_connect, target_bss, hs, sm,
|
||||||
|
netdev->event_filter, cb,
|
||||||
|
netdev->user_data);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
memcpy(netdev->prev_bssid, old_hs->aa, ETH_ALEN);
|
||||||
|
|
||||||
|
netdev->operational = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cancel commands that could be running because of EAPoL activity
|
||||||
|
* like re-keying, this way the callbacks for those commands don't
|
||||||
|
* have to check if failures resulted from the transition.
|
||||||
|
*/
|
||||||
|
if (netdev->group_new_key_cmd_id) {
|
||||||
|
l_genl_family_cancel(nl80211, netdev->group_new_key_cmd_id);
|
||||||
|
netdev->group_new_key_cmd_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netdev->group_management_new_key_cmd_id) {
|
||||||
|
l_genl_family_cancel(nl80211,
|
||||||
|
netdev->group_management_new_key_cmd_id);
|
||||||
|
netdev->group_management_new_key_cmd_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_sm)
|
||||||
|
eapol_sm_free(old_sm);
|
||||||
|
|
||||||
|
handshake_state_free(old_hs);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build an FT Authentication Request frame according to 12.5.2 / 12.5.4:
|
* Build an FT Authentication Request frame according to 12.5.2 / 12.5.4:
|
||||||
* RSN or non-RSN Over-the-air FT Protocol, with the IE contents
|
* RSN or non-RSN Over-the-air FT Protocol, with the IE contents
|
||||||
|
|
|
@ -96,6 +96,9 @@ int netdev_connect_wsc(struct netdev *netdev, struct scan_bss *bss,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
int netdev_disconnect(struct netdev *netdev,
|
int netdev_disconnect(struct netdev *netdev,
|
||||||
netdev_disconnect_cb_t cb, void *user_data);
|
netdev_disconnect_cb_t cb, void *user_data);
|
||||||
|
int netdev_reassociate(struct netdev *netdev, struct scan_bss *target_bss,
|
||||||
|
struct handshake_state *hs,
|
||||||
|
netdev_connect_cb_t cb);
|
||||||
int netdev_fast_transition(struct netdev *netdev, struct scan_bss *target_bss,
|
int netdev_fast_transition(struct netdev *netdev, struct scan_bss *target_bss,
|
||||||
netdev_connect_cb_t cb);
|
netdev_connect_cb_t cb);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue