mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-29 05:39:24 +01:00
station: Move remaining connect/re-connect/roam logic
This commit is contained in:
parent
0912a6afb8
commit
25f36f5644
348
src/device.c
348
src/device.c
@ -49,7 +49,6 @@
|
|||||||
|
|
||||||
struct device {
|
struct device {
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
uint8_t preauth_bssid[ETH_ALEN];
|
|
||||||
|
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
struct netdev *netdev;
|
struct netdev *netdev;
|
||||||
@ -62,9 +61,6 @@ struct device {
|
|||||||
|
|
||||||
static uint32_t netdev_watch;
|
static uint32_t netdev_watch;
|
||||||
|
|
||||||
static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
|
||||||
void *user_data);
|
|
||||||
|
|
||||||
/* TODO: Remove when Station/Device is split */
|
/* TODO: Remove when Station/Device is split */
|
||||||
static bool device_is_busy(struct device *device)
|
static bool device_is_busy(struct device *device)
|
||||||
{
|
{
|
||||||
@ -74,223 +70,6 @@ static bool device_is_busy(struct device *device)
|
|||||||
return station_is_busy(device->station);
|
return station_is_busy(device->station);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_reassociate_cb(struct netdev *netdev,
|
|
||||||
enum netdev_result result,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
struct station *station = device->station;
|
|
||||||
|
|
||||||
l_debug("%d, result: %d", device->index, result);
|
|
||||||
|
|
||||||
if (station->state != STATION_STATE_ROAMING)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (result == NETDEV_RESULT_OK) {
|
|
||||||
station_roamed(station);
|
|
||||||
station_enter_state(station, STATION_STATE_CONNECTED);
|
|
||||||
} else
|
|
||||||
station_roam_failed(station);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_fast_transition_cb(struct netdev *netdev,
|
|
||||||
enum netdev_result result,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
struct station *station = device->station;
|
|
||||||
|
|
||||||
l_debug("%d, result: %d", device->index, result);
|
|
||||||
|
|
||||||
if (station->state != STATION_STATE_ROAMING)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (result == NETDEV_RESULT_OK) {
|
|
||||||
station_roamed(station);
|
|
||||||
station_enter_state(station, STATION_STATE_CONNECTED);
|
|
||||||
} else
|
|
||||||
station_roam_failed(station);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_transition_reassociate(struct device *device,
|
|
||||||
struct scan_bss *bss,
|
|
||||||
struct handshake_state *new_hs)
|
|
||||||
{
|
|
||||||
struct station *station = device->station;
|
|
||||||
|
|
||||||
if (netdev_reassociate(device->netdev, bss, station->connected_bss,
|
|
||||||
new_hs, device_netdev_event,
|
|
||||||
device_reassociate_cb, device) < 0) {
|
|
||||||
handshake_state_free(new_hs);
|
|
||||||
station_roam_failed(station);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
station->connected_bss = bss;
|
|
||||||
station->preparing_roam = false;
|
|
||||||
station_enter_state(station, STATION_STATE_ROAMING);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool bss_match_bssid(const void *a, const void *b)
|
|
||||||
{
|
|
||||||
const struct scan_bss *bss = a;
|
|
||||||
const uint8_t *bssid = b;
|
|
||||||
|
|
||||||
return !memcmp(bss->addr, bssid, sizeof(bss->addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_preauthenticate_cb(struct netdev *netdev,
|
|
||||||
enum netdev_result result,
|
|
||||||
const uint8_t *pmk, void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
struct station *station = device->station;
|
|
||||||
struct network *connected = station->connected_network;
|
|
||||||
struct scan_bss *bss;
|
|
||||||
struct handshake_state *new_hs;
|
|
||||||
|
|
||||||
l_debug("%d, result: %d", device->index, result);
|
|
||||||
|
|
||||||
if (!station->preparing_roam || result == NETDEV_RESULT_ABORTED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bss = l_queue_find(device->station->bss_list, bss_match_bssid,
|
|
||||||
device->preauth_bssid);
|
|
||||||
if (!bss) {
|
|
||||||
l_error("Roam target BSS not found");
|
|
||||||
station_roam_failed(station);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_hs = station_handshake_setup(station, connected, bss);
|
|
||||||
if (!new_hs) {
|
|
||||||
l_error("device_handshake_setup failed");
|
|
||||||
|
|
||||||
station_roam_failed(station);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == NETDEV_RESULT_OK) {
|
|
||||||
uint8_t pmkid[16];
|
|
||||||
uint8_t rsne_buf[300];
|
|
||||||
struct ie_rsn_info rsn_info;
|
|
||||||
|
|
||||||
handshake_state_set_pmk(new_hs, pmk, 32);
|
|
||||||
handshake_state_set_authenticator_address(new_hs,
|
|
||||||
device->preauth_bssid);
|
|
||||||
handshake_state_set_supplicant_address(new_hs,
|
|
||||||
netdev_get_address(device->netdev));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Rebuild the RSNE to include the negotiated PMKID. Note
|
|
||||||
* supplicant_ie can't be a WPA IE here, including because
|
|
||||||
* the WPA IE doesn't have a capabilities field and
|
|
||||||
* target_rsne->preauthentication would have been false in
|
|
||||||
* device_transition_start.
|
|
||||||
*/
|
|
||||||
ie_parse_rsne_from_data(new_hs->supplicant_ie,
|
|
||||||
new_hs->supplicant_ie[1] + 2,
|
|
||||||
&rsn_info);
|
|
||||||
|
|
||||||
handshake_state_get_pmkid(new_hs, pmkid);
|
|
||||||
|
|
||||||
rsn_info.num_pmkids = 1;
|
|
||||||
rsn_info.pmkids = pmkid;
|
|
||||||
|
|
||||||
ie_build_rsne(&rsn_info, rsne_buf);
|
|
||||||
handshake_state_set_supplicant_rsn(new_hs, rsne_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
device_transition_reassociate(device, bss, new_hs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_transition_start(struct device *device, struct scan_bss *bss)
|
|
||||||
{
|
|
||||||
struct station *station = device->station;
|
|
||||||
struct handshake_state *hs = netdev_get_handshake(device->netdev);
|
|
||||||
struct network *connected = station->connected_network;
|
|
||||||
enum security security = network_get_security(connected);
|
|
||||||
uint16_t mdid;
|
|
||||||
struct handshake_state *new_hs;
|
|
||||||
struct ie_rsn_info cur_rsne, target_rsne;
|
|
||||||
|
|
||||||
l_debug("%d, target %s", device->index,
|
|
||||||
util_address_to_string(bss->addr));
|
|
||||||
|
|
||||||
/* Reset AP roam flag, at this point the roaming behaves the same */
|
|
||||||
station->ap_directed_roaming = false;
|
|
||||||
|
|
||||||
if (hs->mde)
|
|
||||||
ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
|
|
||||||
&mdid, NULL, NULL);
|
|
||||||
|
|
||||||
/* Can we use Fast Transition? */
|
|
||||||
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) {
|
|
||||||
/*
|
|
||||||
* There's no need to regenerate the RSNE because neither
|
|
||||||
* the AKM nor cipher suite can change:
|
|
||||||
*
|
|
||||||
* 12.5.2: "If the FTO selects a pairwise cipher suite in
|
|
||||||
* the RSNE that is different from the ones used in the
|
|
||||||
* Initial mobility domain association, then the AP shall
|
|
||||||
* reject the Authentication Request with status code 19
|
|
||||||
* (i.e., Invalid Pairwise Cipher)."
|
|
||||||
*/
|
|
||||||
if (netdev_fast_transition(device->netdev, bss,
|
|
||||||
device_fast_transition_cb) < 0) {
|
|
||||||
station_roam_failed(station);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
station->connected_bss = bss;
|
|
||||||
station->preparing_roam = false;
|
|
||||||
station_enter_state(station, STATION_STATE_ROAMING);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Non-FT transition */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FT not available, we can try preauthentication if available.
|
|
||||||
* 802.11-2012 section 11.5.9.2:
|
|
||||||
* "A STA shall not use preauthentication within the same mobility
|
|
||||||
* domain if AKM suite type 00-0F-AC:3 or 00-0F-AC:4 is used in
|
|
||||||
* the current association."
|
|
||||||
*/
|
|
||||||
if (security == SECURITY_8021X &&
|
|
||||||
!station->roam_no_orig_ap &&
|
|
||||||
scan_bss_get_rsn_info(station->connected_bss,
|
|
||||||
&cur_rsne) >= 0 &&
|
|
||||||
scan_bss_get_rsn_info(bss, &target_rsne) >= 0 &&
|
|
||||||
cur_rsne.preauthentication &&
|
|
||||||
target_rsne.preauthentication) {
|
|
||||||
/*
|
|
||||||
* Both the current and the target AP support
|
|
||||||
* pre-authentication and we're using 8021x authentication so
|
|
||||||
* attempt to pre-authenticate and reassociate afterwards.
|
|
||||||
* If the pre-authentication fails or times out we simply
|
|
||||||
* won't supply any PMKID when reassociating.
|
|
||||||
* Remain in the preparing_roam state.
|
|
||||||
*/
|
|
||||||
memcpy(device->preauth_bssid, bss->addr, ETH_ALEN);
|
|
||||||
|
|
||||||
if (netdev_preauthenticate(device->netdev, bss,
|
|
||||||
device_preauthenticate_cb,
|
|
||||||
device) >= 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_hs = station_handshake_setup(station, connected, bss);
|
|
||||||
if (!new_hs) {
|
|
||||||
l_error("device_handshake_setup failed in reassociation");
|
|
||||||
station_roam_failed(station);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
device_transition_reassociate(device, bss, new_hs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_ap_roam_frame_event(struct netdev *netdev,
|
static void device_ap_roam_frame_event(struct netdev *netdev,
|
||||||
const struct mmpdu_header *hdr,
|
const struct mmpdu_header *hdr,
|
||||||
const void *body, size_t body_len,
|
const void *body, size_t body_len,
|
||||||
@ -302,133 +81,6 @@ static void device_ap_roam_frame_event(struct netdev *netdev,
|
|||||||
station_ap_directed_roam(station, hdr, body, body_len);
|
station_ap_directed_roam(station, hdr, body, body_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void device_connect_cb(struct netdev *netdev, enum netdev_result result,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
struct station *station = device->station;
|
|
||||||
|
|
||||||
l_debug("%d, result: %d", device->index, result);
|
|
||||||
|
|
||||||
if (station->connect_pending) {
|
|
||||||
struct l_dbus_message *reply;
|
|
||||||
|
|
||||||
switch (result) {
|
|
||||||
case NETDEV_RESULT_ABORTED:
|
|
||||||
reply = dbus_error_aborted(station->connect_pending);
|
|
||||||
break;
|
|
||||||
case NETDEV_RESULT_OK:
|
|
||||||
reply = l_dbus_message_new_method_return(
|
|
||||||
station->connect_pending);
|
|
||||||
l_dbus_message_set_arguments(reply, "");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
reply = dbus_error_failed(station->connect_pending);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_pending_reply(&station->connect_pending, reply);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != NETDEV_RESULT_OK) {
|
|
||||||
if (result != NETDEV_RESULT_ABORTED) {
|
|
||||||
network_connect_failed(station->connected_network);
|
|
||||||
station_disassociated(station);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
network_connected(station->connected_network);
|
|
||||||
station_enter_state(station, STATION_STATE_CONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void device_netdev_event(struct netdev *netdev, enum netdev_event event,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct device *device = user_data;
|
|
||||||
struct station *station = device->station;
|
|
||||||
|
|
||||||
switch (event) {
|
|
||||||
case NETDEV_EVENT_AUTHENTICATING:
|
|
||||||
l_debug("Authenticating");
|
|
||||||
break;
|
|
||||||
case NETDEV_EVENT_ASSOCIATING:
|
|
||||||
l_debug("Associating");
|
|
||||||
break;
|
|
||||||
case NETDEV_EVENT_LOST_BEACON:
|
|
||||||
station_lost_beacon(station);
|
|
||||||
break;
|
|
||||||
case NETDEV_EVENT_DISCONNECT_BY_AP:
|
|
||||||
case NETDEV_EVENT_DISCONNECT_BY_SME:
|
|
||||||
station_disconnect_event(station);
|
|
||||||
break;
|
|
||||||
case NETDEV_EVENT_RSSI_THRESHOLD_LOW:
|
|
||||||
station_low_rssi(station);
|
|
||||||
break;
|
|
||||||
case NETDEV_EVENT_RSSI_THRESHOLD_HIGH:
|
|
||||||
station_ok_rssi(station);
|
|
||||||
break;
|
|
||||||
case NETDEV_EVENT_RSSI_LEVEL_NOTIFY:
|
|
||||||
station_rssi_level_changed(station);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
int __device_connect_network(struct device *device, struct network *network,
|
|
||||||
struct scan_bss *bss)
|
|
||||||
{
|
|
||||||
struct l_dbus *dbus = dbus_get_bus();
|
|
||||||
struct station *station = device->station;
|
|
||||||
struct netdev *netdev = station->netdev;
|
|
||||||
struct handshake_state *hs;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (device_is_busy(device))
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
hs = station_handshake_setup(station, network, bss);
|
|
||||||
if (!hs)
|
|
||||||
return -ENOTSUP;
|
|
||||||
|
|
||||||
r = netdev_connect(device->netdev, bss, hs, device_netdev_event,
|
|
||||||
device_connect_cb, device);
|
|
||||||
if (r < 0) {
|
|
||||||
handshake_state_free(hs);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
station->connected_bss = bss;
|
|
||||||
station->connected_network = network;
|
|
||||||
|
|
||||||
station_enter_state(station, STATION_STATE_CONNECTING);
|
|
||||||
|
|
||||||
l_dbus_property_changed(dbus, netdev_get_path(netdev),
|
|
||||||
IWD_DEVICE_INTERFACE, "ConnectedNetwork");
|
|
||||||
l_dbus_property_changed(dbus, network_get_path(network),
|
|
||||||
IWD_NETWORK_INTERFACE, "Connected");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_connect_network(struct device *device, struct network *network,
|
|
||||||
struct scan_bss *bss,
|
|
||||||
struct l_dbus_message *message)
|
|
||||||
{
|
|
||||||
struct station *station = device->station;
|
|
||||||
int err = __device_connect_network(device, network, bss);
|
|
||||||
|
|
||||||
if (err < 0) {
|
|
||||||
struct l_dbus *dbus = dbus_get_bus();
|
|
||||||
|
|
||||||
l_dbus_send(dbus, dbus_error_from_errno(err, message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
station->connect_pending = l_dbus_message_ref(message);
|
|
||||||
station->autoconnect = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct l_dbus_message *device_scan(struct l_dbus *dbus,
|
static struct l_dbus_message *device_scan(struct l_dbus *dbus,
|
||||||
struct l_dbus_message *message,
|
struct l_dbus_message *message,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
|
@ -22,18 +22,9 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct scan_bss;
|
|
||||||
struct wiphy;
|
struct wiphy;
|
||||||
struct netdev;
|
struct netdev;
|
||||||
struct network;
|
|
||||||
struct device;
|
struct device;
|
||||||
|
|
||||||
void device_transition_start(struct device *device, struct scan_bss *bss);
|
|
||||||
|
|
||||||
int __device_connect_network(struct device *device, struct network *network,
|
|
||||||
struct scan_bss *bss);
|
|
||||||
void device_connect_network(struct device *device, struct network *network,
|
|
||||||
struct scan_bss *bss,
|
|
||||||
struct l_dbus_message *message);
|
|
||||||
struct device *device_create(struct wiphy *wiphy, struct netdev *netdev);
|
struct device *device_create(struct wiphy *wiphy, struct netdev *netdev);
|
||||||
void device_remove(struct device *device);
|
void device_remove(struct device *device);
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
#include "src/dbus.h"
|
#include "src/dbus.h"
|
||||||
#include "src/agent.h"
|
#include "src/agent.h"
|
||||||
#include "src/netdev.h"
|
#include "src/netdev.h"
|
||||||
#include "src/device.h"
|
|
||||||
#include "src/wiphy.h"
|
#include "src/wiphy.h"
|
||||||
#include "src/watchlist.h"
|
#include "src/watchlist.h"
|
||||||
#include "src/station.h"
|
#include "src/station.h"
|
||||||
@ -463,8 +462,6 @@ int network_autoconnect(struct network *network, struct scan_bss *bss)
|
|||||||
{
|
{
|
||||||
struct station *station = network->station;
|
struct station *station = network->station;
|
||||||
struct wiphy *wiphy = station_get_wiphy(station);
|
struct wiphy *wiphy = station_get_wiphy(station);
|
||||||
struct netdev *netdev = station_get_netdev(station);
|
|
||||||
struct device *device = netdev_get_device(netdev);
|
|
||||||
bool is_autoconnectable;
|
bool is_autoconnectable;
|
||||||
bool is_rsn;
|
bool is_rsn;
|
||||||
int ret;
|
int ret;
|
||||||
@ -540,7 +537,7 @@ int network_autoconnect(struct network *network, struct scan_bss *bss)
|
|||||||
goto close_settings;
|
goto close_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
return __device_connect_network(device, network, bss);
|
return __station_connect_network(station, network, bss);
|
||||||
|
|
||||||
close_settings:
|
close_settings:
|
||||||
network_settings_close(network);
|
network_settings_close(network);
|
||||||
@ -635,8 +632,6 @@ static void passphrase_callback(enum agent_result result,
|
|||||||
{
|
{
|
||||||
struct network *network = user_data;
|
struct network *network = user_data;
|
||||||
struct station *station = network->station;
|
struct station *station = network->station;
|
||||||
struct netdev *netdev = station_get_netdev(station);
|
|
||||||
struct device *device = netdev_get_device(netdev);
|
|
||||||
struct scan_bss *bss;
|
struct scan_bss *bss;
|
||||||
|
|
||||||
l_debug("result %d", result);
|
l_debug("result %d", result);
|
||||||
@ -686,7 +681,7 @@ static void passphrase_callback(enum agent_result result,
|
|||||||
*/
|
*/
|
||||||
network->update_psk = true;
|
network->update_psk = true;
|
||||||
|
|
||||||
device_connect_network(device, network, bss, message);
|
station_connect_network(station, network, bss, message);
|
||||||
l_dbus_message_unref(message);
|
l_dbus_message_unref(message);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -712,8 +707,6 @@ static struct l_dbus_message *network_connect_psk(struct network *network,
|
|||||||
struct l_dbus_message *message)
|
struct l_dbus_message *message)
|
||||||
{
|
{
|
||||||
struct station *station = network->station;
|
struct station *station = network->station;
|
||||||
struct netdev *netdev = station_get_netdev(station);
|
|
||||||
struct device *device = netdev_get_device(netdev);
|
|
||||||
|
|
||||||
l_debug("");
|
l_debug("");
|
||||||
|
|
||||||
@ -742,7 +735,7 @@ static struct l_dbus_message *network_connect_psk(struct network *network,
|
|||||||
if (!network->agent_request)
|
if (!network->agent_request)
|
||||||
return dbus_error_no_agent(message);
|
return dbus_error_no_agent(message);
|
||||||
} else
|
} else
|
||||||
device_connect_network(device, network, bss, message);
|
station_connect_network(station, network, bss, message);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -942,8 +935,6 @@ static struct l_dbus_message *network_connect_8021x(struct network *network,
|
|||||||
struct l_dbus_message *message)
|
struct l_dbus_message *message)
|
||||||
{
|
{
|
||||||
struct station *station = network->station;
|
struct station *station = network->station;
|
||||||
struct netdev *netdev = station_get_netdev(station);
|
|
||||||
struct device *device = netdev_get_device(netdev);
|
|
||||||
int r;
|
int r;
|
||||||
struct l_queue *missing_secrets = NULL;
|
struct l_queue *missing_secrets = NULL;
|
||||||
struct l_dbus_message *reply;
|
struct l_dbus_message *reply;
|
||||||
@ -976,7 +967,7 @@ static struct l_dbus_message *network_connect_8021x(struct network *network,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_connect_network(device, network, bss, message);
|
station_connect_network(station, network, bss, message);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1002,8 +993,6 @@ static struct l_dbus_message *network_connect(struct l_dbus *dbus,
|
|||||||
{
|
{
|
||||||
struct network *network = user_data;
|
struct network *network = user_data;
|
||||||
struct station *station = network->station;
|
struct station *station = network->station;
|
||||||
struct netdev *netdev = station_get_netdev(station);
|
|
||||||
struct device *device = netdev_get_device(netdev);
|
|
||||||
struct scan_bss *bss;
|
struct scan_bss *bss;
|
||||||
|
|
||||||
l_debug("");
|
l_debug("");
|
||||||
@ -1026,7 +1015,7 @@ static struct l_dbus_message *network_connect(struct l_dbus *dbus,
|
|||||||
case SECURITY_PSK:
|
case SECURITY_PSK:
|
||||||
return network_connect_psk(network, bss, message);
|
return network_connect_psk(network, bss, message);
|
||||||
case SECURITY_NONE:
|
case SECURITY_NONE:
|
||||||
device_connect_network(device, network, bss, message);
|
station_connect_network(station, network, bss, message);
|
||||||
return NULL;
|
return NULL;
|
||||||
case SECURITY_8021X:
|
case SECURITY_8021X:
|
||||||
if (!network_settings_load(network))
|
if (!network_settings_load(network))
|
||||||
@ -1042,8 +1031,6 @@ void network_connect_new_hidden_network(struct network *network,
|
|||||||
struct l_dbus_message *message)
|
struct l_dbus_message *message)
|
||||||
{
|
{
|
||||||
struct station *station = network->station;
|
struct station *station = network->station;
|
||||||
struct netdev *netdev = station_get_netdev(station);
|
|
||||||
struct device *device = netdev_get_device(netdev);
|
|
||||||
struct scan_bss *bss;
|
struct scan_bss *bss;
|
||||||
struct l_dbus_message *error;
|
struct l_dbus_message *error;
|
||||||
|
|
||||||
@ -1071,7 +1058,7 @@ void network_connect_new_hidden_network(struct network *network,
|
|||||||
error = network_connect_psk(network, bss, message);
|
error = network_connect_psk(network, bss, message);
|
||||||
break;
|
break;
|
||||||
case SECURITY_NONE:
|
case SECURITY_NONE:
|
||||||
device_connect_network(device, network, bss, message);
|
station_connect_network(station, network, bss, message);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
error = dbus_error_not_supported(message);
|
error = dbus_error_not_supported(message);
|
||||||
|
364
src/station.c
364
src/station.c
@ -396,9 +396,9 @@ static void station_handshake_event(struct handshake_state *hs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct handshake_state *station_handshake_setup(struct station *station,
|
static struct handshake_state *station_handshake_setup(struct station *station,
|
||||||
struct network *network,
|
struct network *network,
|
||||||
struct scan_bss *bss)
|
struct scan_bss *bss)
|
||||||
{
|
{
|
||||||
enum security security = network_get_security(network);
|
enum security security = network_get_security(network);
|
||||||
struct wiphy *wiphy = station->wiphy;
|
struct wiphy *wiphy = station->wiphy;
|
||||||
@ -597,7 +597,8 @@ const char *station_state_to_string(enum station_state state)
|
|||||||
return "invalid";
|
return "invalid";
|
||||||
}
|
}
|
||||||
|
|
||||||
void station_enter_state(struct station *station, enum station_state state)
|
static void station_enter_state(struct station *station,
|
||||||
|
enum station_state state)
|
||||||
{
|
{
|
||||||
uint32_t index = netdev_get_ifindex(station->netdev);
|
uint32_t index = netdev_get_ifindex(station->netdev);
|
||||||
struct l_dbus *dbus = dbus_get_bus();
|
struct l_dbus *dbus = dbus_get_bus();
|
||||||
@ -706,7 +707,7 @@ static void station_reset_connection_state(struct station *station)
|
|||||||
IWD_NETWORK_INTERFACE, "Connected");
|
IWD_NETWORK_INTERFACE, "Connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
void station_disassociated(struct station *station)
|
static void station_disassociated(struct station *station)
|
||||||
{
|
{
|
||||||
l_debug("%u", netdev_get_ifindex(station->netdev));
|
l_debug("%u", netdev_get_ifindex(station->netdev));
|
||||||
|
|
||||||
@ -718,7 +719,7 @@ void station_disassociated(struct station *station)
|
|||||||
station_enter_state(station, STATION_STATE_AUTOCONNECT);
|
station_enter_state(station, STATION_STATE_AUTOCONNECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void station_disconnect_event(struct station *station)
|
static void station_disconnect_event(struct station *station)
|
||||||
{
|
{
|
||||||
l_debug("%u", netdev_get_ifindex(station->netdev));
|
l_debug("%u", netdev_get_ifindex(station->netdev));
|
||||||
|
|
||||||
@ -736,7 +737,7 @@ void station_disconnect_event(struct station *station)
|
|||||||
|
|
||||||
static void station_roam_timeout_rearm(struct station *station, int seconds);
|
static void station_roam_timeout_rearm(struct station *station, int seconds);
|
||||||
|
|
||||||
void station_roamed(struct station *station)
|
static void station_roamed(struct station *station)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* New signal high/low notification should occur on the next
|
* New signal high/low notification should occur on the next
|
||||||
@ -747,7 +748,7 @@ void station_roamed(struct station *station)
|
|||||||
station->roam_no_orig_ap = false;
|
station->roam_no_orig_ap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void station_roam_failed(struct station *station)
|
static void station_roam_failed(struct station *station)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If we're still connected to the old BSS, only clear preparing_roam
|
* If we're still connected to the old BSS, only clear preparing_roam
|
||||||
@ -769,6 +770,221 @@ void station_roam_failed(struct station *station)
|
|||||||
station_roam_timeout_rearm(station, 60);
|
station_roam_timeout_rearm(station, 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void station_reassociate_cb(struct netdev *netdev,
|
||||||
|
enum netdev_result result,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
|
||||||
|
l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result);
|
||||||
|
|
||||||
|
if (station->state != STATION_STATE_ROAMING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result == NETDEV_RESULT_OK) {
|
||||||
|
station_roamed(station);
|
||||||
|
station_enter_state(station, STATION_STATE_CONNECTED);
|
||||||
|
} else
|
||||||
|
station_roam_failed(station);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_fast_transition_cb(struct netdev *netdev,
|
||||||
|
enum netdev_result result,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
|
||||||
|
l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result);
|
||||||
|
|
||||||
|
if (station->state != STATION_STATE_ROAMING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result == NETDEV_RESULT_OK) {
|
||||||
|
station_roamed(station);
|
||||||
|
station_enter_state(station, STATION_STATE_CONNECTED);
|
||||||
|
} else
|
||||||
|
station_roam_failed(station);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
static void station_transition_reassociate(struct station *station,
|
||||||
|
struct scan_bss *bss,
|
||||||
|
struct handshake_state *new_hs)
|
||||||
|
{
|
||||||
|
if (netdev_reassociate(station->netdev, bss, station->connected_bss,
|
||||||
|
new_hs, station_netdev_event,
|
||||||
|
station_reassociate_cb, station) < 0) {
|
||||||
|
handshake_state_free(new_hs);
|
||||||
|
station_roam_failed(station);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
station->connected_bss = bss;
|
||||||
|
station->preparing_roam = false;
|
||||||
|
station_enter_state(station, STATION_STATE_ROAMING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool bss_match_bssid(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct scan_bss *bss = a;
|
||||||
|
const uint8_t *bssid = b;
|
||||||
|
|
||||||
|
return !memcmp(bss->addr, bssid, sizeof(bss->addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_preauthenticate_cb(struct netdev *netdev,
|
||||||
|
enum netdev_result result,
|
||||||
|
const uint8_t *pmk, void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
struct network *connected = station->connected_network;
|
||||||
|
struct scan_bss *bss;
|
||||||
|
struct handshake_state *new_hs;
|
||||||
|
|
||||||
|
l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result);
|
||||||
|
|
||||||
|
if (!station->preparing_roam || result == NETDEV_RESULT_ABORTED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bss = l_queue_find(station->bss_list, bss_match_bssid,
|
||||||
|
station->preauth_bssid);
|
||||||
|
if (!bss) {
|
||||||
|
l_error("Roam target BSS not found");
|
||||||
|
station_roam_failed(station);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_hs = station_handshake_setup(station, connected, bss);
|
||||||
|
if (!new_hs) {
|
||||||
|
l_error("station_handshake_setup failed");
|
||||||
|
|
||||||
|
station_roam_failed(station);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NETDEV_RESULT_OK) {
|
||||||
|
uint8_t pmkid[16];
|
||||||
|
uint8_t rsne_buf[300];
|
||||||
|
struct ie_rsn_info rsn_info;
|
||||||
|
|
||||||
|
handshake_state_set_pmk(new_hs, pmk, 32);
|
||||||
|
handshake_state_set_authenticator_address(new_hs,
|
||||||
|
station->preauth_bssid);
|
||||||
|
handshake_state_set_supplicant_address(new_hs,
|
||||||
|
netdev_get_address(station->netdev));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rebuild the RSNE to include the negotiated PMKID. Note
|
||||||
|
* supplicant_ie can't be a WPA IE here, including because
|
||||||
|
* the WPA IE doesn't have a capabilities field and
|
||||||
|
* target_rsne->preauthentication would have been false in
|
||||||
|
* station_transition_start.
|
||||||
|
*/
|
||||||
|
ie_parse_rsne_from_data(new_hs->supplicant_ie,
|
||||||
|
new_hs->supplicant_ie[1] + 2,
|
||||||
|
&rsn_info);
|
||||||
|
|
||||||
|
handshake_state_get_pmkid(new_hs, pmkid);
|
||||||
|
|
||||||
|
rsn_info.num_pmkids = 1;
|
||||||
|
rsn_info.pmkids = pmkid;
|
||||||
|
|
||||||
|
ie_build_rsne(&rsn_info, rsne_buf);
|
||||||
|
handshake_state_set_supplicant_rsn(new_hs, rsne_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
station_transition_reassociate(station, bss, new_hs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_transition_start(struct station *station,
|
||||||
|
struct scan_bss *bss)
|
||||||
|
{
|
||||||
|
struct handshake_state *hs = netdev_get_handshake(station->netdev);
|
||||||
|
struct network *connected = station->connected_network;
|
||||||
|
enum security security = network_get_security(connected);
|
||||||
|
uint16_t mdid;
|
||||||
|
struct handshake_state *new_hs;
|
||||||
|
struct ie_rsn_info cur_rsne, target_rsne;
|
||||||
|
|
||||||
|
l_debug("%u, target %s", netdev_get_ifindex(station->netdev),
|
||||||
|
util_address_to_string(bss->addr));
|
||||||
|
|
||||||
|
/* Reset AP roam flag, at this point the roaming behaves the same */
|
||||||
|
station->ap_directed_roaming = false;
|
||||||
|
|
||||||
|
if (hs->mde)
|
||||||
|
ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
|
||||||
|
&mdid, NULL, NULL);
|
||||||
|
|
||||||
|
/* Can we use Fast Transition? */
|
||||||
|
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) {
|
||||||
|
/*
|
||||||
|
* There's no need to regenerate the RSNE because neither
|
||||||
|
* the AKM nor cipher suite can change:
|
||||||
|
*
|
||||||
|
* 12.5.2: "If the FTO selects a pairwise cipher suite in
|
||||||
|
* the RSNE that is different from the ones used in the
|
||||||
|
* Initial mobility domain association, then the AP shall
|
||||||
|
* reject the Authentication Request with status code 19
|
||||||
|
* (i.e., Invalid Pairwise Cipher)."
|
||||||
|
*/
|
||||||
|
if (netdev_fast_transition(station->netdev, bss,
|
||||||
|
station_fast_transition_cb) < 0) {
|
||||||
|
station_roam_failed(station);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
station->connected_bss = bss;
|
||||||
|
station->preparing_roam = false;
|
||||||
|
station_enter_state(station, STATION_STATE_ROAMING);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Non-FT transition */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FT not available, we can try preauthentication if available.
|
||||||
|
* 802.11-2012 section 11.5.9.2:
|
||||||
|
* "A STA shall not use preauthentication within the same mobility
|
||||||
|
* domain if AKM suite type 00-0F-AC:3 or 00-0F-AC:4 is used in
|
||||||
|
* the current association."
|
||||||
|
*/
|
||||||
|
if (security == SECURITY_8021X &&
|
||||||
|
!station->roam_no_orig_ap &&
|
||||||
|
scan_bss_get_rsn_info(station->connected_bss,
|
||||||
|
&cur_rsne) >= 0 &&
|
||||||
|
scan_bss_get_rsn_info(bss, &target_rsne) >= 0 &&
|
||||||
|
cur_rsne.preauthentication &&
|
||||||
|
target_rsne.preauthentication) {
|
||||||
|
/*
|
||||||
|
* Both the current and the target AP support
|
||||||
|
* pre-authentication and we're using 8021x authentication so
|
||||||
|
* attempt to pre-authenticate and reassociate afterwards.
|
||||||
|
* If the pre-authentication fails or times out we simply
|
||||||
|
* won't supply any PMKID when reassociating.
|
||||||
|
* Remain in the preparing_roam state.
|
||||||
|
*/
|
||||||
|
memcpy(station->preauth_bssid, bss->addr, ETH_ALEN);
|
||||||
|
|
||||||
|
if (netdev_preauthenticate(station->netdev, bss,
|
||||||
|
station_preauthenticate_cb,
|
||||||
|
station) >= 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_hs = station_handshake_setup(station, connected, bss);
|
||||||
|
if (!new_hs) {
|
||||||
|
l_error("station_handshake_setup failed in reassociation");
|
||||||
|
station_roam_failed(station);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
station_transition_reassociate(station, bss, new_hs);
|
||||||
|
}
|
||||||
|
|
||||||
static void station_roam_scan_triggered(int err, void *user_data)
|
static void station_roam_scan_triggered(int err, void *user_data)
|
||||||
{
|
{
|
||||||
struct station *station = user_data;
|
struct station *station = user_data;
|
||||||
@ -789,7 +1005,6 @@ static bool station_roam_scan_notify(uint32_t wiphy_id, uint32_t ifindex,
|
|||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
struct station *station = userdata;
|
struct station *station = userdata;
|
||||||
struct device *device = netdev_get_device(station->netdev);
|
|
||||||
struct network *network = station->connected_network;
|
struct network *network = station->connected_network;
|
||||||
struct handshake_state *hs = netdev_get_handshake(station->netdev);
|
struct handshake_state *hs = netdev_get_handshake(station->netdev);
|
||||||
struct scan_bss *bss;
|
struct scan_bss *bss;
|
||||||
@ -895,7 +1110,7 @@ next:
|
|||||||
l_queue_push_tail(station->bss_list, best_bss);
|
l_queue_push_tail(station->bss_list, best_bss);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_transition_start(device, best_bss);
|
station_transition_start(station, best_bss);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -1155,7 +1370,7 @@ static void station_roam_timeout_rearm(struct station *station, int seconds)
|
|||||||
station, NULL);
|
station, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void station_lost_beacon(struct station *station)
|
static void station_lost_beacon(struct station *station)
|
||||||
{
|
{
|
||||||
l_debug("%d", netdev_get_ifindex(station->netdev));
|
l_debug("%d", netdev_get_ifindex(station->netdev));
|
||||||
|
|
||||||
@ -1261,7 +1476,7 @@ format_error:
|
|||||||
l_debug("bad AP roam frame formatting");
|
l_debug("bad AP roam frame formatting");
|
||||||
}
|
}
|
||||||
|
|
||||||
void station_low_rssi(struct station *station)
|
static void station_low_rssi(struct station *station)
|
||||||
{
|
{
|
||||||
if (station->signal_low)
|
if (station->signal_low)
|
||||||
return;
|
return;
|
||||||
@ -1276,7 +1491,7 @@ void station_low_rssi(struct station *station)
|
|||||||
station_roam_timeout_rearm(station, 5);
|
station_roam_timeout_rearm(station, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void station_ok_rssi(struct station *station)
|
static void station_ok_rssi(struct station *station)
|
||||||
{
|
{
|
||||||
l_timeout_remove(station->roam_trigger_timeout);
|
l_timeout_remove(station->roam_trigger_timeout);
|
||||||
station->roam_trigger_timeout = NULL;
|
station->roam_trigger_timeout = NULL;
|
||||||
@ -1284,6 +1499,129 @@ void station_ok_rssi(struct station *station)
|
|||||||
station->signal_low = false;
|
station->signal_low = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void station_netdev_event(struct netdev *netdev, enum netdev_event event,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case NETDEV_EVENT_AUTHENTICATING:
|
||||||
|
l_debug("Authenticating");
|
||||||
|
break;
|
||||||
|
case NETDEV_EVENT_ASSOCIATING:
|
||||||
|
l_debug("Associating");
|
||||||
|
break;
|
||||||
|
case NETDEV_EVENT_LOST_BEACON:
|
||||||
|
station_lost_beacon(station);
|
||||||
|
break;
|
||||||
|
case NETDEV_EVENT_DISCONNECT_BY_AP:
|
||||||
|
case NETDEV_EVENT_DISCONNECT_BY_SME:
|
||||||
|
station_disconnect_event(station);
|
||||||
|
break;
|
||||||
|
case NETDEV_EVENT_RSSI_THRESHOLD_LOW:
|
||||||
|
station_low_rssi(station);
|
||||||
|
break;
|
||||||
|
case NETDEV_EVENT_RSSI_THRESHOLD_HIGH:
|
||||||
|
station_ok_rssi(station);
|
||||||
|
break;
|
||||||
|
case NETDEV_EVENT_RSSI_LEVEL_NOTIFY:
|
||||||
|
station_rssi_level_changed(station);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_connect_cb(struct netdev *netdev, enum netdev_result result,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
|
||||||
|
l_debug("%u, result: %d", netdev_get_ifindex(station->netdev), result);
|
||||||
|
|
||||||
|
if (station->connect_pending) {
|
||||||
|
struct l_dbus_message *reply;
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case NETDEV_RESULT_ABORTED:
|
||||||
|
reply = dbus_error_aborted(station->connect_pending);
|
||||||
|
break;
|
||||||
|
case NETDEV_RESULT_OK:
|
||||||
|
reply = l_dbus_message_new_method_return(
|
||||||
|
station->connect_pending);
|
||||||
|
l_dbus_message_set_arguments(reply, "");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reply = dbus_error_failed(station->connect_pending);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_pending_reply(&station->connect_pending, reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != NETDEV_RESULT_OK) {
|
||||||
|
if (result != NETDEV_RESULT_ABORTED) {
|
||||||
|
network_connect_failed(station->connected_network);
|
||||||
|
station_disassociated(station);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
network_connected(station->connected_network);
|
||||||
|
station_enter_state(station, STATION_STATE_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __station_connect_network(struct station *station, struct network *network,
|
||||||
|
struct scan_bss *bss)
|
||||||
|
{
|
||||||
|
struct l_dbus *dbus = dbus_get_bus();
|
||||||
|
struct netdev *netdev = station->netdev;
|
||||||
|
struct handshake_state *hs;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (station_is_busy(station))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
hs = station_handshake_setup(station, network, bss);
|
||||||
|
if (!hs)
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
r = netdev_connect(station->netdev, bss, hs, station_netdev_event,
|
||||||
|
station_connect_cb, station);
|
||||||
|
if (r < 0) {
|
||||||
|
handshake_state_free(hs);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
station->connected_bss = bss;
|
||||||
|
station->connected_network = network;
|
||||||
|
|
||||||
|
station_enter_state(station, STATION_STATE_CONNECTING);
|
||||||
|
|
||||||
|
l_dbus_property_changed(dbus, netdev_get_path(netdev),
|
||||||
|
IWD_DEVICE_INTERFACE, "ConnectedNetwork");
|
||||||
|
l_dbus_property_changed(dbus, network_get_path(network),
|
||||||
|
IWD_NETWORK_INTERFACE, "Connected");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void station_connect_network(struct station *station, struct network *network,
|
||||||
|
struct scan_bss *bss,
|
||||||
|
struct l_dbus_message *message)
|
||||||
|
{
|
||||||
|
int err = __station_connect_network(station, network, bss);
|
||||||
|
|
||||||
|
if (err < 0) {
|
||||||
|
struct l_dbus *dbus = dbus_get_bus();
|
||||||
|
|
||||||
|
l_dbus_send(dbus, dbus_error_from_errno(err, message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
station->connect_pending = l_dbus_message_ref(message);
|
||||||
|
station->autoconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void station_hidden_network_scan_triggered(int err, void *user_data)
|
static void station_hidden_network_scan_triggered(int err, void *user_data)
|
||||||
{
|
{
|
||||||
struct station *station = user_data;
|
struct station *station = user_data;
|
||||||
|
@ -60,6 +60,7 @@ struct station {
|
|||||||
struct timespec roam_min_time;
|
struct timespec roam_min_time;
|
||||||
struct l_timeout *roam_trigger_timeout;
|
struct l_timeout *roam_trigger_timeout;
|
||||||
uint32_t roam_scan_id;
|
uint32_t roam_scan_id;
|
||||||
|
uint8_t preauth_bssid[6];
|
||||||
|
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
struct netdev *netdev;
|
struct netdev *netdev;
|
||||||
@ -84,12 +85,7 @@ struct network *station_network_find(struct station *station, const char *ssid,
|
|||||||
void station_set_scan_results(struct station *station, struct l_queue *bss_list,
|
void station_set_scan_results(struct station *station, struct l_queue *bss_list,
|
||||||
bool add_to_autoconnect);
|
bool add_to_autoconnect);
|
||||||
|
|
||||||
struct handshake_state *station_handshake_setup(struct station *station,
|
|
||||||
struct network *network,
|
|
||||||
struct scan_bss *bss);
|
|
||||||
|
|
||||||
const char *station_state_to_string(enum station_state state);
|
const char *station_state_to_string(enum station_state state);
|
||||||
void station_enter_state(struct station *station, enum station_state state);
|
|
||||||
enum station_state station_get_state(struct station *station);
|
enum station_state station_get_state(struct station *station);
|
||||||
uint32_t station_add_state_watch(struct station *station,
|
uint32_t station_add_state_watch(struct station *station,
|
||||||
station_state_watch_func_t func,
|
station_state_watch_func_t func,
|
||||||
@ -99,19 +95,10 @@ bool station_remove_state_watch(struct station *station, uint32_t id);
|
|||||||
|
|
||||||
bool station_set_autoconnect(struct station *station, bool autoconnect);
|
bool station_set_autoconnect(struct station *station, bool autoconnect);
|
||||||
|
|
||||||
void station_roam_failed(struct station *station);
|
|
||||||
void station_roamed(struct station *station);
|
|
||||||
void station_lost_beacon(struct station *station);
|
|
||||||
void station_ap_directed_roam(struct station *station,
|
void station_ap_directed_roam(struct station *station,
|
||||||
const struct mmpdu_header *hdr,
|
const struct mmpdu_header *hdr,
|
||||||
const void *body, size_t body_len);
|
const void *body, size_t body_len);
|
||||||
|
|
||||||
void station_low_rssi(struct station *station);
|
|
||||||
void station_ok_rssi(struct station *station);
|
|
||||||
|
|
||||||
void station_disassociated(struct station *station);
|
|
||||||
void station_disconnect_event(struct station *station);
|
|
||||||
|
|
||||||
struct l_dbus_message *station_dbus_connect_hidden_network(
|
struct l_dbus_message *station_dbus_connect_hidden_network(
|
||||||
struct l_dbus *dbus,
|
struct l_dbus *dbus,
|
||||||
struct l_dbus_message *message,
|
struct l_dbus_message *message,
|
||||||
@ -126,6 +113,11 @@ struct l_dbus_message *station_dbus_scan(struct l_dbus *dbus,
|
|||||||
struct l_dbus_message *message,
|
struct l_dbus_message *message,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
int __station_connect_network(struct station *station, struct network *network,
|
||||||
|
struct scan_bss *bss);
|
||||||
|
void station_connect_network(struct station *station, struct network *network,
|
||||||
|
struct scan_bss *bss,
|
||||||
|
struct l_dbus_message *message);
|
||||||
int station_disconnect(struct station *station);
|
int station_disconnect(struct station *station);
|
||||||
|
|
||||||
void station_rssi_level_changed(struct station *station);
|
void station_rssi_level_changed(struct station *station);
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include "src/dbus.h"
|
#include "src/dbus.h"
|
||||||
#include "src/netdev.h"
|
#include "src/netdev.h"
|
||||||
#include "src/watchlist.h"
|
#include "src/watchlist.h"
|
||||||
#include "src/device.h"
|
|
||||||
#include "src/wiphy.h"
|
#include "src/wiphy.h"
|
||||||
#include "src/station.h"
|
#include "src/station.h"
|
||||||
#include "src/scan.h"
|
#include "src/scan.h"
|
||||||
@ -114,7 +113,6 @@ static struct l_dbus_message *wsc_error_time_expired(struct l_dbus_message *msg)
|
|||||||
}
|
}
|
||||||
static void wsc_try_credentials(struct wsc *wsc)
|
static void wsc_try_credentials(struct wsc *wsc)
|
||||||
{
|
{
|
||||||
struct device *device = netdev_get_device(wsc->netdev);
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct network *network;
|
struct network *network;
|
||||||
struct scan_bss *bss;
|
struct scan_bss *bss;
|
||||||
@ -138,7 +136,8 @@ static void wsc_try_credentials(struct wsc *wsc)
|
|||||||
!network_set_psk(network, wsc->creds[i].psk))
|
!network_set_psk(network, wsc->creds[i].psk))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
device_connect_network(device, network, bss, wsc->pending);
|
station_connect_network(wsc->station, network, bss,
|
||||||
|
wsc->pending);
|
||||||
l_dbus_message_unref(wsc->pending);
|
l_dbus_message_unref(wsc->pending);
|
||||||
wsc->pending = NULL;
|
wsc->pending = NULL;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user