mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-17 09:29:22 +01:00
network: Move network related code into network.c
away from wiphy.c
This commit is contained in:
parent
5e4c675175
commit
d4feeebdc1
230
src/network.c
230
src/network.c
@ -28,6 +28,9 @@
|
||||
|
||||
#include <ell/ell.h>
|
||||
|
||||
#include "src/ie.h"
|
||||
#include "src/crypto.h"
|
||||
|
||||
#include "src/iwd.h"
|
||||
#include "src/common.h"
|
||||
#include "src/storage.h"
|
||||
@ -35,6 +38,7 @@
|
||||
#include "src/dbus.h"
|
||||
#include "src/agent.h"
|
||||
#include "src/device.h"
|
||||
#include "src/wiphy.h"
|
||||
#include "src/network.h"
|
||||
|
||||
struct network_info {
|
||||
@ -271,6 +275,226 @@ void network_settings_close(struct network *network)
|
||||
network->settings = NULL;
|
||||
}
|
||||
|
||||
static struct scan_bss *network_select_bss(struct wiphy *wiphy,
|
||||
struct network *network)
|
||||
{
|
||||
struct l_queue *bss_list = network->bss_list;
|
||||
const struct l_queue_entry *bss_entry;
|
||||
|
||||
/* TODO: sort the list by RSSI, potentially other criteria. */
|
||||
|
||||
switch (network->security) {
|
||||
case SECURITY_NONE:
|
||||
/* Pick the first bss (strongest signal) */
|
||||
return l_queue_peek_head(bss_list);
|
||||
|
||||
case SECURITY_PSK:
|
||||
case SECURITY_8021X:
|
||||
/* Pick the first bss that advertises any cipher we support. */
|
||||
for (bss_entry = l_queue_get_entries(bss_list); bss_entry;
|
||||
bss_entry = bss_entry->next) {
|
||||
struct scan_bss *bss = bss_entry->data;
|
||||
uint16_t pairwise_ciphers, group_ciphers;
|
||||
|
||||
bss_get_supported_ciphers(bss, &pairwise_ciphers,
|
||||
&group_ciphers);
|
||||
|
||||
if (wiphy_select_cipher(wiphy, pairwise_ciphers) &&
|
||||
wiphy_select_cipher(wiphy,
|
||||
group_ciphers))
|
||||
return bss;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void passphrase_callback(enum agent_result result,
|
||||
const char *passphrase,
|
||||
struct l_dbus_message *message,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
struct wiphy *wiphy = device_get_wiphy(network->netdev);
|
||||
struct scan_bss *bss;
|
||||
|
||||
l_debug("result %d", result);
|
||||
|
||||
network->agent_request = 0;
|
||||
|
||||
if (result != AGENT_RESULT_OK) {
|
||||
dbus_pending_reply(&message, dbus_error_aborted(message));
|
||||
goto err;
|
||||
}
|
||||
|
||||
bss = network_select_bss(wiphy, network);
|
||||
|
||||
/* Did all good BSSes go away while we waited */
|
||||
if (!bss) {
|
||||
dbus_pending_reply(&message, dbus_error_failed(message));
|
||||
goto err;
|
||||
}
|
||||
|
||||
l_free(network->psk);
|
||||
network->psk = l_malloc(32);
|
||||
|
||||
if (crypto_psk_from_passphrase(passphrase, (uint8_t *) network->ssid,
|
||||
strlen(network->ssid),
|
||||
network->psk) < 0) {
|
||||
l_error("PMK generation failed. "
|
||||
"Ensure Crypto Engine is properly configured");
|
||||
dbus_pending_reply(&message, dbus_error_failed(message));
|
||||
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to store the PSK in our permanent store. However, before
|
||||
* we do that, make sure the PSK works. We write to the store only
|
||||
* when we are connected
|
||||
*/
|
||||
network->update_psk = true;
|
||||
|
||||
device_connect_network(network->netdev, network, bss, message);
|
||||
return;
|
||||
|
||||
err:
|
||||
network_settings_close(network);
|
||||
|
||||
l_free(network->psk);
|
||||
network->psk = NULL;
|
||||
}
|
||||
|
||||
static struct l_dbus_message *network_connect_psk(struct network *network,
|
||||
struct scan_bss *bss,
|
||||
struct l_dbus_message *message)
|
||||
{
|
||||
struct netdev *netdev = network->netdev;
|
||||
const char *psk;
|
||||
|
||||
l_debug("");
|
||||
|
||||
network_settings_load(network);
|
||||
|
||||
psk = l_settings_get_value(network->settings, "Security",
|
||||
"PreSharedKey");
|
||||
|
||||
if (psk) {
|
||||
size_t len;
|
||||
|
||||
l_debug("psk: %s", psk);
|
||||
|
||||
l_free(network->psk);
|
||||
network->psk = l_util_from_hexstring(psk, &len);
|
||||
|
||||
l_debug("len: %zd", len);
|
||||
|
||||
if (network->psk && len != 32) {
|
||||
l_debug("Can't parse PSK");
|
||||
l_free(network->psk);
|
||||
network->psk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
l_debug("ask_psk: %s", network->ask_psk ? "true" : "false");
|
||||
|
||||
if (network->ask_psk || !network->psk) {
|
||||
network->ask_psk = false;
|
||||
|
||||
network->agent_request =
|
||||
agent_request_passphrase(network->object_path,
|
||||
passphrase_callback,
|
||||
message,
|
||||
network);
|
||||
|
||||
if (!network->agent_request)
|
||||
return dbus_error_no_agent(message);
|
||||
} else
|
||||
device_connect_network(netdev, network, bss, message);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct l_dbus_message *network_connect(struct l_dbus *dbus,
|
||||
struct l_dbus_message *message,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
struct netdev *netdev = network->netdev;
|
||||
struct scan_bss *bss;
|
||||
|
||||
l_debug("");
|
||||
|
||||
if (device_is_busy(netdev))
|
||||
return dbus_error_busy(message);
|
||||
|
||||
/*
|
||||
* Select the best BSS to use at this time. If we have to query the
|
||||
* agent this may not be the final choice because BSS visibility can
|
||||
* change while we wait for the agent.
|
||||
*/
|
||||
bss = network_select_bss(device_get_wiphy(netdev), network);
|
||||
|
||||
/* None of the BSSes is compatible with our stack */
|
||||
if (!bss)
|
||||
return dbus_error_not_supported(message);
|
||||
|
||||
switch (network->security) {
|
||||
case SECURITY_PSK:
|
||||
return network_connect_psk(network, bss, message);
|
||||
case SECURITY_NONE:
|
||||
device_connect_network(netdev, network, bss, message);
|
||||
return NULL;
|
||||
case SECURITY_8021X:
|
||||
network_settings_load(network);
|
||||
device_connect_network(netdev, network, bss, message);
|
||||
return NULL;
|
||||
default:
|
||||
return dbus_error_not_supported(message);
|
||||
}
|
||||
}
|
||||
|
||||
static bool network_property_get_name(struct l_dbus *dbus,
|
||||
struct l_dbus_message *message,
|
||||
struct l_dbus_message_builder *builder,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
|
||||
l_dbus_message_builder_append_basic(builder, 's', network->ssid);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool network_property_is_connected(struct l_dbus *dbus,
|
||||
struct l_dbus_message *message,
|
||||
struct l_dbus_message_builder *builder,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
bool connected;
|
||||
|
||||
connected = device_get_connected_network(network->netdev) == network;
|
||||
l_dbus_message_builder_append_basic(builder, 'b', &connected);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setup_network_interface(struct l_dbus_interface *interface)
|
||||
{
|
||||
l_dbus_interface_method(interface, "Connect", 0,
|
||||
network_connect,
|
||||
"", "");
|
||||
|
||||
l_dbus_interface_property(interface, "Name", 0, "s",
|
||||
network_property_get_name, NULL);
|
||||
|
||||
l_dbus_interface_property(interface, "Connected", 0, "b",
|
||||
network_property_is_connected,
|
||||
NULL);
|
||||
}
|
||||
|
||||
bool __iwd_network_append_properties(const struct network *network,
|
||||
struct l_dbus_message_builder *builder)
|
||||
{
|
||||
@ -373,10 +597,16 @@ void network_remove(struct network *network)
|
||||
|
||||
void network_init()
|
||||
{
|
||||
if (!l_dbus_register_interface(dbus_get_bus(), IWD_NETWORK_INTERFACE,
|
||||
setup_network_interface, NULL, true))
|
||||
l_error("Unable to register %s interface",
|
||||
IWD_NETWORK_INTERFACE);
|
||||
|
||||
networks = l_queue_new();
|
||||
}
|
||||
|
||||
void network_exit()
|
||||
{
|
||||
l_queue_destroy(networks, l_free);
|
||||
l_dbus_unregister_interface(dbus_get_bus(), IWD_NETWORK_INTERFACE);
|
||||
}
|
||||
|
232
src/wiphy.c
232
src/wiphy.c
@ -272,43 +272,6 @@ enum ie_rsn_cipher_suite wiphy_select_cipher(struct wiphy *wiphy, uint16_t mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct scan_bss *network_select_bss(struct wiphy *wiphy,
|
||||
struct network *network)
|
||||
{
|
||||
struct l_queue *bss_list = network->bss_list;
|
||||
const struct l_queue_entry *bss_entry;
|
||||
|
||||
/* TODO: sort the list by RSSI, potentially other criteria. */
|
||||
|
||||
switch (network->security) {
|
||||
case SECURITY_NONE:
|
||||
/* Pick the first bss (strongest signal) */
|
||||
return l_queue_peek_head(bss_list);
|
||||
|
||||
case SECURITY_PSK:
|
||||
case SECURITY_8021X:
|
||||
/* Pick the first bss that advertises any cipher we support. */
|
||||
for (bss_entry = l_queue_get_entries(bss_list); bss_entry;
|
||||
bss_entry = bss_entry->next) {
|
||||
struct scan_bss *bss = bss_entry->data;
|
||||
uint16_t pairwise_ciphers, group_ciphers;
|
||||
|
||||
bss_get_supported_ciphers(bss, &pairwise_ciphers,
|
||||
&group_ciphers);
|
||||
|
||||
if (wiphy_select_cipher(wiphy, pairwise_ciphers) &&
|
||||
wiphy_select_cipher(wiphy,
|
||||
group_ciphers))
|
||||
return bss;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int mlme_authenticate_cmd(struct network *network, struct scan_bss *bss)
|
||||
{
|
||||
struct netdev *netdev = network_get_netdev(network);
|
||||
@ -341,189 +304,6 @@ void device_connect_network(struct netdev *device, struct network *network,
|
||||
mlme_authenticate_cmd(network, bss);
|
||||
}
|
||||
|
||||
static void passphrase_callback(enum agent_result result,
|
||||
const char *passphrase,
|
||||
struct l_dbus_message *message,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
struct wiphy *wiphy = device_get_wiphy(network->netdev);
|
||||
struct scan_bss *bss;
|
||||
|
||||
l_debug("result %d", result);
|
||||
|
||||
network->agent_request = 0;
|
||||
|
||||
if (result != AGENT_RESULT_OK) {
|
||||
dbus_pending_reply(&message, dbus_error_aborted(message));
|
||||
goto err;
|
||||
}
|
||||
|
||||
bss = network_select_bss(wiphy, network);
|
||||
|
||||
/* Did all good BSSes go away while we waited */
|
||||
if (!bss) {
|
||||
dbus_pending_reply(&message, dbus_error_failed(message));
|
||||
goto err;
|
||||
}
|
||||
|
||||
l_free(network->psk);
|
||||
network->psk = l_malloc(32);
|
||||
|
||||
if (crypto_psk_from_passphrase(passphrase, (uint8_t *) network->ssid,
|
||||
strlen(network->ssid),
|
||||
network->psk) < 0) {
|
||||
l_error("PMK generation failed. "
|
||||
"Ensure Crypto Engine is properly configured");
|
||||
dbus_pending_reply(&message, dbus_error_failed(message));
|
||||
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to store the PSK in our permanent store. However, before
|
||||
* we do that, make sure the PSK works. We write to the store only
|
||||
* when we are connected
|
||||
*/
|
||||
network->update_psk = true;
|
||||
|
||||
device_connect_network(network->netdev, network, bss, message);
|
||||
return;
|
||||
|
||||
err:
|
||||
network_settings_close(network);
|
||||
|
||||
l_free(network->psk);
|
||||
network->psk = NULL;
|
||||
}
|
||||
|
||||
static struct l_dbus_message *network_connect_psk(struct network *network,
|
||||
struct scan_bss *bss,
|
||||
struct l_dbus_message *message)
|
||||
{
|
||||
struct netdev *netdev = network->netdev;
|
||||
const char *psk;
|
||||
|
||||
l_debug("");
|
||||
|
||||
network_settings_load(network);
|
||||
|
||||
psk = l_settings_get_value(network->settings, "Security",
|
||||
"PreSharedKey");
|
||||
|
||||
if (psk) {
|
||||
size_t len;
|
||||
|
||||
l_debug("psk: %s", psk);
|
||||
|
||||
l_free(network->psk);
|
||||
network->psk = l_util_from_hexstring(psk, &len);
|
||||
|
||||
l_debug("len: %zd", len);
|
||||
|
||||
if (network->psk && len != 32) {
|
||||
l_debug("Can't parse PSK");
|
||||
l_free(network->psk);
|
||||
network->psk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
l_debug("ask_psk: %s", network->ask_psk ? "true" : "false");
|
||||
|
||||
if (network->ask_psk || !network->psk) {
|
||||
network->ask_psk = false;
|
||||
|
||||
network->agent_request =
|
||||
agent_request_passphrase(network->object_path,
|
||||
passphrase_callback,
|
||||
message,
|
||||
network);
|
||||
|
||||
if (!network->agent_request)
|
||||
return dbus_error_no_agent(message);
|
||||
} else
|
||||
device_connect_network(netdev, network, bss, message);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct l_dbus_message *network_connect(struct l_dbus *dbus,
|
||||
struct l_dbus_message *message,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
struct netdev *netdev = network->netdev;
|
||||
struct scan_bss *bss;
|
||||
|
||||
l_debug("");
|
||||
|
||||
if (device_is_busy(netdev))
|
||||
return dbus_error_busy(message);
|
||||
|
||||
/*
|
||||
* Select the best BSS to use at this time. If we have to query the
|
||||
* agent this may not be the final choice because BSS visibility can
|
||||
* change while we wait for the agent.
|
||||
*/
|
||||
bss = network_select_bss(device_get_wiphy(netdev), network);
|
||||
|
||||
/* None of the BSSes is compatible with our stack */
|
||||
if (!bss)
|
||||
return dbus_error_not_supported(message);
|
||||
|
||||
switch (network->security) {
|
||||
case SECURITY_PSK:
|
||||
return network_connect_psk(network, bss, message);
|
||||
case SECURITY_NONE:
|
||||
device_connect_network(netdev, network, bss, message);
|
||||
return NULL;
|
||||
case SECURITY_8021X:
|
||||
network_settings_load(network);
|
||||
device_connect_network(netdev, network, bss, message);
|
||||
return NULL;
|
||||
default:
|
||||
return dbus_error_not_supported(message);
|
||||
}
|
||||
}
|
||||
|
||||
static bool network_property_get_name(struct l_dbus *dbus,
|
||||
struct l_dbus_message *message,
|
||||
struct l_dbus_message_builder *builder,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
|
||||
l_dbus_message_builder_append_basic(builder, 's', network->ssid);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool network_property_is_connected(struct l_dbus *dbus,
|
||||
struct l_dbus_message *message,
|
||||
struct l_dbus_message_builder *builder,
|
||||
void *user_data)
|
||||
{
|
||||
struct network *network = user_data;
|
||||
bool connected;
|
||||
|
||||
connected = network->netdev->connected_network == network;
|
||||
l_dbus_message_builder_append_basic(builder, 'b', &connected);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setup_network_interface(struct l_dbus_interface *interface)
|
||||
{
|
||||
l_dbus_interface_method(interface, "Connect", 0,
|
||||
network_connect,
|
||||
"", "");
|
||||
|
||||
l_dbus_interface_property(interface, "Name", 0, "s",
|
||||
network_property_get_name, NULL);
|
||||
|
||||
l_dbus_interface_property(interface, "Connected", 0, "b",
|
||||
network_property_is_connected,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void bss_free(void *data)
|
||||
{
|
||||
struct scan_bss *bss = data;
|
||||
@ -2276,20 +2056,11 @@ bool wiphy_init(struct l_genl_family *in)
|
||||
l_queue_destroy(wiphy_list, NULL);
|
||||
}
|
||||
|
||||
if (!l_dbus_register_interface(dbus_get_bus(),
|
||||
IWD_NETWORK_INTERFACE,
|
||||
setup_network_interface,
|
||||
NULL, true))
|
||||
return false;
|
||||
|
||||
if (!l_dbus_register_interface(dbus_get_bus(),
|
||||
IWD_DEVICE_INTERFACE,
|
||||
setup_device_interface,
|
||||
NULL, true)) {
|
||||
l_dbus_unregister_interface(dbus_get_bus(),
|
||||
IWD_NETWORK_INTERFACE);
|
||||
NULL, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
nl80211 = in;
|
||||
|
||||
@ -2342,7 +2113,6 @@ bool wiphy_exit(void)
|
||||
nl80211 = NULL;
|
||||
|
||||
l_dbus_unregister_interface(dbus_get_bus(), IWD_DEVICE_INTERFACE);
|
||||
l_dbus_unregister_interface(dbus_get_bus(), IWD_NETWORK_INTERFACE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user