2008-11-03 04:13:42 +00:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
2004-06-24 14:18:37 +00:00
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
2008-06-26 18:31:52 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2004-06-24 14:18:37 +00:00
|
|
|
*
|
2016-03-01 09:56:51 +01:00
|
|
|
* Copyright 2004 - 2016 Red Hat, Inc.
|
2014-09-05 10:55:37 +02:00
|
|
|
* Copyright 2005 - 2008 Novell, Inc.
|
2004-06-24 14:18:37 +00:00
|
|
|
*/
|
|
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-default.h"
|
2014-08-25 16:21:59 +02:00
|
|
|
|
2004-06-24 14:18:37 +00:00
|
|
|
#include "NetworkManagerUtils.h"
|
2016-03-01 09:56:51 +01:00
|
|
|
|
2016-06-01 12:31:36 +02:00
|
|
|
#include "nm-common-macros.h"
|
2005-03-14 Ray Strode <rstrode@redhat.com>
Fourth (probably working) cut at porting to
dbus 0.30 api and new hal. This cut adds
some new logging macros to make debugging
easier.
* dispatcher-daemon/NetworkManagerDispatcher.c:
* info-daemon/NetworkmanagerInfo.c:
* info-daemon/NetworkManagerInfoPassphraseDialog.c:
* info-daemon/NetworkManagerInfoVPN.c:
* src/NetworkManager.c:
* src/NetworkManagerAP.c:
* src/NetworkManagerAPList.c:
* src/NetworkManagerDHCP.c:
* src/NetworkManagerDbus.c:
* src/NetworkManagerDevice.c:
* src/NetworkManagerPolicy.c:
* src/NetworkManagerSystem.c:
* src/NetworkManagerUtils.c:
* src/NetworkManagerWireless.c:
* src/autoip.c:
* src/nm-dbus-nm.c:
* src/backends/NetworkManagerDebian.c:
* src/backends/NetworkManagerGentoo.c:
* src/backends/NetworkManagerRedHat.c:
* src/backends/NetworkManagerSlackware.c:
use new logging macros.
* dispatcher-daemon/NetworkManagerDispatcher.c:
(nmd_dbus_filter): s/dbus_free/g_free/
* info-daemon/Makefile.am: link in utils library.
* info-daemon/NetworkmanagerInfo.c: use new logging
macros.
(nmi_dbus_get_network): don't assume enumerations
are 32-bit.
(nmi_dbus_nmi_message_handler): don't free what
doesn't belong to us.
* libnm_glib/libnm_glib.c:
(libnm_glib_get_nm_status):
(libnm_glib_init): don't free what doesn't
belong to us.
(libnm_glib_dbus): strdup result, so it doesn't get
lost when message is unref'd.
* panel-applet/NMWirelessAppletDbus.c:
(nmwa_dbus_update_devices): s/dbus_free/g_free/
* src/NetworkManager.c:
(nm_monitor_wired_link_state): request initial status
dump of all cards when we start up, instead of relying
on /sys/.../carrier.
(nm_info_handler), (nm_set_up_log_handlers):
log handlers to specify what syslog priorites
the logging macros default to.
* src/NetworkManagerAPList.c:
(nm_ap_list_populate_from_nmi):
s/dbus_free_string_array/g_strfreev/
* src/NetworkManagerDbus.c:
(nm_dbus_get_network_object):
validate d-bus message argument types.
Advance message iterator after reading argument,
prepend instead of append to GSList.
* src/NetworkManagerDevice.c:
(nm_device_probe_wired_link_status):
remove redundant /sys in /sys path. remove wrong
contents == NULL means has carrier assumption.
* src/nm-netlink-monitor.c
(nm_netlink_monitor_request_status): implement
function to ask kernel to dump interface link
status over netlink socket.
* test/*.c: s/dbus_free/g_free/
* utils/nm-utils.h:
(nm_print_backtrace): new macro to print backtrace.
(nm_get_timestamp): new macro to get sub-second precise
unix timestamp.
(nm_info), (nm_debug), (nm_warning), (nm_error):
new logging functions. nm_info just prints,
nm_debug includes timestamp and function,
nm_warning includes function, nm_error includes
backtrace and sigtrap.
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@497 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-03-15 05:30:15 +00:00
|
|
|
#include "nm-utils.h"
|
2011-01-13 13:28:52 -06:00
|
|
|
#include "nm-setting-connection.h"
|
|
|
|
|
#include "nm-setting-ip4-config.h"
|
|
|
|
|
#include "nm-setting-ip6-config.h"
|
2016-03-01 09:56:51 +01:00
|
|
|
#include "nm-core-internal.h"
|
2004-06-24 14:18:37 +00:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
#include "nm-platform.h"
|
|
|
|
|
#include "nm-exported-object.h"
|
|
|
|
|
#include "nm-auth-utils.h"
|
2014-08-11 09:37:05 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/******************************************************************************/
|
2015-01-14 13:15:24 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/**
|
|
|
|
|
* nm_utils_get_shared_wifi_permission:
|
|
|
|
|
* @connection: the NMConnection to lookup the permission.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a static string of the wifi-permission (if any) or %NULL.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_utils_get_shared_wifi_permission (NMConnection *connection)
|
2015-01-14 13:15:24 +01:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
NMSettingWireless *s_wifi;
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
|
|
|
|
const char *method = NULL;
|
2015-01-14 13:15:24 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0)
|
|
|
|
|
return NULL; /* Not shared */
|
2015-01-14 13:15:24 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
s_wifi = nm_connection_get_setting_wireless (connection);
|
|
|
|
|
if (s_wifi) {
|
|
|
|
|
s_wsec = nm_connection_get_setting_wireless_security (connection);
|
|
|
|
|
if (s_wsec)
|
|
|
|
|
return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED;
|
|
|
|
|
else
|
|
|
|
|
return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN;
|
2015-01-14 13:15:24 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
return NULL;
|
2015-01-14 13:15:24 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/******************************************************************************/
|
2015-01-14 13:15:24 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static char *
|
|
|
|
|
get_new_connection_name (const GSList *existing,
|
|
|
|
|
const char *preferred,
|
|
|
|
|
const char *fallback_prefix)
|
|
|
|
|
{
|
|
|
|
|
GSList *names = NULL;
|
|
|
|
|
const GSList *iter;
|
|
|
|
|
char *cname = NULL;
|
|
|
|
|
int i = 0;
|
|
|
|
|
gboolean preferred_found = FALSE;
|
2015-01-14 13:15:24 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
g_assert (fallback_prefix);
|
2015-01-14 13:15:24 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
for (iter = existing; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
NMConnection *candidate = NM_CONNECTION (iter->data);
|
|
|
|
|
const char *id;
|
2015-09-24 12:44:20 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
id = nm_connection_get_id (candidate);
|
|
|
|
|
g_assert (id);
|
|
|
|
|
names = g_slist_append (names, (gpointer) id);
|
2015-09-24 12:44:20 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (preferred && !preferred_found && (strcmp (preferred, id) == 0))
|
|
|
|
|
preferred_found = TRUE;
|
2015-09-24 12:44:20 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Return the preferred name if it was unique */
|
|
|
|
|
if (preferred && !preferred_found) {
|
|
|
|
|
g_slist_free (names);
|
|
|
|
|
return g_strdup (preferred);
|
2015-09-24 12:44:20 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Otherwise find the next available unique connection name using the given
|
|
|
|
|
* connection name template.
|
|
|
|
|
*/
|
|
|
|
|
while (!cname && (i++ < 10000)) {
|
|
|
|
|
char *temp;
|
|
|
|
|
gboolean found = FALSE;
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Translators: the first %s is a prefix for the connection id, such
|
|
|
|
|
* as "Wired Connection" or "VPN Connection". The %d is a number
|
|
|
|
|
* that is combined with the first argument to create a unique
|
|
|
|
|
* connection id. */
|
|
|
|
|
temp = g_strdup_printf (C_("connection id fallback", "%s %d"),
|
|
|
|
|
fallback_prefix, i);
|
|
|
|
|
for (iter = names; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
if (!strcmp (iter->data, temp)) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found)
|
|
|
|
|
cname = temp;
|
|
|
|
|
else
|
|
|
|
|
g_free (temp);
|
|
|
|
|
}
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
g_slist_free (names);
|
|
|
|
|
return cname;
|
2015-07-24 18:54:13 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static char *
|
2016-03-08 13:57:20 +01:00
|
|
|
get_new_connection_ifname (NMPlatform *platform,
|
|
|
|
|
const GSList *existing,
|
2016-03-01 09:56:51 +01:00
|
|
|
const char *prefix)
|
2015-07-24 18:54:13 +02:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
int i;
|
|
|
|
|
char *name;
|
|
|
|
|
const GSList *iter;
|
|
|
|
|
gboolean found;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 500; i++) {
|
|
|
|
|
name = g_strdup_printf ("%s%d", prefix, i);
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-08 13:57:20 +01:00
|
|
|
if (nm_platform_link_get_by_ifname (platform, name))
|
2016-03-01 09:56:51 +01:00
|
|
|
goto next;
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
for (iter = existing, found = FALSE; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
NMConnection *candidate = iter->data;
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (g_strcmp0 (nm_connection_get_interface_name (candidate), name) == 0) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!found)
|
|
|
|
|
return name;
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
next:
|
|
|
|
|
g_free (name);
|
2015-07-24 18:54:13 +02:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
|
|
|
|
|
return NULL;
|
2015-07-24 18:54:13 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
const char *
|
|
|
|
|
nm_utils_get_ip_config_method (NMConnection *connection,
|
|
|
|
|
GType ip_setting_type)
|
2015-07-24 18:54:13 +02:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingIPConfig *s_ip4, *s_ip6;
|
|
|
|
|
const char *method;
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (ip_setting_type == NM_TYPE_SETTING_IP4_CONFIG) {
|
|
|
|
|
g_return_val_if_fail (s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
2015-07-24 18:54:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (nm_setting_connection_get_master (s_con))
|
|
|
|
|
return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
|
|
|
else {
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
if (!s_ip4)
|
|
|
|
|
return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
|
|
|
method = nm_setting_ip_config_get_method (s_ip4);
|
|
|
|
|
g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
2015-10-01 13:01:39 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
return method;
|
|
|
|
|
}
|
2015-10-01 13:01:39 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
} else if (ip_setting_type == NM_TYPE_SETTING_IP6_CONFIG) {
|
|
|
|
|
g_return_val_if_fail (s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
2015-10-01 13:01:39 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (nm_setting_connection_get_master (s_con))
|
|
|
|
|
return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
|
|
|
|
else {
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
if (!s_ip6)
|
|
|
|
|
return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
|
|
|
|
method = nm_setting_ip_config_get_method (s_ip6);
|
|
|
|
|
g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
2015-10-01 13:01:39 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
return method;
|
|
|
|
|
}
|
2015-10-01 13:01:39 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
} else
|
|
|
|
|
g_assert_not_reached ();
|
2015-10-01 13:01:39 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
void
|
2016-03-08 13:57:20 +01:00
|
|
|
nm_utils_complete_generic (NMPlatform *platform,
|
|
|
|
|
NMConnection *connection,
|
2016-03-01 09:56:51 +01:00
|
|
|
const char *ctype,
|
|
|
|
|
const GSList *existing,
|
|
|
|
|
const char *preferred_id,
|
|
|
|
|
const char *fallback_id_prefix,
|
|
|
|
|
const char *ifname_prefix,
|
|
|
|
|
gboolean default_enable_ipv6)
|
2004-07-06 01:34:10 +00:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
char *id, *uuid, *ifname;
|
|
|
|
|
GHashTable *parameters;
|
2004-07-06 01:34:10 +00:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
g_assert (fallback_id_prefix);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
if (!s_con) {
|
|
|
|
|
s_con = (NMSettingConnection *) nm_setting_connection_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_con));
|
2015-04-23 12:51:01 +02:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_TYPE, ctype, NULL);
|
2007-11-15 18:33:17 +00:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!nm_setting_connection_get_uuid (s_con)) {
|
|
|
|
|
uuid = nm_utils_uuid_generate ();
|
|
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_UUID, uuid, NULL);
|
|
|
|
|
g_free (uuid);
|
|
|
|
|
}
|
2007-11-15 18:33:17 +00:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Add a connection ID if absent */
|
|
|
|
|
if (!nm_setting_connection_get_id (s_con)) {
|
|
|
|
|
id = get_new_connection_name (existing, preferred_id, fallback_id_prefix);
|
|
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_ID, id, NULL);
|
|
|
|
|
g_free (id);
|
|
|
|
|
}
|
2007-11-15 18:33:17 +00:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Add an interface name, if requested */
|
|
|
|
|
if (ifname_prefix && !nm_setting_connection_get_interface_name (s_con)) {
|
2016-03-08 13:57:20 +01:00
|
|
|
ifname = get_new_connection_ifname (platform, existing, ifname_prefix);
|
2016-03-01 09:56:51 +01:00
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NULL);
|
|
|
|
|
g_free (ifname);
|
2015-04-23 12:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Normalize */
|
|
|
|
|
parameters = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
|
g_hash_table_insert (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD,
|
|
|
|
|
default_enable_ipv6 ? NM_SETTING_IP6_CONFIG_METHOD_AUTO : NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
|
|
|
|
|
nm_connection_normalize (connection, parameters, NULL, NULL);
|
|
|
|
|
g_hash_table_destroy (parameters);
|
2004-07-06 01:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/*****************************************************************************/
|
2004-06-24 14:18:37 +00:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static GHashTable *
|
|
|
|
|
check_property_in_hash (GHashTable *hash,
|
|
|
|
|
const char *s_name,
|
|
|
|
|
const char *p_name)
|
2014-02-13 18:12:41 +01:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
GHashTable *props;
|
2014-08-28 23:36:45 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
props = g_hash_table_lookup (hash, s_name);
|
|
|
|
|
if ( !props
|
|
|
|
|
|| !g_hash_table_lookup (props, p_name)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return props;
|
2014-02-13 18:12:41 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static void
|
|
|
|
|
remove_from_hash (GHashTable *s_hash,
|
|
|
|
|
GHashTable *p_hash,
|
|
|
|
|
const char *s_name,
|
|
|
|
|
const char *p_name)
|
2015-03-27 11:55:51 +01:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!p_hash)
|
2015-03-27 11:55:51 +01:00
|
|
|
return;
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
g_hash_table_remove (p_hash, p_name);
|
|
|
|
|
if (g_hash_table_size (p_hash) == 0)
|
|
|
|
|
g_hash_table_remove (s_hash, s_name);
|
|
|
|
|
}
|
2015-03-27 11:55:51 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static gboolean
|
|
|
|
|
check_ip6_method (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings)
|
|
|
|
|
{
|
|
|
|
|
GHashTable *props;
|
|
|
|
|
const char *orig_ip6_method, *candidate_ip6_method;
|
|
|
|
|
NMSettingIPConfig *candidate_ip6;
|
|
|
|
|
gboolean allow = FALSE;
|
2015-03-27 11:55:51 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
props = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD);
|
|
|
|
|
if (!props)
|
|
|
|
|
return TRUE;
|
2015-03-27 11:55:51 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* If the generated connection is 'link-local' and the candidate is both 'auto'
|
|
|
|
|
* and may-fail=TRUE, then the candidate is OK to use. may-fail is included
|
|
|
|
|
* in the decision because if the candidate is 'auto' but may-fail=FALSE, then
|
|
|
|
|
* the connection could not possibly have been previously activated on the
|
|
|
|
|
* device if the device has no non-link-local IPv6 address.
|
|
|
|
|
*/
|
|
|
|
|
orig_ip6_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
candidate_ip6_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
candidate_ip6 = nm_connection_get_setting_ip6_config (candidate);
|
2015-03-27 11:55:51 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if ( strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0
|
|
|
|
|
&& strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
|
|
|
|
&& (!candidate_ip6 || nm_setting_ip_config_get_may_fail (candidate_ip6))) {
|
|
|
|
|
allow = TRUE;
|
2015-03-27 11:55:51 +01:00
|
|
|
}
|
2014-02-13 18:12:41 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* If the generated connection method is 'link-local' or 'auto' and the candidate
|
|
|
|
|
* method is 'ignore' we can take the connection, because NM didn't simply take care
|
|
|
|
|
* of IPv6.
|
|
|
|
|
*/
|
|
|
|
|
if ( ( strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0
|
|
|
|
|
|| strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0)
|
|
|
|
|
&& strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
|
|
|
|
|
allow = TRUE;
|
2008-04-27 12:23:17 +00:00
|
|
|
}
|
2004-10-28 19:49:55 +00:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (allow) {
|
|
|
|
|
remove_from_hash (settings, props,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD);
|
2008-04-27 12:23:17 +00:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
return allow;
|
2015-01-09 11:25:06 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static int
|
|
|
|
|
route_compare (NMIPRoute *route1, NMIPRoute *route2, gint64 default_metric)
|
2014-10-01 15:01:13 +02:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
gint64 r, metric1, metric2;
|
2015-06-30 14:51:42 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
r = g_strcmp0 (nm_ip_route_get_dest (route1), nm_ip_route_get_dest (route2));
|
|
|
|
|
if (r)
|
|
|
|
|
return r;
|
2014-10-01 15:01:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
r = nm_ip_route_get_prefix (route1) - nm_ip_route_get_prefix (route2);
|
|
|
|
|
if (r)
|
|
|
|
|
return r > 0 ? 1 : -1;
|
2015-06-30 12:28:29 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
r = g_strcmp0 (nm_ip_route_get_next_hop (route1), nm_ip_route_get_next_hop (route2));
|
|
|
|
|
if (r)
|
|
|
|
|
return r;
|
2014-10-01 15:01:13 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
metric1 = nm_ip_route_get_metric (route1) == -1 ? default_metric : nm_ip_route_get_metric (route1);
|
|
|
|
|
metric2 = nm_ip_route_get_metric (route2) == -1 ? default_metric : nm_ip_route_get_metric (route2);
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
r = metric1 - metric2;
|
|
|
|
|
if (r)
|
|
|
|
|
return r > 0 ? 1 : -1;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
r = nm_ip_route_get_family (route1) - nm_ip_route_get_family (route2);
|
|
|
|
|
if (r)
|
|
|
|
|
return r > 0 ? 1 : -1;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
return 0;
|
2014-02-14 12:54:36 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static int
|
|
|
|
|
route_ptr_compare (const void *a, const void *b)
|
2014-02-14 12:54:36 +01:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
return route_compare (*(NMIPRoute **) a, *(NMIPRoute **) b, -1);
|
2014-02-14 12:54:36 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static gboolean
|
|
|
|
|
check_ip_routes (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings,
|
|
|
|
|
gint64 default_metric,
|
|
|
|
|
gboolean v4)
|
2014-02-14 12:54:36 +01:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
gs_free NMIPRoute **routes1 = NULL, **routes2 = NULL;
|
|
|
|
|
NMSettingIPConfig *s_ip1, *s_ip2;
|
|
|
|
|
const char *s_name;
|
|
|
|
|
GHashTable *props;
|
|
|
|
|
guint i, num;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
s_name = v4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME :
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
props = check_property_in_hash (settings,
|
|
|
|
|
s_name,
|
|
|
|
|
NM_SETTING_IP_CONFIG_ROUTES);
|
|
|
|
|
if (!props)
|
|
|
|
|
return TRUE;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
s_ip1 = (NMSettingIPConfig *) nm_connection_get_setting_by_name (orig, s_name);
|
|
|
|
|
s_ip2 = (NMSettingIPConfig *) nm_connection_get_setting_by_name (candidate, s_name);
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!s_ip1 || !s_ip2)
|
|
|
|
|
return FALSE;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
num = nm_setting_ip_config_get_num_routes (s_ip1);
|
|
|
|
|
if (num != nm_setting_ip_config_get_num_routes (s_ip2))
|
|
|
|
|
return FALSE;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
routes1 = g_new (NMIPRoute *, num);
|
|
|
|
|
routes2 = g_new (NMIPRoute *, num);
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
|
routes1[i] = nm_setting_ip_config_get_route (s_ip1, i);
|
|
|
|
|
routes2[i] = nm_setting_ip_config_get_route (s_ip2, i);
|
|
|
|
|
}
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
qsort (routes1, num, sizeof (NMIPRoute *), route_ptr_compare);
|
|
|
|
|
qsort (routes2, num, sizeof (NMIPRoute *), route_ptr_compare);
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
|
if (route_compare (routes1[i], routes2[i], default_metric))
|
|
|
|
|
return FALSE;
|
2014-02-14 12:54:36 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
remove_from_hash (settings, props, s_name, NM_SETTING_IP_CONFIG_ROUTES);
|
|
|
|
|
return TRUE;
|
2014-02-14 12:54:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2016-03-01 09:56:51 +01:00
|
|
|
check_ip4_method (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings,
|
|
|
|
|
gboolean device_has_carrier)
|
2014-02-14 12:54:36 +01:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
GHashTable *props;
|
|
|
|
|
const char *orig_ip4_method, *candidate_ip4_method;
|
|
|
|
|
NMSettingIPConfig *candidate_ip4;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
props = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD);
|
|
|
|
|
if (!props)
|
|
|
|
|
return TRUE;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* If the generated connection is 'disabled' (device had no IP addresses)
|
|
|
|
|
* but it has no carrier, that most likely means that IP addressing could
|
|
|
|
|
* not complete and thus no IP addresses were assigned. In that case, allow
|
|
|
|
|
* matching to the "auto" method.
|
|
|
|
|
*/
|
|
|
|
|
orig_ip4_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
candidate_ip4_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
candidate_ip4 = nm_connection_get_setting_ip4_config (candidate);
|
2014-12-04 18:05:24 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if ( strcmp (orig_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0
|
|
|
|
|
&& strcmp (candidate_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0
|
|
|
|
|
&& (!candidate_ip4 || nm_setting_ip_config_get_may_fail (candidate_ip4))
|
|
|
|
|
&& (device_has_carrier == FALSE)) {
|
|
|
|
|
remove_from_hash (settings, props,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD);
|
|
|
|
|
return TRUE;
|
2014-12-04 18:05:24 +01:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
return FALSE;
|
2014-12-04 18:05:24 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static gboolean
|
|
|
|
|
check_connection_interface_name (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings)
|
2014-02-14 12:54:36 +01:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
GHashTable *props;
|
|
|
|
|
const char *orig_ifname, *cand_ifname;
|
|
|
|
|
NMSettingConnection *s_con_orig, *s_con_cand;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
props = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME);
|
|
|
|
|
if (!props)
|
|
|
|
|
return TRUE;
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* If one of the interface names is NULL, we accept that connection */
|
|
|
|
|
s_con_orig = nm_connection_get_setting_connection (orig);
|
|
|
|
|
s_con_cand = nm_connection_get_setting_connection (candidate);
|
|
|
|
|
orig_ifname = nm_setting_connection_get_interface_name (s_con_orig);
|
|
|
|
|
cand_ifname = nm_setting_connection_get_interface_name (s_con_cand);
|
2014-02-14 12:54:36 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!orig_ifname || !cand_ifname) {
|
|
|
|
|
remove_from_hash (settings, props,
|
|
|
|
|
NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME);
|
|
|
|
|
return TRUE;
|
2014-02-14 12:54:36 +01:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
return FALSE;
|
2014-02-14 12:54:36 +01:00
|
|
|
}
|
2014-10-01 16:15:52 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static gboolean
|
|
|
|
|
check_connection_mac_address (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings)
|
2014-10-01 16:15:52 +02:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
GHashTable *props;
|
|
|
|
|
const char *orig_mac = NULL, *cand_mac = NULL;
|
|
|
|
|
NMSettingWired *s_wired_orig, *s_wired_cand;
|
2014-03-04 17:01:10 -05:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
props = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_MAC_ADDRESS);
|
|
|
|
|
if (!props)
|
|
|
|
|
return TRUE;
|
2014-03-12 12:06:20 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* If one of the MAC addresses is NULL, we accept that connection */
|
|
|
|
|
s_wired_orig = nm_connection_get_setting_wired (orig);
|
|
|
|
|
if (s_wired_orig)
|
|
|
|
|
orig_mac = nm_setting_wired_get_mac_address (s_wired_orig);
|
2014-03-12 12:06:20 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
s_wired_cand = nm_connection_get_setting_wired (candidate);
|
|
|
|
|
if (s_wired_cand)
|
|
|
|
|
cand_mac = nm_setting_wired_get_mac_address (s_wired_cand);
|
2014-03-12 12:06:20 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!orig_mac || !cand_mac) {
|
|
|
|
|
remove_from_hash (settings, props,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_MAC_ADDRESS);
|
|
|
|
|
return TRUE;
|
2014-03-12 12:06:20 +01:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
return FALSE;
|
2015-08-06 17:06:42 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static gboolean
|
|
|
|
|
check_connection_cloned_mac_address (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings)
|
2015-08-06 17:06:42 +02:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
GHashTable *props;
|
|
|
|
|
const char *orig_mac = NULL, *cand_mac = NULL;
|
|
|
|
|
NMSettingWired *s_wired_orig, *s_wired_cand;
|
2014-03-12 12:06:20 +01:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
props = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
|
|
|
|
|
if (!props)
|
2014-06-30 13:55:04 +02:00
|
|
|
return TRUE;
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* If one of the MAC addresses is NULL, we accept that connection */
|
|
|
|
|
s_wired_orig = nm_connection_get_setting_wired (orig);
|
|
|
|
|
if (s_wired_orig)
|
|
|
|
|
orig_mac = nm_setting_wired_get_cloned_mac_address (s_wired_orig);
|
2014-04-10 15:29:45 -05:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
s_wired_cand = nm_connection_get_setting_wired (candidate);
|
|
|
|
|
if (s_wired_cand)
|
|
|
|
|
cand_mac = nm_setting_wired_get_cloned_mac_address (s_wired_cand);
|
2014-04-10 15:29:45 -05:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!orig_mac || !cand_mac) {
|
|
|
|
|
remove_from_hash (settings, props,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
|
|
|
|
|
return TRUE;
|
2014-04-10 15:29:45 -05:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
return FALSE;
|
2014-04-10 15:29:45 -05:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static gboolean
|
|
|
|
|
check_connection_s390_props (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings)
|
2014-04-10 15:29:45 -05:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
GHashTable *props1, *props2, *props3;
|
|
|
|
|
NMSettingWired *s_wired_orig, *s_wired_cand;
|
|
|
|
|
|
|
|
|
|
props1 = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_S390_SUBCHANNELS);
|
|
|
|
|
props2 = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_S390_NETTYPE);
|
|
|
|
|
props3 = check_property_in_hash (settings,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_S390_OPTIONS);
|
|
|
|
|
if (!props1 && !props2 && !props3)
|
2014-04-10 15:29:45 -05:00
|
|
|
return TRUE;
|
2016-03-01 09:56:51 +01:00
|
|
|
|
|
|
|
|
/* If the generated connection did not contain wired setting,
|
|
|
|
|
* allow it to match to a connection with a wired setting,
|
|
|
|
|
* but default (empty) s390-* properties */
|
|
|
|
|
s_wired_orig = nm_connection_get_setting_wired (orig);
|
|
|
|
|
s_wired_cand = nm_connection_get_setting_wired (candidate);
|
|
|
|
|
if (!s_wired_orig && s_wired_cand) {
|
|
|
|
|
const char * const *subchans = nm_setting_wired_get_s390_subchannels (s_wired_cand);
|
|
|
|
|
const char *nettype = nm_setting_wired_get_s390_nettype (s_wired_cand);
|
|
|
|
|
guint32 num_options = nm_setting_wired_get_num_s390_options (s_wired_cand);
|
|
|
|
|
|
|
|
|
|
if ((!subchans || !*subchans) && !nettype && num_options == 0) {
|
|
|
|
|
remove_from_hash (settings, props1,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_S390_SUBCHANNELS);
|
|
|
|
|
remove_from_hash (settings, props2,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_S390_NETTYPE);
|
|
|
|
|
remove_from_hash (settings, props3,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_S390_OPTIONS);
|
2014-04-10 15:29:45 -05:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
static NMConnection *
|
|
|
|
|
check_possible_match (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings,
|
|
|
|
|
gboolean device_has_carrier,
|
|
|
|
|
gint64 default_v4_metric,
|
|
|
|
|
gint64 default_v6_metric)
|
2014-04-10 15:29:45 -05:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
g_return_val_if_fail (settings != NULL, NULL);
|
2014-04-10 15:29:45 -05:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!check_ip6_method (orig, candidate, settings))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (!check_ip4_method (orig, candidate, settings, device_has_carrier))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (!check_ip_routes (orig, candidate, settings, default_v4_metric, TRUE))
|
|
|
|
|
return NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!check_ip_routes (orig, candidate, settings, default_v6_metric, FALSE))
|
|
|
|
|
return NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!check_connection_interface_name (orig, candidate, settings))
|
|
|
|
|
return NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!check_connection_mac_address (orig, candidate, settings))
|
|
|
|
|
return NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!check_connection_cloned_mac_address (orig, candidate, settings))
|
|
|
|
|
return NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!check_connection_s390_props (orig, candidate, settings))
|
|
|
|
|
return NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (g_hash_table_size (settings) == 0)
|
|
|
|
|
return candidate;
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-03-01 09:56:51 +01:00
|
|
|
* nm_utils_match_connection:
|
|
|
|
|
* @connections: a (optionally pre-sorted) list of connections from which to
|
|
|
|
|
* find a matching connection to @original based on "inferrable" properties
|
|
|
|
|
* @original: the #NMConnection to find a match for from @connections
|
|
|
|
|
* @device_has_carrier: pass %TRUE if the device that generated @original has
|
|
|
|
|
* a carrier, %FALSE if not
|
|
|
|
|
* @match_filter_func: a function to check whether each connection from @connections
|
|
|
|
|
* should be considered for matching. This function should return %TRUE if the
|
|
|
|
|
* connection should be considered, %FALSE if the connection should be ignored
|
|
|
|
|
* @match_compat_data: data pointer passed to @match_filter_func
|
2015-10-03 19:44:27 +02:00
|
|
|
*
|
2016-03-01 09:56:51 +01:00
|
|
|
* Checks each connection from @connections until a matching connection is found
|
|
|
|
|
* considering only setting properties marked with %NM_SETTING_PARAM_INFERRABLE
|
|
|
|
|
* and checking a few other characteristics like IPv6 method. If the caller
|
|
|
|
|
* desires some priority order of the connections, @connections should be
|
|
|
|
|
* sorted before calling this function.
|
2015-10-03 19:44:27 +02:00
|
|
|
*
|
2016-03-01 09:56:51 +01:00
|
|
|
* Returns: the best #NMConnection matching @original, or %NULL if no connection
|
|
|
|
|
* matches well enough.
|
2015-10-03 19:44:27 +02:00
|
|
|
*/
|
2016-03-01 09:56:51 +01:00
|
|
|
NMConnection *
|
|
|
|
|
nm_utils_match_connection (GSList *connections,
|
|
|
|
|
NMConnection *original,
|
|
|
|
|
gboolean device_has_carrier,
|
|
|
|
|
gint64 default_v4_metric,
|
|
|
|
|
gint64 default_v6_metric,
|
|
|
|
|
NMUtilsMatchFilterFunc match_filter_func,
|
|
|
|
|
gpointer match_filter_data)
|
2015-10-03 19:44:27 +02:00
|
|
|
{
|
2016-03-01 09:56:51 +01:00
|
|
|
NMConnection *best_match = NULL;
|
|
|
|
|
GSList *iter;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
for (iter = connections; iter; iter = iter->next) {
|
|
|
|
|
NMConnection *candidate = NM_CONNECTION (iter->data);
|
|
|
|
|
GHashTable *diffs = NULL;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (match_filter_func) {
|
|
|
|
|
if (!match_filter_func (candidate, match_filter_data))
|
|
|
|
|
continue;
|
2015-10-03 19:44:27 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
if (!nm_connection_diff (original, candidate, NM_SETTING_COMPARE_FLAG_INFERRABLE, &diffs)) {
|
|
|
|
|
if (!best_match) {
|
|
|
|
|
best_match = check_possible_match (original, candidate, diffs, device_has_carrier,
|
|
|
|
|
default_v4_metric, default_v6_metric);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!best_match && nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) {
|
|
|
|
|
GString *diff_string;
|
|
|
|
|
GHashTableIter s_iter, p_iter;
|
|
|
|
|
gpointer setting_name, setting;
|
|
|
|
|
gpointer property_name, value;
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
diff_string = g_string_new (NULL);
|
|
|
|
|
g_hash_table_iter_init (&s_iter, diffs);
|
|
|
|
|
while (g_hash_table_iter_next (&s_iter, &setting_name, &setting)) {
|
|
|
|
|
g_hash_table_iter_init (&p_iter, setting);
|
|
|
|
|
while (g_hash_table_iter_next (&p_iter, &property_name, &value)) {
|
|
|
|
|
if (diff_string->len)
|
|
|
|
|
g_string_append (diff_string, ", ");
|
|
|
|
|
g_string_append_printf (diff_string, "%s.%s",
|
|
|
|
|
(char *) setting_name,
|
|
|
|
|
(char *) property_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-03 19:44:27 +02:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
nm_log_dbg (LOGD_CORE, "Connection '%s' differs from candidate '%s' in %s",
|
|
|
|
|
nm_connection_get_id (original),
|
|
|
|
|
nm_connection_get_id (candidate),
|
|
|
|
|
diff_string->str);
|
|
|
|
|
g_string_free (diff_string, TRUE);
|
2015-10-03 19:44:27 +02:00
|
|
|
}
|
2016-03-01 09:56:51 +01:00
|
|
|
|
|
|
|
|
g_hash_table_unref (diffs);
|
|
|
|
|
continue;
|
2015-10-03 19:44:27 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Exact match */
|
|
|
|
|
return candidate;
|
2015-10-03 19:44:27 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/* Best match (if any) */
|
|
|
|
|
return best_match;
|
2015-10-03 19:44:27 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/******************************************************************************/
|
2015-04-03 10:08:52 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_g_value_set_object_path:
|
|
|
|
|
* @value: a #GValue, initialized to store an object path
|
|
|
|
|
* @object: (allow-none): an #NMExportedObject
|
|
|
|
|
*
|
|
|
|
|
* Sets @value to @object's object path. If @object is %NULL, or not
|
|
|
|
|
* exported, @value is set to "/".
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_utils_g_value_set_object_path (GValue *value, gpointer object)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (!object || NM_IS_EXPORTED_OBJECT (object));
|
|
|
|
|
|
|
|
|
|
if (object && nm_exported_object_is_exported (object))
|
2015-04-16 12:34:55 -04:00
|
|
|
g_value_set_string (value, nm_exported_object_get_path (object));
|
2015-04-03 10:08:52 -04:00
|
|
|
else
|
2015-04-16 12:34:55 -04:00
|
|
|
g_value_set_string (value, "/");
|
2015-04-03 10:08:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_g_value_set_object_path_array:
|
|
|
|
|
* @value: a #GValue, initialized to store an object path
|
|
|
|
|
* @objects: a #GSList of #NMExportedObjects
|
2015-08-06 10:29:29 +02:00
|
|
|
* @filter_func: (allow-none): function to call on each object in @objects
|
|
|
|
|
* @user_data: data to pass to @filter_func
|
2015-04-03 10:08:52 -04:00
|
|
|
*
|
|
|
|
|
* Sets @value to an array of object paths of the objects in @objects.
|
|
|
|
|
*/
|
|
|
|
|
void
|
2015-08-06 10:29:29 +02:00
|
|
|
nm_utils_g_value_set_object_path_array (GValue *value,
|
|
|
|
|
GSList *objects,
|
|
|
|
|
NMUtilsObjectFunc filter_func,
|
|
|
|
|
gpointer user_data)
|
2015-04-03 10:08:52 -04:00
|
|
|
{
|
2015-08-18 15:12:43 +02:00
|
|
|
char **paths;
|
|
|
|
|
guint i;
|
2015-04-03 10:08:52 -04:00
|
|
|
GSList *iter;
|
|
|
|
|
|
2015-08-18 15:12:43 +02:00
|
|
|
paths = g_new (char *, g_slist_length (objects) + 1);
|
|
|
|
|
for (i = 0, iter = objects; iter; iter = iter->next) {
|
2015-04-03 10:08:52 -04:00
|
|
|
NMExportedObject *object = iter->data;
|
2015-12-04 13:12:04 +01:00
|
|
|
const char *path;
|
2015-04-03 10:08:52 -04:00
|
|
|
|
2015-12-04 13:12:04 +01:00
|
|
|
path = nm_exported_object_get_path (object);
|
|
|
|
|
if (!path)
|
2015-04-03 10:08:52 -04:00
|
|
|
continue;
|
2015-08-18 15:12:43 +02:00
|
|
|
if (filter_func && !filter_func ((GObject *) object, user_data))
|
2015-08-06 10:29:29 +02:00
|
|
|
continue;
|
2015-12-04 13:12:04 +01:00
|
|
|
paths[i++] = g_strdup (path);
|
2015-04-03 10:08:52 -04:00
|
|
|
}
|
2015-08-18 15:12:43 +02:00
|
|
|
paths[i] = NULL;
|
|
|
|
|
g_value_take_boxed (value, paths);
|
2015-04-03 10:08:52 -04:00
|
|
|
}
|
2015-04-15 14:53:30 -04:00
|
|
|
|
2016-03-01 09:56:51 +01:00
|
|
|
/******************************************************************************/
|