mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-05 06:28:05 +02:00
wifi/iwd: merge branch 'pr/42'
https://github.com/NetworkManager/NetworkManager/pull/42
This commit is contained in:
commit
60d4b370ba
3 changed files with 295 additions and 31 deletions
|
|
@ -399,6 +399,52 @@ deactivate (NMDevice *device)
|
|||
cleanup_association_attempt (NM_DEVICE_IWD (device), TRUE);
|
||||
}
|
||||
|
||||
static NMIwdNetworkSecurity
|
||||
get_connection_iwd_security (NMConnection *connection)
|
||||
{
|
||||
NMSettingWirelessSecurity *s_wireless_sec;
|
||||
const char *key_mgmt = NULL;
|
||||
|
||||
s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
|
||||
if (!s_wireless_sec)
|
||||
return NM_IWD_NETWORK_SECURITY_NONE;
|
||||
|
||||
key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
|
||||
nm_assert (key_mgmt);
|
||||
|
||||
if (!strcmp (key_mgmt, "none") || !strcmp (key_mgmt, "ieee8021x"))
|
||||
return NM_IWD_NETWORK_SECURITY_WEP;
|
||||
|
||||
if (!strcmp (key_mgmt, "wpa-psk"))
|
||||
return NM_IWD_NETWORK_SECURITY_PSK;
|
||||
|
||||
nm_assert (!strcmp (key_mgmt, "wpa-eap"));
|
||||
return NM_IWD_NETWORK_SECURITY_8021X;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_connection_known_network (NMConnection *connection)
|
||||
{
|
||||
NMSettingWireless *s_wireless;
|
||||
GBytes *ssid;
|
||||
gs_free gchar *str_ssid = NULL;
|
||||
|
||||
s_wireless = nm_connection_get_setting_wireless (connection);
|
||||
if (!s_wireless)
|
||||
return FALSE;
|
||||
|
||||
ssid = nm_setting_wireless_get_ssid (s_wireless);
|
||||
if (!ssid)
|
||||
return FALSE;
|
||||
|
||||
str_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
|
||||
g_bytes_get_size (ssid));
|
||||
|
||||
return nm_iwd_manager_is_known_network (nm_iwd_manager_get (),
|
||||
str_ssid,
|
||||
get_connection_iwd_security (connection));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
{
|
||||
|
|
@ -447,6 +493,14 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
|||
if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* 8021x networks can only be used if they've been provisioned on the IWD side and
|
||||
* thus are Known Networks.
|
||||
*/
|
||||
if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) {
|
||||
if (!is_connection_known_network (connection))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +509,6 @@ get_ap_by_path (NMDeviceIwd *self, const char *path)
|
|||
{
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
return g_hash_table_lookup (NM_DEVICE_IWD_GET_PRIVATE (self)->aps, path);
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -472,6 +525,23 @@ check_connection_available (NMDevice *device,
|
|||
s_wifi = nm_connection_get_setting_wireless (connection);
|
||||
g_return_val_if_fail (s_wifi, FALSE);
|
||||
|
||||
/* Only Infrastrusture mode at this time */
|
||||
mode = nm_setting_wireless_get_mode (s_wifi);
|
||||
if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* Hidden SSIDs not supported yet */
|
||||
if (nm_setting_wireless_get_hidden (s_wifi))
|
||||
return FALSE;
|
||||
|
||||
/* 8021x networks can only be used if they've been provisioned on the IWD side and
|
||||
* thus are Known Networks.
|
||||
*/
|
||||
if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) {
|
||||
if (!is_connection_known_network (connection))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* a connection that is available for a certain @specific_object, MUST
|
||||
* also be available in general (without @specific_object). */
|
||||
|
||||
|
|
@ -482,15 +552,6 @@ check_connection_available (NMDevice *device,
|
|||
return ap ? nm_wifi_ap_check_compatible (ap, connection) : FALSE;
|
||||
}
|
||||
|
||||
/* Only Infrastrusture mode at this time */
|
||||
mode = nm_setting_wireless_get_mode (s_wifi);
|
||||
if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) != 0)
|
||||
return FALSE;
|
||||
|
||||
/* Hidden SSIDs not supported yet */
|
||||
if (nm_setting_wireless_get_hidden (s_wifi))
|
||||
return FALSE;
|
||||
|
||||
if (NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
|
||||
return TRUE;
|
||||
|
||||
|
|
@ -608,6 +669,19 @@ complete_connection (NMDevice *device,
|
|||
if (tmp_ssid)
|
||||
g_byte_array_unref (tmp_ssid);
|
||||
|
||||
/* 8021x networks can only be used if they've been provisioned on the IWD side and
|
||||
* thus are Known Networks.
|
||||
*/
|
||||
if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) {
|
||||
if (!is_connection_known_network (connection)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_DEVICE_ERROR_INVALID_CONNECTION,
|
||||
"This 8021x network has not been provisioned on this machine");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
perm_hw_addr = nm_device_get_permanent_hw_address (device);
|
||||
if (perm_hw_addr) {
|
||||
setting_mac = nm_setting_wireless_get_mac_address (s_wifi);
|
||||
|
|
@ -682,6 +756,14 @@ can_auto_connect (NMDevice *device,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* 8021x networks can only be used if they've been provisioned on the IWD side and
|
||||
* thus are Known Networks.
|
||||
*/
|
||||
if (get_connection_iwd_security (connection) == NM_IWD_NETWORK_SECURITY_8021X) {
|
||||
if (!is_connection_known_network (connection))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ap = nm_wifi_aps_find_first_compatible (priv->aps, connection, FALSE);
|
||||
if (ap) {
|
||||
/* All good; connection is usable */
|
||||
|
|
@ -997,10 +1079,25 @@ handle_8021x_or_psk_auth_fail (NMDeviceIwd *self)
|
|||
NMActRequest *req;
|
||||
const char *setting_name = NULL;
|
||||
gboolean handled = FALSE;
|
||||
NMConnection *connection;
|
||||
|
||||
req = nm_device_get_act_request (device);
|
||||
g_return_val_if_fail (req != NULL, FALSE);
|
||||
|
||||
/* If this is an IWD Known Network, even if the failure was caused by bad secrets,
|
||||
* IWD won't ask our agent for new secrets until we call ForgetNetwork. For 8021x
|
||||
* this is not a good idea since the IWD network config file is assumed to be
|
||||
* provisioned by the system admin and the admin needs to intervene anyway. For
|
||||
* PSK we may want to do this here (TODO).
|
||||
*/
|
||||
connection = nm_act_request_get_applied_connection (req);
|
||||
if (is_connection_known_network (connection)) {
|
||||
_LOGI (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation: (wifi) disconnected during association to an IWD Known Network, giving up");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( need_new_8021x_secrets (self, &setting_name)
|
||||
|| need_new_wpa_psk (self, &setting_name)) {
|
||||
nm_act_request_clear_secrets (req);
|
||||
|
|
@ -1030,6 +1127,7 @@ network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
|||
NMConnection *connection;
|
||||
NMSettingWireless *s_wifi;
|
||||
GBytes *ssid;
|
||||
gs_free gchar *str_ssid = NULL;
|
||||
|
||||
if (!_nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res,
|
||||
G_VARIANT_TYPE ("()"),
|
||||
|
|
@ -1084,11 +1182,17 @@ network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
|||
if (!ssid)
|
||||
goto failed;
|
||||
|
||||
str_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL),
|
||||
g_bytes_get_size (ssid));
|
||||
|
||||
_LOGI (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Connected to '%s'.",
|
||||
ssid ? nm_utils_escape_ssid (g_bytes_get_data (ssid, NULL),
|
||||
g_bytes_get_size (ssid)) : "(none)");
|
||||
str_ssid);
|
||||
nm_device_activate_schedule_stage3_ip_config_start (device);
|
||||
|
||||
nm_iwd_manager_network_connected (nm_iwd_manager_get (), str_ssid,
|
||||
get_connection_iwd_security (connection));
|
||||
|
||||
return;
|
||||
|
||||
failed:
|
||||
|
|
@ -1206,8 +1310,14 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
s_wireless = nm_connection_get_setting_wireless (connection);
|
||||
g_assert (s_wireless);
|
||||
|
||||
/* If we need secrets, get them */
|
||||
setting_name = nm_connection_need_secrets (connection, NULL);
|
||||
/* If we need secrets, get them. If a network is an IWD Known Network the secrets
|
||||
* will have been stored by IWD and we don't require any secrets here.
|
||||
*/
|
||||
if (!is_connection_known_network (connection))
|
||||
setting_name = nm_connection_need_secrets (connection, NULL);
|
||||
else
|
||||
setting_name = NULL;
|
||||
|
||||
if (setting_name) {
|
||||
_LOGI (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation: (wifi) access point '%s' has security, but secrets are required.",
|
||||
|
|
@ -1243,8 +1353,6 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
NM_IWD_NETWORK_INTERFACE,
|
||||
NULL, &error);
|
||||
if (!network_proxy) {
|
||||
return FALSE;
|
||||
|
||||
_LOGE (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation: (wifi) could not get Network interface proxy for %s: %s",
|
||||
nm_wifi_ap_get_supplicant_path (ap),
|
||||
|
|
|
|||
|
|
@ -26,18 +26,25 @@
|
|||
#include <net/if.h>
|
||||
|
||||
#include "nm-logging.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-device-iwd.h"
|
||||
#include "nm-utils/nm-random-utils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
gchar *name;
|
||||
NMIwdNetworkSecurity security;
|
||||
} KnownNetworkData;
|
||||
|
||||
typedef struct {
|
||||
GCancellable *cancellable;
|
||||
gboolean running;
|
||||
GDBusObjectManager *object_manager;
|
||||
guint agent_id;
|
||||
gchar *agent_path;
|
||||
GSList *known_networks;
|
||||
} NMIwdManagerPrivate;
|
||||
|
||||
struct _NMIwdManager {
|
||||
|
|
@ -232,6 +239,26 @@ psk_agent_export (GDBusConnection *connection, gpointer user_data,
|
|||
return id;
|
||||
}
|
||||
|
||||
static void
|
||||
register_agent (NMIwdManager *self)
|
||||
{
|
||||
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
|
||||
GDBusInterface *agent_manager;
|
||||
|
||||
agent_manager = g_dbus_object_manager_get_interface (priv->object_manager,
|
||||
"/",
|
||||
NM_IWD_AGENT_MANAGER_INTERFACE);
|
||||
|
||||
/* Register our agent */
|
||||
g_dbus_proxy_call (G_DBUS_PROXY (agent_manager),
|
||||
"RegisterAgent",
|
||||
g_variant_new ("(o)", priv->agent_path),
|
||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (agent_manager);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -336,6 +363,99 @@ object_added (NMIwdManager *self, GDBusObject *object)
|
|||
g_list_free_full (interfaces, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
known_network_free (KnownNetworkData *network)
|
||||
{
|
||||
g_free (network->name);
|
||||
g_free (network);
|
||||
}
|
||||
|
||||
static void
|
||||
list_known_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
NMIwdManager *self = user_data;
|
||||
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
|
||||
gs_free_error GError *error = NULL;
|
||||
gs_unref_variant GVariant *variant = NULL;
|
||||
GVariantIter *networks, *props;
|
||||
|
||||
variant = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res,
|
||||
G_VARIANT_TYPE ("(aa{sv})"),
|
||||
&error);
|
||||
if (!variant) {
|
||||
_LOGE ("ListKnownNetworks() failed: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free);
|
||||
priv->known_networks = NULL;
|
||||
|
||||
g_variant_get (variant, "(aa{sv})", &networks);
|
||||
|
||||
while (g_variant_iter_next (networks, "a{sv}", &props)) {
|
||||
const gchar *key;
|
||||
const gchar *name = NULL;
|
||||
const gchar *type = NULL;
|
||||
GVariant *val;
|
||||
KnownNetworkData *network_data;
|
||||
|
||||
while (g_variant_iter_next (props, "{&sv}", &key, &val)) {
|
||||
if (!strcmp (key, "Name"))
|
||||
name = g_variant_get_string (val, NULL);
|
||||
|
||||
if (!strcmp (key, "Type"))
|
||||
type = g_variant_get_string (val, NULL);
|
||||
|
||||
g_variant_unref (val);
|
||||
}
|
||||
|
||||
if (!name || !type)
|
||||
goto next;
|
||||
|
||||
network_data = g_new (KnownNetworkData, 1);
|
||||
network_data->name = g_strdup (name);
|
||||
if (!strcmp (type, "open"))
|
||||
network_data->security = NM_IWD_NETWORK_SECURITY_NONE;
|
||||
else if (!strcmp (type, "psk"))
|
||||
network_data->security = NM_IWD_NETWORK_SECURITY_PSK;
|
||||
else if (!strcmp (type, "8021x"))
|
||||
network_data->security = NM_IWD_NETWORK_SECURITY_8021X;
|
||||
|
||||
priv->known_networks = g_slist_append (priv->known_networks,
|
||||
network_data);
|
||||
|
||||
next:
|
||||
g_variant_iter_free (props);
|
||||
}
|
||||
|
||||
g_variant_iter_free (networks);
|
||||
|
||||
/* For completness we may want to call nm_device_emit_recheck_auto_activate
|
||||
* and nm_device_recheck_available_connections for all affected devices
|
||||
* now but the ListKnownNetworks call should have been really fast,
|
||||
* faster than any scan on any newly created devices could have happened.
|
||||
*/
|
||||
}
|
||||
|
||||
static void
|
||||
update_known_networks (NMIwdManager *self)
|
||||
{
|
||||
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
|
||||
GDBusInterface *known_networks_if;
|
||||
|
||||
known_networks_if = g_dbus_object_manager_get_interface (priv->object_manager,
|
||||
"/",
|
||||
NM_IWD_KNOWN_NETWORKS_INTERFACE);
|
||||
|
||||
g_dbus_proxy_call (G_DBUS_PROXY (known_networks_if),
|
||||
"ListKnownNetworks",
|
||||
g_variant_new ("()"),
|
||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
priv->cancellable, list_known_networks_cb, self);
|
||||
|
||||
g_object_unref (known_networks_if);
|
||||
}
|
||||
|
||||
static void
|
||||
name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
|
|
@ -356,22 +476,10 @@ name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
|
|||
|
||||
g_list_free_full (objects, g_object_unref);
|
||||
|
||||
if (priv->agent_id) {
|
||||
GDBusInterface *agent_manager;
|
||||
if (priv->agent_id)
|
||||
register_agent (self);
|
||||
|
||||
agent_manager = g_dbus_object_manager_get_interface (object_manager,
|
||||
"/",
|
||||
NM_IWD_AGENT_MANAGER_INTERFACE);
|
||||
|
||||
/* Register our agent */
|
||||
g_dbus_proxy_call (G_DBUS_PROXY (agent_manager),
|
||||
"RegisterAgent",
|
||||
g_variant_new ("(o)", priv->agent_path),
|
||||
G_DBUS_CALL_FLAGS_NONE, -1,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
g_object_unref (agent_manager);
|
||||
}
|
||||
update_known_networks (self);
|
||||
} else {
|
||||
NMManager *manager = nm_manager_get ();
|
||||
const GSList *devices, *iter;
|
||||
|
|
@ -498,6 +606,39 @@ prepare_object_manager (NMIwdManager *self)
|
|||
got_object_manager, self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_iwd_manager_is_known_network (NMIwdManager *self, const gchar *name,
|
||||
NMIwdNetworkSecurity security)
|
||||
{
|
||||
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
|
||||
const GSList *iter;
|
||||
|
||||
for (iter = priv->known_networks; iter; iter = g_slist_next (iter)) {
|
||||
const KnownNetworkData *network = iter->data;
|
||||
|
||||
if (!strcmp (network->name, name) && network->security == security)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nm_iwd_manager_network_connected (NMIwdManager *self, const gchar *name,
|
||||
NMIwdNetworkSecurity security)
|
||||
{
|
||||
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
|
||||
KnownNetworkData *network_data;
|
||||
|
||||
if (nm_iwd_manager_is_known_network (self, name, security))
|
||||
return;
|
||||
|
||||
network_data = g_new (KnownNetworkData, 1);
|
||||
network_data->name = g_strdup (name);
|
||||
network_data->security = security;
|
||||
priv->known_networks = g_slist_append (priv->known_networks, network_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_DEFINE_SINGLETON_GETTER (NMIwdManager, nm_iwd_manager_get,
|
||||
|
|
@ -540,6 +681,9 @@ dispose (GObject *object)
|
|||
|
||||
nm_clear_g_cancellable (&priv->cancellable);
|
||||
|
||||
g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free);
|
||||
priv->known_networks = NULL;
|
||||
|
||||
G_OBJECT_CLASS (nm_iwd_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@
|
|||
#define NM_IWD_KNOWN_NETWORKS_INTERFACE "net.connman.iwd.KnownNetworks"
|
||||
#define NM_IWD_SIGNAL_AGENT_INTERFACE "net.connman.iwd.SignalLevelAgent"
|
||||
|
||||
typedef enum {
|
||||
NM_IWD_NETWORK_SECURITY_NONE,
|
||||
NM_IWD_NETWORK_SECURITY_WEP,
|
||||
NM_IWD_NETWORK_SECURITY_PSK,
|
||||
NM_IWD_NETWORK_SECURITY_8021X,
|
||||
} NMIwdNetworkSecurity;
|
||||
|
||||
#define NM_TYPE_IWD_MANAGER (nm_iwd_manager_get_type ())
|
||||
#define NM_IWD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IWD_MANAGER, NMIwdManager))
|
||||
#define NM_IWD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IWD_MANAGER, NMIwdManagerClass))
|
||||
|
|
@ -50,4 +57,9 @@ GType nm_iwd_manager_get_type (void);
|
|||
|
||||
NMIwdManager *nm_iwd_manager_get (void);
|
||||
|
||||
gboolean nm_iwd_manager_is_known_network (NMIwdManager *self, const gchar *name,
|
||||
NMIwdNetworkSecurity security);
|
||||
void nm_iwd_manager_network_connected (NMIwdManager *self, const gchar *name,
|
||||
NMIwdNetworkSecurity security);
|
||||
|
||||
#endif /* __NETWORKMANAGER_IWD_MANAGER_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue