wifi/iwd: merge branch 'balrog-kun/iwd-known-networks'

https://github.com/NetworkManager/NetworkManager/pull/183
This commit is contained in:
Thomas Haller
2018-09-05 16:06:57 +02:00
7 changed files with 432 additions and 233 deletions

View File

@@ -2804,6 +2804,7 @@ static EAPMethodsTable eap_methods_table[] = {
{ "sim", need_secrets_sim, NULL },
{ "gtc", need_secrets_password, verify_identity },
{ "otp", NULL, NULL }, // FIXME: implement
{ "external", NULL, NULL },
{ NULL, NULL, NULL }
};
@@ -2812,7 +2813,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
{
NMSetting8021x *self = NM_SETTING_802_1X (setting);
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", NULL };
const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", "external", NULL };
GSList *iter;
if (error)

View File

@@ -448,33 +448,12 @@ deactivate_async (NMDevice *device,
G_DBUS_CALL_FLAGS_NONE, -1, cancellable, disconnect_cb, ctx);
}
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;
NMIwdNetworkSecurity security;
gboolean security_ok;
GBytes *ssid;
gs_free char *ssid_utf8 = NULL;
@@ -487,9 +466,13 @@ is_connection_known_network (NMConnection *connection)
return FALSE;
ssid_utf8 = _nm_utils_ssid_to_utf8 (ssid);
security = nm_wifi_connection_get_iwd_security (connection, &security_ok);
if (!security_ok)
return FALSE;
return nm_iwd_manager_is_known_network (nm_iwd_manager_get (),
ssid_utf8,
get_connection_iwd_security (connection));
ssid_utf8, security);
}
static gboolean
@@ -543,7 +526,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection, GError
/* 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 (nm_wifi_connection_get_iwd_security (connection, NULL) == NM_IWD_NETWORK_SECURITY_8021X) {
if (!is_connection_known_network (connection)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"802.1x profile is not a known network");
@@ -587,7 +570,7 @@ check_connection_available (NMDevice *device,
/* 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 (nm_wifi_connection_get_iwd_security (connection, NULL) == NM_IWD_NETWORK_SECURITY_8021X) {
if (!is_connection_known_network (connection)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"network is not known to iwd");
@@ -731,7 +714,7 @@ complete_connection (NMDevice *device,
/* 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 (nm_wifi_connection_get_iwd_security (connection, NULL) == NM_IWD_NETWORK_SECURITY_8021X) {
if (!is_connection_known_network (connection)) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
@@ -772,6 +755,32 @@ complete_connection (NMDevice *device,
return TRUE;
}
static gboolean
get_variant_boolean (GVariant *v, const char *property)
{
if (!v || !g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) {
nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
"Property %s not cached or not boolean type", property);
return FALSE;
}
return g_variant_get_boolean (v);
}
static const char *
get_variant_state (GVariant *v)
{
if (!v || !g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)) {
nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
"State property not cached or not a string");
return "unknown";
}
return g_variant_get_string (v, NULL);
}
static gboolean
is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
{
@@ -783,7 +792,7 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
return FALSE;
value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "Powered");
return g_variant_get_boolean (value);
return get_variant_boolean (value, "Powered");
}
static gboolean
@@ -835,7 +844,7 @@ can_auto_connect (NMDevice *device,
/* 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 (nm_wifi_connection_get_iwd_security (connection, NULL) == NM_IWD_NETWORK_SECURITY_8021X) {
if (!is_connection_known_network (connection))
return FALSE;
}
@@ -1305,9 +1314,6 @@ network_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data)
ssid_utf8);
nm_device_activate_schedule_stage3_ip_config_start (device);
nm_iwd_manager_network_connected (nm_iwd_manager_get (), ssid_utf8,
get_connection_iwd_security (connection));
return;
failed:
@@ -1756,7 +1762,8 @@ state_changed (NMDeviceIwd *self, const char *new_state)
NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
return;
}
} else if (nm_streq (new_state, "unknown"))
return;
_LOGE (LOGD_WIFI, "State %s unknown", new_state);
}
@@ -1802,13 +1809,13 @@ properties_changed (GDBusProxy *proxy, GVariant *changed_properties,
g_variant_get (changed_properties, "a{sv}", &iter);
while (g_variant_iter_next (iter, "{&sv}", &key, &value)) {
if (!strcmp (key, "State"))
state_changed (self, g_variant_get_string (value, NULL));
state_changed (self, get_variant_state (value));
if (!strcmp (key, "Scanning"))
scanning_changed (self, g_variant_get_boolean (value));
scanning_changed (self, get_variant_boolean (value, "Scanning"));
if (!strcmp (key, "Powered"))
powered_changed (self, g_variant_get_boolean (value));
powered_changed (self, get_variant_boolean (value, "Powered"));
g_variant_unref (value);
}
@@ -1849,12 +1856,12 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object)
priv->dbus_proxy = G_DBUS_PROXY (interface);
value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "Scanning");
priv->scanning = g_variant_get_boolean (value);
priv->scanning = get_variant_boolean (value, "Scanning");
g_variant_unref (value);
priv->scan_requested = FALSE;
value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "State");
state_changed (self, g_variant_get_string (value, NULL));
state_changed (self, get_variant_state (value));
g_variant_unref (value);
g_signal_connect (priv->dbus_proxy, "g-properties-changed",

View File

@@ -29,13 +29,21 @@
#include "nm-core-internal.h"
#include "nm-manager.h"
#include "nm-device-iwd.h"
#include "nm-wifi-utils.h"
#include "nm-utils/nm-random-utils.h"
#include "settings/nm-settings.h"
/*****************************************************************************/
typedef struct {
char *name;
const char *name;
NMIwdNetworkSecurity security;
char buf[0];
} KnownNetworkId;
typedef struct {
GDBusProxy *known_network;
NMSettingsConnection *mirror_connection;
} KnownNetworkData;
typedef struct {
@@ -45,7 +53,7 @@ typedef struct {
GDBusObjectManager *object_manager;
guint agent_id;
char *agent_path;
GSList *known_networks;
GHashTable *known_networks;
} NMIwdManagerPrivate;
struct _NMIwdManager {
@@ -83,6 +91,36 @@ G_DEFINE_TYPE (NMIwdManager, nm_iwd_manager, G_TYPE_OBJECT)
/*****************************************************************************/
static void mirror_8021x_connection_take_and_delete (NMSettingsConnection *sett_conn);
/*****************************************************************************/
static const char *
get_variant_string_or_null (GVariant *v)
{
if (!v)
return NULL;
if ( !g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)
&& !g_variant_is_of_type (v, G_VARIANT_TYPE_OBJECT_PATH))
return NULL;
return g_variant_get_string (v, NULL);
}
static const char *
get_property_string_or_null (GDBusProxy *proxy, const char *property)
{
gs_unref_variant GVariant *value = NULL;
if (!proxy || !property)
return NULL;
value = g_dbus_proxy_get_cached_property (proxy, property);
return get_variant_string_or_null (value);
}
static void
agent_dbus_method_cb (GDBusConnection *connection,
const char *sender, const char *object_path,
@@ -95,7 +133,6 @@ agent_dbus_method_cb (GDBusConnection *connection,
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
const char *network_path, *device_path, *ifname;
gs_unref_object GDBusInterface *network = NULL, *device_obj = NULL;
gs_unref_variant GVariant *value = NULL;
int ifindex;
NMDevice *device;
gs_free char *name_owner = NULL;
@@ -113,9 +150,8 @@ agent_dbus_method_cb (GDBusConnection *connection,
network = g_dbus_object_manager_get_interface (priv->object_manager,
network_path,
NM_IWD_NETWORK_INTERFACE);
value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (network), "Device");
device_path = g_variant_get_string (value, NULL);
device_path = get_property_string_or_null (G_DBUS_PROXY (network), "Device");
if (!device_path) {
_LOGD ("agent-request: device not cached for network %s in IWD Agent request",
network_path);
@@ -125,10 +161,8 @@ agent_dbus_method_cb (GDBusConnection *connection,
device_obj = g_dbus_object_manager_get_interface (priv->object_manager,
device_path,
NM_IWD_DEVICE_INTERFACE);
g_variant_unref (value);
value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (device_obj), "Name");
ifname = g_variant_get_string (value, NULL);
ifname = get_property_string_or_null (G_DBUS_PROXY (device_obj), "Name");
if (!ifname) {
_LOGD ("agent-request: name not cached for device %s in IWD Agent request",
device_path);
@@ -251,38 +285,68 @@ register_agent (NMIwdManager *self)
/*****************************************************************************/
static KnownNetworkId *
known_network_id_new (const char *name, NMIwdNetworkSecurity security)
{
KnownNetworkId *id;
gsize strsize = strlen (name) + 1;
id = g_malloc (sizeof (KnownNetworkId) + strsize);
id->name = id->buf;
id->security = security;
memcpy (id->buf, name, strsize);
return id;
}
static guint
known_network_id_hash (KnownNetworkId *id)
{
NMHashState h;
nm_hash_init (&h, 1947951703u);
nm_hash_update_val (&h, id->security);
nm_hash_update_str (&h, id->name);
return nm_hash_complete (&h);
}
static gboolean
known_network_id_equal (KnownNetworkId *a, KnownNetworkId *b)
{
return a->security == b->security
&& nm_streq (a->name, b->name);
}
static void
set_device_dbus_object (NMIwdManager *self, GDBusInterface *interface,
known_network_data_free (KnownNetworkData *network)
{
if (!network)
return;
g_object_unref (network->known_network);
mirror_8021x_connection_take_and_delete (network->mirror_connection);
g_slice_free (KnownNetworkData, network);
}
/*****************************************************************************/
static void
set_device_dbus_object (NMIwdManager *self, GDBusProxy *proxy,
GDBusObject *object)
{
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
GDBusProxy *proxy;
GVariant *value;
const char *ifname;
int ifindex;
NMDevice *device;
if (!priv->running)
return;
g_return_if_fail (G_IS_DBUS_PROXY (interface));
proxy = G_DBUS_PROXY (interface);
if (strcmp (g_dbus_proxy_get_interface_name (proxy),
NM_IWD_DEVICE_INTERFACE))
return;
value = g_dbus_proxy_get_cached_property (proxy, "Name");
if (!value) {
ifname = get_property_string_or_null (proxy, "Name");
if (!ifname) {
_LOGE ("Name not cached for Device at %s",
g_dbus_proxy_get_object_path (proxy));
return;
}
ifname = g_variant_get_string (value, NULL);
ifindex = if_nametoindex (ifname);
g_variant_unref (value);
if (!ifindex) {
_LOGE ("if_nametoindex failed for Name %s for Device at %s: %i",
@@ -299,13 +363,183 @@ set_device_dbus_object (NMIwdManager *self, GDBusInterface *interface,
nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), object);
}
/* Create an in-memory NMConnection for a WPA2-Enterprise network that
* has been preprovisioned with an IWD config file so that NM autoconnect
* mechanism and the clients know this networks needs no additional EAP
* configuration from the user. Only do this if no existing connection
* SSID and security type match that network yet.
*/
static NMSettingsConnection *
mirror_8021x_connection (NMIwdManager *self,
const char *name)
{
NMSettings *settings = NM_SETTINGS_GET;
NMSettingsConnection *const*iter;
gs_unref_object NMConnection *connection = NULL;
NMSettingsConnection *settings_connection;
char uuid[37];
NMSetting *setting;
GError *error = NULL;
gs_unref_bytes GBytes *new_ssid = NULL;
for (iter = nm_settings_get_connections (settings, NULL); *iter; iter++) {
NMSettingsConnection *sett_conn = *iter;
NMConnection *conn = nm_settings_connection_get_connection (sett_conn);
NMIwdNetworkSecurity security;
gs_free char *ssid_name = NULL;
NMSettingWireless *s_wifi;
security = nm_wifi_connection_get_iwd_security (conn, NULL);
if (security != NM_IWD_NETWORK_SECURITY_8021X)
continue;
s_wifi = nm_connection_get_setting_wireless (conn);
if (!s_wifi)
continue;
ssid_name = _nm_utils_ssid_to_utf8 (nm_setting_wireless_get_ssid (s_wifi));
/* We already have an NMSettingsConnection matching this
* KnownNetwork, whether it's saved or an in-memory connection
* potentially created by ourselves. Nothing to do here.
*/
if (nm_streq (ssid_name, name))
return NULL;
}
connection = nm_simple_connection_new ();
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_CONNECTION,
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_CONNECTION_ID, name,
NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid),
NM_SETTING_CONNECTION_READ_ONLY, TRUE,
NULL));
nm_connection_add_setting (connection, setting);
new_ssid = g_bytes_new (name, strlen (name));
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS,
NM_SETTING_WIRELESS_SSID, new_ssid,
NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
NULL));
nm_connection_add_setting (connection, setting);
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_WIRELESS_SECURITY,
NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open",
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap",
NULL));
nm_connection_add_setting (connection, setting);
setting = NM_SETTING (g_object_new (NM_TYPE_SETTING_802_1X, NULL));
nm_setting_802_1x_add_eap_method (NM_SETTING_802_1X (setting), "external");
nm_connection_add_setting (connection, setting);
if (!nm_connection_normalize (connection, NULL, NULL, NULL))
return NULL;
settings_connection = nm_settings_add_connection (settings, connection,
FALSE, &error);
if (!settings_connection) {
_LOGW ("failed to add a mirror NMConnection for IWD's Known Network '%s': %s",
name, error->message);
g_error_free (error);
return NULL;
}
nm_settings_connection_set_flags (settings_connection,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED |
NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED,
TRUE);
return settings_connection;
}
static void
mirror_8021x_connection_take_and_delete (NMSettingsConnection *sett_conn)
{
NMSettingsConnectionIntFlags flags;
if (!sett_conn)
return;
flags = nm_settings_connection_get_flags (sett_conn);
/* If connection has not been saved since we created it
* in interface_added it too can be removed now. */
if (NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED))
nm_settings_connection_delete (sett_conn, NULL);
g_object_unref (sett_conn);
}
static void
interface_added (GDBusObjectManager *object_manager, GDBusObject *object,
GDBusInterface *interface, gpointer user_data)
{
NMIwdManager *self = user_data;
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
GDBusProxy *proxy;
const char *iface_name;
set_device_dbus_object (self, interface, object);
if (!priv->running)
return;
g_return_if_fail (G_IS_DBUS_PROXY (interface));
proxy = G_DBUS_PROXY (interface);
iface_name = g_dbus_proxy_get_interface_name (proxy);
if (nm_streq (iface_name, NM_IWD_DEVICE_INTERFACE)) {
set_device_dbus_object (self, proxy, object);
return;
}
if (nm_streq (iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) {
KnownNetworkId *id;
KnownNetworkData *data;
NMIwdNetworkSecurity security;
const char *type_str, *name;
NMSettingsConnection *sett_conn = NULL;
type_str = get_property_string_or_null (proxy, "Type");
name = get_property_string_or_null (proxy, "Name");
if (!type_str || !name)
return;
if (nm_streq (type_str, "open"))
security = NM_IWD_NETWORK_SECURITY_NONE;
else if (nm_streq (type_str, "psk"))
security = NM_IWD_NETWORK_SECURITY_PSK;
else if (nm_streq (type_str, "8021x"))
security = NM_IWD_NETWORK_SECURITY_8021X;
else
return;
id = known_network_id_new (name, security);
data = g_hash_table_lookup (priv->known_networks, id);
if (data)
g_free (id);
else {
data = g_slice_new0 (KnownNetworkData);
data->known_network = g_object_ref (proxy);
g_hash_table_insert (priv->known_networks, id, data);
}
if (security == NM_IWD_NETWORK_SECURITY_8021X) {
sett_conn = mirror_8021x_connection (self, name);
if ( sett_conn
&& sett_conn != data->mirror_connection) {
NMSettingsConnection *sett_conn_old = data->mirror_connection;
data->mirror_connection = nm_g_object_ref (sett_conn);
mirror_8021x_connection_take_and_delete (sett_conn_old);
}
} else
mirror_8021x_connection_take_and_delete (g_steal_pointer (&data->mirror_connection));
return;
}
}
static void
@@ -313,15 +547,41 @@ interface_removed (GDBusObjectManager *object_manager, GDBusObject *object,
GDBusInterface *interface, gpointer user_data)
{
NMIwdManager *self = user_data;
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
GDBusProxy *proxy;
const char *iface_name;
/*
* TODO: we may need to save the GDBusInterface or GDBusObject
* pointer in the hash table because we may be no longer able to
* access the Name property or map the name to ifindex with
* if_nametoindex at this point.
*/
g_return_if_fail (G_IS_DBUS_PROXY (interface));
set_device_dbus_object (self, interface, NULL);
proxy = G_DBUS_PROXY (interface);
iface_name = g_dbus_proxy_get_interface_name (proxy);
if (nm_streq (iface_name, NM_IWD_DEVICE_INTERFACE)) {
set_device_dbus_object (self, proxy, NULL);
return;
}
if (nm_streq (iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) {
KnownNetworkId id;
const char *type_str;
type_str = get_property_string_or_null (proxy, "Type");
id.name = get_property_string_or_null (proxy, "Name");
if (!type_str || !id.name)
return;
if (nm_streq (type_str, "open"))
id.security = NM_IWD_NETWORK_SECURITY_NONE;
else if (nm_streq (type_str, "psk"))
id.security = NM_IWD_NETWORK_SECURITY_PSK;
else if (nm_streq (type_str, "8021x"))
id.security = NM_IWD_NETWORK_SECURITY_8021X;
else
return;
g_hash_table_remove (priv->known_networks, &id);
return;
}
}
static gboolean
@@ -341,108 +601,16 @@ object_added (NMIwdManager *self, GDBusObject *object)
GList *interfaces, *iter;
interfaces = g_dbus_object_get_interfaces (object);
for (iter = interfaces; iter; iter = iter->next) {
GDBusInterface *interface = G_DBUS_INTERFACE (iter->data);
set_device_dbus_object (self, interface, object);
interface_added (NULL, object, interface, self);
}
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 char *key;
const char *name = NULL;
const char *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 prepare_object_manager (NMIwdManager *self);
static void
@@ -492,28 +660,14 @@ device_added (NMManager *manager, NMDevice *device, gpointer user_data)
objects = g_dbus_object_manager_get_objects (priv->object_manager);
for (iter = objects; iter; iter = iter->next) {
GDBusObject *object = G_DBUS_OBJECT (iter->data);
GDBusInterface *interface;
GDBusProxy *proxy;
GVariant *value;
gs_unref_object GDBusInterface *interface = NULL;
const char *obj_ifname;
interface = g_dbus_object_get_interface (object,
NM_IWD_DEVICE_INTERFACE);
if (!interface)
continue;
obj_ifname = get_property_string_or_null ((GDBusProxy *) interface, "Name");
proxy = G_DBUS_PROXY (interface);
value = g_dbus_proxy_get_cached_property (proxy, "Name");
if (!value) {
g_object_unref (interface);
continue;
}
obj_ifname = g_variant_get_string (value, NULL);
g_variant_unref (value);
g_object_unref (interface);
if (strcmp (nm_device_get_iface (device), obj_ifname))
if (!obj_ifname || strcmp (nm_device_get_iface (device), obj_ifname))
continue;
nm_device_iwd_set_dbus_object (NM_DEVICE_IWD (device), object);
@@ -535,7 +689,7 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
object_manager = g_dbus_object_manager_client_new_for_bus_finish (result, &error);
if (object_manager == NULL) {
_LOGE ("failed to acquire IWD Object Manager: Wi-Fi will not be available (%s)",
NM_G_ERROR_MSG (error));
error->message);
g_clear_error (&error);
return;
}
@@ -549,11 +703,13 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
connection = g_dbus_object_manager_client_get_connection (G_DBUS_OBJECT_MANAGER_CLIENT (object_manager));
priv->agent_id = iwd_agent_export (connection, self,
&priv->agent_path, &error);
priv->agent_id = iwd_agent_export (connection,
self,
&priv->agent_path,
&error);
if (!priv->agent_id) {
_LOGE ("failed to export the IWD Agent: PSK/8021x WiFi networks will not work: %s",
NM_G_ERROR_MSG (error));
error->message);
g_clear_error (&error);
}
@@ -567,6 +723,8 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
g_signal_connect (priv->object_manager, "interface-removed",
G_CALLBACK (interface_removed), self);
g_hash_table_remove_all (priv->known_networks);
objects = g_dbus_object_manager_get_objects (object_manager);
for (iter = objects; iter; iter = iter->next)
object_added (self, G_DBUS_OBJECT (iter->data));
@@ -575,8 +733,6 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
if (priv->agent_id)
register_agent (self);
update_known_networks (self);
}
}
@@ -598,32 +754,9 @@ nm_iwd_manager_is_known_network (NMIwdManager *self, const char *name,
NMIwdNetworkSecurity security)
{
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
const GSList *iter;
KnownNetworkId kn_id = { name, security };
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 char *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);
return g_hash_table_contains (priv->known_networks, &kn_id);
}
/*****************************************************************************/
@@ -642,6 +775,11 @@ nm_iwd_manager_init (NMIwdManager *self)
priv->cancellable = g_cancellable_new ();
priv->known_networks = g_hash_table_new_full ((GHashFunc) known_network_id_hash,
(GEqualFunc) known_network_id_equal,
g_free,
(GDestroyNotify) known_network_data_free);
prepare_object_manager (self);
}
@@ -673,8 +811,7 @@ dispose (GObject *object)
nm_clear_g_cancellable (&priv->cancellable);
g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free);
priv->known_networks = NULL;
nm_clear_pointer (&priv->known_networks, g_hash_table_destroy);
if (priv->manager) {
g_signal_handlers_disconnect_by_data (priv->manager, self);

View File

@@ -22,6 +22,7 @@
#define __NETWORKMANAGER_IWD_MANAGER_H__
#include "devices/nm-device.h"
#include "nm-wifi-utils.h"
#define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM
#define NM_IWD_SERVICE "net.connman.iwd"
@@ -33,16 +34,9 @@
#define NM_IWD_AGENT_INTERFACE "net.connman.iwd.Agent"
#define NM_IWD_WSC_INTERFACE \
"net.connman.iwd.WiFiSimpleConfiguration"
#define NM_IWD_KNOWN_NETWORKS_INTERFACE "net.connman.iwd.KnownNetworks"
#define NM_IWD_KNOWN_NETWORK_INTERFACE "net.connman.iwd.KnownNetwork"
#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))
@@ -59,7 +53,5 @@ NMIwdManager *nm_iwd_manager_get (void);
gboolean nm_iwd_manager_is_known_network (NMIwdManager *self, const char *name,
NMIwdNetworkSecurity security);
void nm_iwd_manager_network_connected (NMIwdManager *self, const char *name,
NMIwdNetworkSecurity security);
#endif /* __NETWORKMANAGER_IWD_MANAGER_H__ */

View File

@@ -815,3 +815,36 @@ nm_wifi_utils_is_manf_default_ssid (GBytes *ssid)
}
return FALSE;
}
NMIwdNetworkSecurity
nm_wifi_connection_get_iwd_security (NMConnection *connection,
gboolean *mapped)
{
NMSettingWirelessSecurity *s_wireless_sec;
const char *key_mgmt = NULL;
if (!nm_connection_get_setting_wireless (connection))
goto error;
NM_SET_OUT (mapped, TRUE);
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 (NM_IN_STRSET (key_mgmt, "none", "ieee8021x"))
return NM_IWD_NETWORK_SECURITY_WEP;
if (nm_streq (key_mgmt, "wpa-psk"))
return NM_IWD_NETWORK_SECURITY_PSK;
if (nm_streq (key_mgmt, "wpa-eap"))
return NM_IWD_NETWORK_SECURITY_8021X;
error:
NM_SET_OUT (mapped, FALSE);
return NM_IWD_NETWORK_SECURITY_NONE;
}

View File

@@ -27,6 +27,13 @@
#include "nm-setting-wireless-security.h"
#include "nm-setting-8021x.h"
typedef enum {
NM_IWD_NETWORK_SECURITY_NONE,
NM_IWD_NETWORK_SECURITY_WEP,
NM_IWD_NETWORK_SECURITY_PSK,
NM_IWD_NETWORK_SECURITY_8021X,
} NMIwdNetworkSecurity;
gboolean nm_wifi_utils_complete_connection (GBytes *ssid,
const char *bssid,
NM80211Mode mode,
@@ -41,4 +48,7 @@ guint32 nm_wifi_utils_level_to_quality (int val);
gboolean nm_wifi_utils_is_manf_default_ssid (GBytes *ssid);
NMIwdNetworkSecurity nm_wifi_connection_get_iwd_security (NMConnection *connection,
gboolean *mapped);
#endif /* __NM_WIFI_UTILS_H__ */

View File

@@ -1001,6 +1001,7 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
guint32 frag, hdrs;
gs_free char *frag_str = NULL;
NMSetting8021xAuthFlags phase1_auth_flags;
nm_auto_free_gstring GString *eap_str = NULL;
g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
g_return_val_if_fail (setting != NULL, FALSE);
@@ -1037,20 +1038,38 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
priv->ap_scan = 0;
}
if (!ADD_STRING_LIST_VAL (self, setting, 802_1x, eap_method, eap_methods, "eap", ' ', TRUE, NULL, error))
return FALSE;
/* Check EAP method for special handling: PEAP + GTC, FAST */
/* Build the "eap" option string while we check for EAP methods needing
* special handling: PEAP + GTC, FAST, external */
eap_str = g_string_new (NULL);
num_eap = nm_setting_802_1x_get_num_eap_methods (setting);
for (i = 0; i < num_eap; i++) {
const char *method = nm_setting_802_1x_get_eap_method (setting, i);
if (method && (strcasecmp (method, "fast") == 0)) {
if (nm_streq (method, "fast")) {
fast = TRUE;
priv->fast_required = TRUE;
}
if (nm_streq (method, "external")) {
if (num_eap == 1) {
g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG,
"Connection settings managed externally to NM, connection"
" cannot be used with wpa_supplicant");
return FALSE;
}
continue;
}
if (eap_str->len)
g_string_append_c (eap_str, ' ');
g_string_append (eap_str, method);
}
g_string_ascii_up (eap_str);
if ( eap_str->len
&& !nm_supplicant_config_add_option (self, "eap", eap_str->str, -1, NULL, error))
return FALSE;
/* Adjust the fragment size according to MTU, but do not set it higher than 1280-14
* for better compatibility */
hdrs = 14; /* EAPOL + EAP-TLS */