mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-21 10:14:41 +00:00
merge: branch 'th/devcon-track-autoconnect'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1530
This commit is contained in:
commit
61c0971748
|
@ -1860,3 +1860,13 @@ nm_linux_platform_setup_with_tc_cache(void)
|
|||
{
|
||||
nm_platform_setup(nm_linux_platform_new(NULL, FALSE, FALSE, TRUE));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NM_UTILS_FLAGS2STR_DEFINE(
|
||||
nm_settings_autoconnect_blocked_reason_to_string,
|
||||
NMSettingsAutoconnectBlockedReason,
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NONE, "none"),
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST, "user-request"),
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED, "failed"),
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NO_SECRETS, "no-secrets"), );
|
||||
|
|
|
@ -228,6 +228,26 @@ void nm_utils_ip_routes_to_dbus(int addr_family,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum _nm_packed {
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NONE = 0,
|
||||
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST = (1LL << 0),
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED = (1LL << 1),
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NO_SECRETS = (1LL << 2),
|
||||
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_ALL =
|
||||
(NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST
|
||||
| NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED
|
||||
| NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NO_SECRETS),
|
||||
} NMSettingsAutoconnectBlockedReason;
|
||||
|
||||
const char *
|
||||
nm_settings_autoconnect_blocked_reason_to_string(NMSettingsAutoconnectBlockedReason reason,
|
||||
char *buf,
|
||||
gsize len);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* For now, all we track about a DHCP lease is the GHashTable with
|
||||
* the options.
|
||||
*
|
||||
|
|
|
@ -29,10 +29,6 @@ enum NMActStageReturn {
|
|||
|
||||
#define NM_DEVICE_CAP_INTERNAL_MASK 0xc0000000
|
||||
|
||||
NMSettings *nm_device_get_settings(NMDevice *self);
|
||||
|
||||
NMManager *nm_device_get_manager(NMDevice *self);
|
||||
|
||||
gboolean nm_device_set_ip_ifindex(NMDevice *self, int ifindex);
|
||||
|
||||
gboolean nm_device_set_ip_iface(NMDevice *self, const char *iface);
|
||||
|
|
|
@ -17729,6 +17729,7 @@ nm_device_init(NMDevice *self)
|
|||
|
||||
c_list_init(&priv->concheck_lst_head);
|
||||
c_list_init(&self->devices_lst);
|
||||
c_list_init(&self->devcon_dev_lst_head);
|
||||
c_list_init(&priv->slaves);
|
||||
|
||||
priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE;
|
||||
|
@ -17849,6 +17850,7 @@ dispose(GObject *object)
|
|||
_LOGD(LOGD_DEVICE, "disposing");
|
||||
|
||||
nm_assert(c_list_is_empty(&self->devices_lst));
|
||||
nm_assert(c_list_is_empty(&self->devcon_dev_lst_head));
|
||||
|
||||
while ((con_handle = c_list_first_entry(&priv->concheck_lst_head,
|
||||
NMDeviceConnectivityHandle,
|
||||
|
|
|
@ -144,6 +144,7 @@ struct _NMDevice {
|
|||
NMDBusObject parent;
|
||||
struct _NMDevicePrivate *_priv;
|
||||
CList devices_lst;
|
||||
CList devcon_dev_lst_head;
|
||||
};
|
||||
|
||||
/* The flags have an relaxing meaning, that means, specifying more flags, can make
|
||||
|
@ -421,6 +422,10 @@ typedef struct _NMDeviceClass {
|
|||
const char *(*get_dhcp_anycast_address)(NMDevice *self);
|
||||
} NMDeviceClass;
|
||||
|
||||
NMSettings *nm_device_get_settings(NMDevice *self);
|
||||
|
||||
NMManager *nm_device_get_manager(NMDevice *self);
|
||||
|
||||
GType nm_device_get_type(void);
|
||||
|
||||
struct _NMDedupMultiIndex *nm_device_get_multi_index(NMDevice *self);
|
||||
|
|
|
@ -240,9 +240,11 @@ ovsdb_interface_failed(NMOvsdb *ovsdb,
|
|||
return;
|
||||
|
||||
if (connection) {
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
nm_device_get_manager(device),
|
||||
device,
|
||||
connection,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
|
|
|
@ -2302,9 +2302,10 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
|||
* to reset the retry count so we set no timeout.
|
||||
*/
|
||||
if (priv->iwd_autoconnect) {
|
||||
NMSettingsConnection *sett_conn = nm_act_request_get_settings_connection(req);
|
||||
|
||||
nm_settings_connection_autoconnect_retries_set(sett_conn, 0);
|
||||
nm_manager_devcon_autoconnect_retries_set(nm_device_get_manager(device),
|
||||
device,
|
||||
nm_act_request_get_settings_connection(req),
|
||||
0);
|
||||
}
|
||||
|
||||
/* With priv->iwd_autoconnect, if we're assuming a connection because
|
||||
|
|
|
@ -69,6 +69,26 @@ typedef struct {
|
|||
bool os_owner : 1;
|
||||
} RfkillRadioState;
|
||||
|
||||
#define AUTOCONNECT_RESET_RETRIES_TIMER_SEC 300
|
||||
|
||||
typedef struct {
|
||||
NMDevice *device;
|
||||
NMSettingsConnection *sett_conn;
|
||||
CList dev_lst;
|
||||
CList con_lst;
|
||||
|
||||
/* Autoconnet retries needs to be tracked for each (device, connection)
|
||||
* tuple because when a connection is a multiconnect one, each valid device
|
||||
* must try to autoconnect the retries defined in the connection. */
|
||||
struct {
|
||||
guint32 retries;
|
||||
gint32 blocked_until_sec;
|
||||
NMSettingsAutoconnectBlockedReason blocked_reason;
|
||||
bool initialized : 1;
|
||||
} autoconnect;
|
||||
|
||||
} DevConData;
|
||||
|
||||
typedef enum {
|
||||
ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL,
|
||||
ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER,
|
||||
|
@ -173,6 +193,8 @@ typedef struct {
|
|||
} prop_filter;
|
||||
NMRfkillManager *rfkill_mgr;
|
||||
|
||||
GHashTable *devcon_data_dict;
|
||||
|
||||
CList link_cb_lst;
|
||||
|
||||
NMCheckpointManager *checkpoint_mgr;
|
||||
|
@ -415,6 +437,11 @@ static void _activation_auth_done(NMManager *self,
|
|||
|
||||
static void _rfkill_update(NMManager *self, NMRfkillType rtype);
|
||||
|
||||
static DevConData *_devcon_lookup_data(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
gboolean create);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NM_CACHED_QUARK_FCN("autoconnect-root", autoconnect_root_quark);
|
||||
|
@ -1212,6 +1239,415 @@ active_connection_get_by_path(NMManager *self, const char *path)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint32
|
||||
_autoconnect_retries_initial(NMSettingsConnection *sett_conn)
|
||||
{
|
||||
NMSettingConnection *s_con;
|
||||
int retries = -1;
|
||||
|
||||
s_con = nm_connection_get_setting_connection(nm_settings_connection_get_connection(sett_conn));
|
||||
if (s_con)
|
||||
retries = nm_setting_connection_get_autoconnect_retries(s_con);
|
||||
|
||||
if (retries == -1)
|
||||
retries = nm_config_data_get_autoconnect_retries_default(NM_CONFIG_GET_DATA);
|
||||
|
||||
nm_assert(retries >= 0 && ((guint) retries) <= ((guint) G_MAXINT32));
|
||||
|
||||
if (retries == 0)
|
||||
return NM_AUTOCONNECT_RETRIES_FOREVER;
|
||||
return (guint32) retries;
|
||||
}
|
||||
|
||||
static void
|
||||
_autoconnect_retries_set(NMManager *self, DevConData *data, guint32 retries, gboolean is_reset)
|
||||
{
|
||||
nm_assert(data);
|
||||
|
||||
if (data->autoconnect.retries != retries || !data->autoconnect.initialized) {
|
||||
_LOGT(LOGD_SETTINGS,
|
||||
"autoconnect: device[%p] (%s): retries set %d%s",
|
||||
data->device,
|
||||
nm_device_get_ip_iface(data->device),
|
||||
retries,
|
||||
is_reset ? " (reset)" : "");
|
||||
data->autoconnect.initialized = TRUE;
|
||||
data->autoconnect.retries = retries;
|
||||
}
|
||||
|
||||
if (retries != 0) {
|
||||
_LOGT(LOGD_SETTINGS,
|
||||
"autoconnect: device[%p] (%s): no longer block autoconnect (due to retry count) %s",
|
||||
data->device,
|
||||
nm_device_get_ip_iface(data->device),
|
||||
is_reset ? " (reset)" : "");
|
||||
data->autoconnect.blocked_until_sec = 0;
|
||||
} else {
|
||||
/* NOTE: the blocked time must be identical for all connections, otherwise
|
||||
* the tracking of resetting the retry count in NMPolicy needs adjustment
|
||||
* in _connection_autoconnect_retries_set() (as it would need to re-evaluate
|
||||
* the next-timeout every time a connection gets blocked). */
|
||||
data->autoconnect.blocked_until_sec =
|
||||
nm_utils_get_monotonic_timestamp_sec() + AUTOCONNECT_RESET_RETRIES_TIMER_SEC;
|
||||
_LOGT(LOGD_SETTINGS,
|
||||
"autoconnect: device[%p] (%s): block autoconnect due to retry count for %d seconds",
|
||||
data->device,
|
||||
nm_device_get_ip_iface(data->device),
|
||||
AUTOCONNECT_RESET_RETRIES_TIMER_SEC);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_manager_devcon_autoconnect_retries_get:
|
||||
* @self: the #NMManager
|
||||
* @device: the #NMDevice
|
||||
* @sett_conn: the #NMSettingsConnection
|
||||
*
|
||||
* Returns the number of autoconnect retries left for the (device, connection)
|
||||
* tuple. If the value is not yet set, initialize it with the value from the
|
||||
* connection or with the global default.
|
||||
*/
|
||||
guint32
|
||||
nm_manager_devcon_autoconnect_retries_get(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn)
|
||||
{
|
||||
DevConData *data;
|
||||
|
||||
nm_assert(NM_IS_MANAGER(self));
|
||||
nm_assert(NM_IS_DEVICE(device));
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
|
||||
nm_assert(self == nm_device_get_manager(device));
|
||||
nm_assert(self == nm_settings_connection_get_manager(sett_conn));
|
||||
|
||||
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
|
||||
|
||||
if (G_UNLIKELY(!data->autoconnect.initialized)) {
|
||||
_autoconnect_retries_set(self, data, _autoconnect_retries_initial(sett_conn), FALSE);
|
||||
}
|
||||
|
||||
return data->autoconnect.retries;
|
||||
}
|
||||
|
||||
void
|
||||
nm_manager_devcon_autoconnect_retries_set(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
guint32 retries)
|
||||
{
|
||||
_autoconnect_retries_set(self,
|
||||
_devcon_lookup_data(self, device, sett_conn, TRUE),
|
||||
retries,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
nm_manager_devcon_autoconnect_retries_reset(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn)
|
||||
{
|
||||
DevConData *data;
|
||||
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
|
||||
|
||||
if (device)
|
||||
_autoconnect_retries_set(self,
|
||||
_devcon_lookup_data(self, device, sett_conn, TRUE),
|
||||
_autoconnect_retries_initial(sett_conn),
|
||||
TRUE);
|
||||
else {
|
||||
c_list_for_each_entry (data, &sett_conn->devcon_con_lst_head, con_lst)
|
||||
_autoconnect_retries_set(self, data, _autoconnect_retries_initial(sett_conn), TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_manager_devcon_autoconnect_reset_reconnect_all:
|
||||
* @self: the #NMManager
|
||||
* @device: the #NMDevice
|
||||
* @sett_conn: the #NMSettingsConnection
|
||||
* @only_no_secrets: boolean to reset all reasons or only no secrets.
|
||||
*
|
||||
* Returns a boolean indicating if something changed or not when resetting the
|
||||
* blocked reasons. If a #NMDevice is present then we also reset the reasons
|
||||
* for the (device, connection) tuple.
|
||||
*/
|
||||
gboolean
|
||||
nm_manager_devcon_autoconnect_reset_reconnect_all(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
gboolean only_no_secrets)
|
||||
{
|
||||
gboolean changed = FALSE;
|
||||
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
|
||||
|
||||
if (only_no_secrets) {
|
||||
/* we only reset the no-secrets blocked flag. */
|
||||
if (nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NO_SECRETS,
|
||||
FALSE)) {
|
||||
/* maybe the connection is still blocked afterwards for other reasons
|
||||
* and in the larger picture nothing changed. Check if the connection
|
||||
* is still blocked or not. */
|
||||
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/* we reset the tries-count and any blocked-reason */
|
||||
nm_manager_devcon_autoconnect_retries_reset(self, NULL, sett_conn);
|
||||
|
||||
/* if there is a device and we changed the state, then something changed. */
|
||||
if (device
|
||||
&& nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
self,
|
||||
device,
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED
|
||||
| NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST,
|
||||
FALSE))
|
||||
changed = TRUE;
|
||||
|
||||
/* we remove all the blocked reason from the connection, if something
|
||||
* happened, then it means the status changed */
|
||||
if (nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NO_SECRETS
|
||||
| NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST,
|
||||
FALSE))
|
||||
changed = TRUE;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
gint32
|
||||
nm_manager_devcon_autoconnect_retries_blocked_until(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn)
|
||||
{
|
||||
DevConData *data;
|
||||
gint32 min_stamp;
|
||||
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
|
||||
|
||||
if (device) {
|
||||
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
|
||||
return data->autoconnect.blocked_until_sec;
|
||||
} else {
|
||||
min_stamp = 0;
|
||||
c_list_for_each_entry (data, &sett_conn->devcon_con_lst_head, con_lst) {
|
||||
gint32 condev_stamp = data->autoconnect.blocked_until_sec;
|
||||
if (condev_stamp == 0)
|
||||
continue;
|
||||
|
||||
if (min_stamp == 0 || min_stamp > condev_stamp)
|
||||
min_stamp = condev_stamp;
|
||||
}
|
||||
}
|
||||
|
||||
return min_stamp;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_manager_devcon_autoconnect_is_blocked(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn)
|
||||
{
|
||||
DevConData *data;
|
||||
|
||||
nm_assert(NM_IS_DEVICE(device));
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
|
||||
|
||||
if (nm_settings_connection_autoconnect_is_blocked(sett_conn))
|
||||
return TRUE;
|
||||
|
||||
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
|
||||
if (data->autoconnect.blocked_reason != NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NONE)
|
||||
return TRUE;
|
||||
|
||||
if (data->autoconnect.retries == 0 && data->autoconnect.initialized)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
NMSettingsAutoconnectBlockedReason value,
|
||||
gboolean set)
|
||||
{
|
||||
NMSettingsAutoconnectBlockedReason v;
|
||||
DevConData *data;
|
||||
gboolean changed = FALSE;
|
||||
char buf[100];
|
||||
|
||||
nm_assert(value);
|
||||
nm_assert(sett_conn);
|
||||
|
||||
if (device) {
|
||||
data = _devcon_lookup_data(self, device, sett_conn, TRUE);
|
||||
v = data->autoconnect.blocked_reason;
|
||||
v = NM_FLAGS_ASSIGN(v, value, set);
|
||||
|
||||
if (data->autoconnect.blocked_reason == v)
|
||||
return FALSE;
|
||||
|
||||
_LOGT(LOGD_SETTINGS,
|
||||
"autoconnect: blocked reason: %s for device %s",
|
||||
nm_settings_autoconnect_blocked_reason_to_string(v, buf, sizeof(buf)),
|
||||
nm_device_get_ip_iface(device));
|
||||
data->autoconnect.blocked_reason = v;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
c_list_for_each_entry (data, &sett_conn->devcon_con_lst_head, con_lst) {
|
||||
v = data->autoconnect.blocked_reason;
|
||||
v = NM_FLAGS_ASSIGN(v, value, set);
|
||||
|
||||
if (data->autoconnect.blocked_reason == v)
|
||||
continue;
|
||||
_LOGT(LOGD_SETTINGS,
|
||||
"autoconnect: blocked reason: %s for device %s",
|
||||
nm_settings_autoconnect_blocked_reason_to_string(v, buf, sizeof(buf)),
|
||||
nm_device_get_ip_iface(data->device));
|
||||
data->autoconnect.blocked_reason = v;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint
|
||||
_devcon_data_hash(gconstpointer ptr)
|
||||
{
|
||||
const DevConData *data = ptr;
|
||||
|
||||
nm_assert(NM_IS_DEVICE(data->device));
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(data->sett_conn));
|
||||
|
||||
return nm_hash_vals(1832112199u, data->device, data->sett_conn);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_devcon_data_equal(gconstpointer ptr_a, gconstpointer ptr_b)
|
||||
{
|
||||
const DevConData *data_a = ptr_a;
|
||||
const DevConData *data_b = ptr_b;
|
||||
|
||||
nm_assert(NM_IS_DEVICE(data_a->device));
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(data_a->sett_conn));
|
||||
nm_assert(NM_IS_DEVICE(data_b->device));
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(data_b->sett_conn));
|
||||
|
||||
return data_a->device == data_b->device && data_a->sett_conn == data_b->sett_conn;
|
||||
}
|
||||
|
||||
static DevConData *
|
||||
_devcon_lookup_data(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
gboolean create)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
DevConData *data;
|
||||
DevConData needle;
|
||||
|
||||
nm_assert(NM_IS_DEVICE(device));
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
|
||||
nm_assert(self == nm_device_get_manager(device));
|
||||
nm_assert(self == nm_settings_connection_get_manager(sett_conn));
|
||||
|
||||
needle.device = device;
|
||||
needle.sett_conn = sett_conn;
|
||||
|
||||
data = g_hash_table_lookup(priv->devcon_data_dict, &needle);
|
||||
|
||||
if (data)
|
||||
return data;
|
||||
if (!create)
|
||||
return NULL;
|
||||
|
||||
data = g_slice_new(DevConData);
|
||||
*data = (DevConData){
|
||||
.device = device,
|
||||
.sett_conn = sett_conn,
|
||||
.autoconnect =
|
||||
{
|
||||
.initialized = FALSE,
|
||||
},
|
||||
};
|
||||
c_list_link_tail(&device->devcon_dev_lst_head, &data->dev_lst);
|
||||
c_list_link_tail(&sett_conn->devcon_con_lst_head, &data->con_lst);
|
||||
|
||||
g_hash_table_add(priv->devcon_data_dict, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
_devcon_remove_data(NMManager *self, DevConData *data)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self);
|
||||
|
||||
nm_assert(data);
|
||||
nm_assert(NM_IS_DEVICE(data->device));
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(data->sett_conn));
|
||||
nm_assert(data == _devcon_lookup_data(self, data->device, data->sett_conn, FALSE));
|
||||
|
||||
c_list_unlink_stale(&data->dev_lst);
|
||||
c_list_unlink_stale(&data->con_lst);
|
||||
g_hash_table_remove(priv->devcon_data_dict, data);
|
||||
nm_g_slice_free(data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_devcon_remove_device_all(NMManager *self, NMDevice *device)
|
||||
{
|
||||
DevConData *data;
|
||||
gboolean changed;
|
||||
|
||||
nm_assert(NM_IS_DEVICE(device));
|
||||
|
||||
while ((data = c_list_first_entry(&device->devcon_dev_lst_head, DevConData, dev_lst))) {
|
||||
changed = TRUE;
|
||||
_devcon_remove_data(self, data);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_devcon_remove_sett_conn_all(NMManager *self, NMSettingsConnection *sett_conn)
|
||||
{
|
||||
DevConData *data;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(sett_conn));
|
||||
|
||||
while ((data = c_list_first_entry(&sett_conn->devcon_con_lst_head, DevConData, con_lst))) {
|
||||
changed = TRUE;
|
||||
_devcon_remove_data(self, data);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void
|
||||
nm_manager_notify_delete_settings_connections(NMManager *self, NMSettingsConnection *sett_conn)
|
||||
{
|
||||
_devcon_remove_sett_conn_all(self, sett_conn);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_config_changed_cb(NMConfig *config,
|
||||
NMConfigData *config_data,
|
||||
|
@ -1814,6 +2250,8 @@ remove_device(NMManager *self, NMDevice *device, gboolean quitting)
|
|||
|
||||
nm_settings_device_removed(priv->settings, device, quitting);
|
||||
|
||||
_devcon_remove_device_all(self, device);
|
||||
|
||||
c_list_unlink(&device->devices_lst);
|
||||
|
||||
_parent_notify_changed(self, device, TRUE);
|
||||
|
@ -5159,7 +5597,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError **
|
|||
if (nm_active_connection_get_activation_reason(active)
|
||||
== NM_ACTIVATION_REASON_AUTOCONNECT
|
||||
&& NM_FLAGS_HAS(nm_settings_connection_autoconnect_blocked_reason_get(parent_con),
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST)) {
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST)) {
|
||||
g_set_error(error,
|
||||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_DEPENDENCY_FAILED,
|
||||
|
@ -5790,7 +6228,7 @@ _activation_auth_done(NMManager *self,
|
|||
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
connection,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST,
|
||||
FALSE);
|
||||
g_dbus_method_invocation_return_value(
|
||||
invocation,
|
||||
|
@ -8114,6 +8552,8 @@ nm_manager_init(NMManager *self)
|
|||
priv->state = NM_STATE_DISCONNECTED;
|
||||
priv->startup = TRUE;
|
||||
|
||||
priv->devcon_data_dict = g_hash_table_new(_devcon_data_hash, _devcon_data_equal);
|
||||
|
||||
/* sleep/wake handling */
|
||||
priv->sleep_monitor = nm_sleep_monitor_new();
|
||||
g_signal_connect(priv->sleep_monitor, NM_SLEEP_MONITOR_SLEEPING, G_CALLBACK(sleeping_cb), self);
|
||||
|
@ -8447,6 +8887,8 @@ dispose(GObject *object)
|
|||
|
||||
nm_clear_pointer(&priv->device_route_metrics, g_hash_table_destroy);
|
||||
|
||||
nm_clear_pointer(&priv->devcon_data_dict, g_hash_table_destroy);
|
||||
|
||||
G_OBJECT_CLASS(nm_manager_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
|
|
|
@ -207,6 +207,11 @@ struct _NMDnsManager *nm_manager_get_dns_manager(NMManager *self);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nm_manager_notify_delete_settings_connections(NMManager *self,
|
||||
NMSettingsConnection *sett_conn);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nm_manager_device_auth_request(NMManager *self,
|
||||
NMDevice *device,
|
||||
GDBusMethodInvocation *context,
|
||||
|
@ -219,4 +224,40 @@ void nm_manager_device_auth_request(NMManager *self,
|
|||
|
||||
void nm_manager_unblock_failed_ovs_interfaces(NMManager *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define NM_AUTOCONNECT_RETRIES_FOREVER G_MAXUINT32
|
||||
|
||||
guint32 nm_manager_devcon_autoconnect_retries_get(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn);
|
||||
|
||||
void nm_manager_devcon_autoconnect_retries_set(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
guint32 retries);
|
||||
|
||||
void nm_manager_devcon_autoconnect_retries_reset(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn);
|
||||
|
||||
gboolean nm_manager_devcon_autoconnect_reset_reconnect_all(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
gboolean only_no_secrets);
|
||||
|
||||
gint32 nm_manager_devcon_autoconnect_retries_blocked_until(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn);
|
||||
|
||||
gboolean nm_manager_devcon_autoconnect_is_blocked(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn);
|
||||
|
||||
gboolean nm_manager_devcon_autoconnect_blocked_reason_set(NMManager *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *sett_conn,
|
||||
NMSettingsAutoconnectBlockedReason value,
|
||||
gboolean set);
|
||||
|
||||
#endif /* __NETWORKMANAGER_MANAGER_H__ */
|
||||
|
|
|
@ -1328,9 +1328,11 @@ pending_ac_state_changed(NMActiveConnection *ac, guint state, guint reason, NMPo
|
|||
*/
|
||||
if (reason != NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED) {
|
||||
con = nm_active_connection_get_settings_connection(ac);
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
priv->manager,
|
||||
nm_active_connection_get_device(ac),
|
||||
con,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
TRUE);
|
||||
schedule_activate_check(self, nm_active_connection_get_device(ac));
|
||||
}
|
||||
|
@ -1391,7 +1393,7 @@ auto_activate_device(NMPolicy *self, NMDevice *device)
|
|||
NMSettingConnection *s_con;
|
||||
const char *permission;
|
||||
|
||||
if (nm_settings_connection_autoconnect_is_blocked(candidate))
|
||||
if (nm_manager_devcon_autoconnect_is_blocked(priv->manager, device, candidate))
|
||||
continue;
|
||||
|
||||
cand_conn = nm_settings_connection_get_connection(candidate);
|
||||
|
@ -1435,9 +1437,11 @@ auto_activate_device(NMPolicy *self, NMDevice *device)
|
|||
"connection '%s' auto-activation failed: %s",
|
||||
nm_settings_connection_get_id(best_connection),
|
||||
error->message);
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
priv->manager,
|
||||
device,
|
||||
best_connection,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
TRUE);
|
||||
schedule_activate_check(self, device);
|
||||
return;
|
||||
|
@ -1600,10 +1604,12 @@ nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self)
|
|||
NMConnection *connection = nm_settings_connection_get_connection(sett_conn);
|
||||
|
||||
if (nm_connection_get_setting_ovs_interface(connection)) {
|
||||
nm_settings_connection_autoconnect_retries_reset(sett_conn);
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn);
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
priv->manager,
|
||||
NULL,
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -1637,33 +1643,11 @@ reset_autoconnect_all(
|
|||
NULL))
|
||||
continue;
|
||||
|
||||
if (only_no_secrets) {
|
||||
/* we only reset the no-secrets blocked flag. */
|
||||
if (nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
|
||||
FALSE)) {
|
||||
/* maybe the connection is still blocked afterwards for other reasons
|
||||
* and in the larger picture nothing changed. But it's too complicated
|
||||
* to find out exactly. Just assume, something changed to be sure. */
|
||||
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
|
||||
changed = TRUE;
|
||||
}
|
||||
} else {
|
||||
/* we reset the tries-count and any blocked-reason */
|
||||
if (nm_settings_connection_autoconnect_retries_get(sett_conn) == 0)
|
||||
changed = TRUE;
|
||||
nm_settings_connection_autoconnect_retries_reset(sett_conn);
|
||||
|
||||
if (nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL
|
||||
& ~NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
|
||||
FALSE)) {
|
||||
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
if (nm_manager_devcon_autoconnect_reset_reconnect_all(priv->manager,
|
||||
device,
|
||||
sett_conn,
|
||||
only_no_secrets))
|
||||
changed = TRUE;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
@ -1737,12 +1721,13 @@ reset_connections_retries(gpointer user_data)
|
|||
for (i = 0; connections[i]; i++) {
|
||||
NMSettingsConnection *connection = connections[i];
|
||||
|
||||
con_stamp = nm_settings_connection_autoconnect_retries_blocked_until(connection);
|
||||
con_stamp =
|
||||
nm_manager_devcon_autoconnect_retries_blocked_until(priv->manager, NULL, connection);
|
||||
if (con_stamp == 0)
|
||||
continue;
|
||||
|
||||
if (con_stamp <= now) {
|
||||
nm_settings_connection_autoconnect_retries_reset(connection);
|
||||
nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, connection);
|
||||
changed = TRUE;
|
||||
} else if (min_stamp == 0 || min_stamp > con_stamp)
|
||||
min_stamp = con_stamp;
|
||||
|
@ -1761,20 +1746,23 @@ reset_connections_retries(gpointer user_data)
|
|||
}
|
||||
|
||||
static void
|
||||
_connection_autoconnect_retries_set(NMPolicy *self, NMSettingsConnection *connection, int tries)
|
||||
_connection_autoconnect_retries_set(NMPolicy *self,
|
||||
NMDevice *device,
|
||||
NMSettingsConnection *connection,
|
||||
guint32 tries)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||
|
||||
nm_assert(NM_IS_SETTINGS_CONNECTION(connection));
|
||||
nm_assert(tries >= 0);
|
||||
|
||||
nm_settings_connection_autoconnect_retries_set(connection, tries);
|
||||
nm_manager_devcon_autoconnect_retries_set(priv->manager, device, connection, tries);
|
||||
|
||||
if (tries == 0) {
|
||||
/* Schedule a handler to reset retries count */
|
||||
if (!priv->reset_retries_id) {
|
||||
gint32 retry_time =
|
||||
nm_settings_connection_autoconnect_retries_blocked_until(connection);
|
||||
gint32 retry_time = nm_manager_devcon_autoconnect_retries_blocked_until(priv->manager,
|
||||
device,
|
||||
connection);
|
||||
|
||||
g_warn_if_fail(retry_time != 0);
|
||||
priv->reset_retries_id =
|
||||
|
@ -1839,13 +1827,16 @@ activate_slave_connections(NMPolicy *self, NMDevice *device)
|
|||
continue;
|
||||
|
||||
if (!internal_activation) {
|
||||
if (nm_settings_connection_autoconnect_retries_get(sett_conn) == 0)
|
||||
changed = TRUE;
|
||||
nm_settings_connection_autoconnect_retries_reset(sett_conn);
|
||||
nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn);
|
||||
/* we cannot know if they changed or not, so considering we did a reset, let's consider they changed. */
|
||||
changed = TRUE;
|
||||
}
|
||||
if (nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
/* unblock the devices associated with that connection */
|
||||
if (nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
priv->manager,
|
||||
NULL,
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
FALSE)) {
|
||||
if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
|
||||
changed = TRUE;
|
||||
|
@ -1968,9 +1959,11 @@ device_state_changed(NMDevice *device,
|
|||
* a missing SIM or wrong modem initialization).
|
||||
*/
|
||||
if (sett_conn) {
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
priv->manager,
|
||||
device,
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
TRUE);
|
||||
}
|
||||
break;
|
||||
|
@ -1988,7 +1981,6 @@ device_state_changed(NMDevice *device,
|
|||
if (sett_conn && old_state >= NM_DEVICE_STATE_PREPARE
|
||||
&& old_state <= NM_DEVICE_STATE_ACTIVATED) {
|
||||
gboolean blocked = FALSE;
|
||||
int tries;
|
||||
guint64 con_v;
|
||||
|
||||
if (nm_device_state_reason_check(reason) == NM_DEVICE_STATE_REASON_NO_SECRETS) {
|
||||
|
@ -2012,7 +2004,7 @@ device_state_changed(NMDevice *device,
|
|||
nm_settings_connection_get_id(sett_conn));
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NO_SECRETS,
|
||||
TRUE);
|
||||
blocked = TRUE;
|
||||
}
|
||||
|
@ -2027,26 +2019,37 @@ device_state_changed(NMDevice *device,
|
|||
* dependency-failed.
|
||||
*/
|
||||
_LOGD(LOGD_DEVICE,
|
||||
"connection '%s' now blocked from autoconnect due to failed dependency",
|
||||
"autoconnect: connection[%p] (%s) now blocked from autoconnect due to failed "
|
||||
"dependency",
|
||||
sett_conn,
|
||||
nm_settings_connection_get_id(sett_conn));
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
priv->manager,
|
||||
device,
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED,
|
||||
TRUE);
|
||||
blocked = TRUE;
|
||||
}
|
||||
|
||||
if (!blocked) {
|
||||
tries = nm_settings_connection_autoconnect_retries_get(sett_conn);
|
||||
if (tries > 0) {
|
||||
guint32 tries;
|
||||
|
||||
tries = nm_manager_devcon_autoconnect_retries_get(priv->manager, device, sett_conn);
|
||||
if (tries == 0) {
|
||||
/* blocked */
|
||||
} else if (tries != NM_AUTOCONNECT_RETRIES_FOREVER) {
|
||||
_LOGD(LOGD_DEVICE,
|
||||
"connection '%s' failed to autoconnect; %d tries left",
|
||||
"autoconnect: connection[%p] (%s): failed to autoconnect; %u tries left",
|
||||
sett_conn,
|
||||
nm_settings_connection_get_id(sett_conn),
|
||||
tries - 1);
|
||||
_connection_autoconnect_retries_set(self, sett_conn, tries - 1);
|
||||
} else if (tries != 0) {
|
||||
tries - 1u);
|
||||
_connection_autoconnect_retries_set(self, device, sett_conn, tries - 1u);
|
||||
} else {
|
||||
_LOGD(LOGD_DEVICE,
|
||||
"connection '%s' failed to autoconnect; infinite tries left",
|
||||
"autoconnect: connection[%p] (%s) failed to autoconnect; infinite tries "
|
||||
"left",
|
||||
sett_conn,
|
||||
nm_settings_connection_get_id(sett_conn));
|
||||
}
|
||||
}
|
||||
|
@ -2055,7 +2058,7 @@ device_state_changed(NMDevice *device,
|
|||
case NM_DEVICE_STATE_ACTIVATED:
|
||||
if (sett_conn) {
|
||||
/* Reset auto retries back to default since connection was successful */
|
||||
nm_settings_connection_autoconnect_retries_reset(sett_conn);
|
||||
nm_manager_devcon_autoconnect_retries_reset(priv->manager, device, sett_conn);
|
||||
}
|
||||
|
||||
/* Since there is no guarantee that device_l3cd_changed() is called
|
||||
|
@ -2087,27 +2090,34 @@ device_state_changed(NMDevice *device,
|
|||
case NM_DEVICE_STATE_DEACTIVATING:
|
||||
if (sett_conn) {
|
||||
NMSettingsAutoconnectBlockedReason blocked_reason =
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE;
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NONE;
|
||||
|
||||
switch (nm_device_state_reason_check(reason)) {
|
||||
case NM_DEVICE_STATE_REASON_USER_REQUESTED:
|
||||
blocked_reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST;
|
||||
blocked_reason = NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST;
|
||||
break;
|
||||
case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
|
||||
blocked_reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED;
|
||||
blocked_reason = NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE) {
|
||||
if (blocked_reason != NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NONE) {
|
||||
_LOGD(LOGD_DEVICE,
|
||||
"blocking autoconnect of connection '%s': %s",
|
||||
nm_settings_connection_get_id(sett_conn),
|
||||
NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_string,
|
||||
nm_device_state_reason_check(reason)));
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(sett_conn,
|
||||
blocked_reason,
|
||||
TRUE);
|
||||
if (blocked_reason == NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED)
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(priv->manager,
|
||||
device,
|
||||
sett_conn,
|
||||
blocked_reason,
|
||||
TRUE);
|
||||
else
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(sett_conn,
|
||||
blocked_reason,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
ip6_remove_device_prefix_delegations(self, device);
|
||||
|
@ -2146,9 +2156,11 @@ device_state_changed(NMDevice *device,
|
|||
case NM_DEVICE_STATE_IP_CONFIG:
|
||||
/* We must have secrets if we got here. */
|
||||
if (sett_conn)
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
nm_manager_devcon_autoconnect_blocked_reason_set(
|
||||
priv->manager,
|
||||
device,
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_ALL,
|
||||
FALSE);
|
||||
break;
|
||||
case NM_DEVICE_STATE_SECONDARIES:
|
||||
|
|
|
@ -24,13 +24,10 @@
|
|||
#include "libnm-core-intern/nm-core-internal.h"
|
||||
#include "nm-audit-manager.h"
|
||||
#include "nm-settings.h"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "settings/plugins/keyfile/nms-keyfile-storage.h"
|
||||
|
||||
#define AUTOCONNECT_RETRIES_UNSET -2
|
||||
#define AUTOCONNECT_RETRIES_FOREVER -1
|
||||
#define AUTOCONNECT_RESET_RETRIES_TIMER 300
|
||||
|
||||
#define SEEN_BSSIDS_MAX 30
|
||||
|
||||
#define _NM_SETTINGS_UPDATE2_FLAG_ALL_PERSIST_MODES \
|
||||
|
@ -159,10 +156,6 @@ typedef struct _NMSettingsConnectionPrivate {
|
|||
|
||||
guint64 last_secret_agent_version_id;
|
||||
|
||||
int autoconnect_retries;
|
||||
|
||||
gint32 autoconnect_retries_blocked_until;
|
||||
|
||||
bool timestamp_set : 1;
|
||||
|
||||
NMSettingsAutoconnectBlockedReason autoconnect_blocked_reason : 4;
|
||||
|
@ -227,6 +220,22 @@ static guint _get_seen_bssids(NMSettingsConnection *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMSettings *
|
||||
nm_settings_connection_get_settings(NMSettingsConnection *self)
|
||||
{
|
||||
g_return_val_if_fail(NM_IS_SETTINGS_CONNECTION(self), NULL);
|
||||
|
||||
return NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->settings;
|
||||
}
|
||||
|
||||
NMManager *
|
||||
nm_settings_connection_get_manager(NMSettingsConnection *self)
|
||||
{
|
||||
return nm_settings_get_manager(nm_settings_connection_get_settings(self));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMDevice *
|
||||
nm_settings_connection_default_wired_get_device(NMSettingsConnection *self)
|
||||
{
|
||||
|
@ -1445,52 +1454,6 @@ update_complete(NMSettingsConnection *self, UpdateInfo *info, GError *error)
|
|||
g_slice_free(UpdateInfo, info);
|
||||
}
|
||||
|
||||
static int
|
||||
_autoconnect_retries_initial(NMSettingsConnection *self)
|
||||
{
|
||||
NMSettingConnection *s_con;
|
||||
int retries = -1;
|
||||
|
||||
s_con = nm_connection_get_setting_connection(nm_settings_connection_get_connection(self));
|
||||
if (s_con)
|
||||
retries = nm_setting_connection_get_autoconnect_retries(s_con);
|
||||
|
||||
/* -1 means 'default' */
|
||||
if (retries == -1)
|
||||
retries = nm_config_data_get_autoconnect_retries_default(NM_CONFIG_GET_DATA);
|
||||
|
||||
/* 0 means 'forever', which is translated to a retry count of -1 */
|
||||
if (retries == 0)
|
||||
retries = AUTOCONNECT_RETRIES_FOREVER;
|
||||
|
||||
nm_assert(retries == AUTOCONNECT_RETRIES_FOREVER || retries >= 0);
|
||||
return retries;
|
||||
}
|
||||
|
||||
static void
|
||||
_autoconnect_retries_set(NMSettingsConnection *self, int retries, gboolean is_reset)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
|
||||
|
||||
g_return_if_fail(retries == AUTOCONNECT_RETRIES_FOREVER || retries >= 0);
|
||||
|
||||
if (priv->autoconnect_retries != retries) {
|
||||
_LOGT("autoconnect: retries set %d%s", retries, is_reset ? " (reset)" : "");
|
||||
priv->autoconnect_retries = retries;
|
||||
}
|
||||
|
||||
if (retries)
|
||||
priv->autoconnect_retries_blocked_until = 0;
|
||||
else {
|
||||
/* NOTE: the blocked time must be identical for all connections, otherwise
|
||||
* the tracking of resetting the retry count in NMPolicy needs adjustment
|
||||
* in _connection_autoconnect_retries_set() (as it would need to re-evaluate
|
||||
* the next-timeout every time a connection gets blocked). */
|
||||
priv->autoconnect_retries_blocked_until =
|
||||
nm_utils_get_monotonic_timestamp_sec() + AUTOCONNECT_RESET_RETRIES_TIMER;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_auth_cb(NMSettingsConnection *self,
|
||||
GDBusMethodInvocation *context,
|
||||
|
@ -1539,10 +1502,13 @@ update_auth_cb(NMSettingsConnection *self,
|
|||
/* New secrets, allow autoconnection again */
|
||||
if (nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
self,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NO_SECRETS,
|
||||
FALSE)
|
||||
&& !nm_settings_connection_autoconnect_blocked_reason_get(self))
|
||||
nm_settings_connection_autoconnect_retries_reset(self);
|
||||
nm_manager_devcon_autoconnect_retries_reset(
|
||||
nm_settings_connection_get_manager(self),
|
||||
NULL,
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1615,7 +1581,9 @@ update_auth_cb(NMSettingsConnection *self,
|
|||
}
|
||||
|
||||
/* Reset auto retries back to default since connection was updated */
|
||||
nm_settings_connection_autoconnect_retries_reset(self);
|
||||
nm_manager_devcon_autoconnect_retries_reset(nm_settings_connection_get_manager(self),
|
||||
NULL,
|
||||
self);
|
||||
|
||||
update_complete(self, info, local);
|
||||
}
|
||||
|
@ -2534,56 +2502,6 @@ nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *se
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_settings_connection_autoconnect_retries_get:
|
||||
* @self: the settings connection
|
||||
*
|
||||
* Returns the number of autoconnect retries left. If the value is
|
||||
* not yet set, initialize it with the value from the connection or
|
||||
* with the global default.
|
||||
*/
|
||||
int
|
||||
nm_settings_connection_autoconnect_retries_get(NMSettingsConnection *self)
|
||||
{
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
|
||||
|
||||
if (G_UNLIKELY(priv->autoconnect_retries == AUTOCONNECT_RETRIES_UNSET)) {
|
||||
_autoconnect_retries_set(self, _autoconnect_retries_initial(self), TRUE);
|
||||
}
|
||||
return priv->autoconnect_retries;
|
||||
}
|
||||
|
||||
void
|
||||
nm_settings_connection_autoconnect_retries_set(NMSettingsConnection *self, int retries)
|
||||
{
|
||||
g_return_if_fail(NM_IS_SETTINGS_CONNECTION(self));
|
||||
g_return_if_fail(retries >= 0);
|
||||
|
||||
_autoconnect_retries_set(self, retries, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
nm_settings_connection_autoconnect_retries_reset(NMSettingsConnection *self)
|
||||
{
|
||||
g_return_if_fail(NM_IS_SETTINGS_CONNECTION(self));
|
||||
|
||||
_autoconnect_retries_set(self, _autoconnect_retries_initial(self), TRUE);
|
||||
}
|
||||
|
||||
gint32
|
||||
nm_settings_connection_autoconnect_retries_blocked_until(NMSettingsConnection *self)
|
||||
{
|
||||
return NM_SETTINGS_CONNECTION_GET_PRIVATE(self)->autoconnect_retries_blocked_until;
|
||||
}
|
||||
|
||||
static NM_UTILS_FLAGS2STR_DEFINE(
|
||||
_autoconnect_blocked_reason_to_string,
|
||||
NMSettingsAutoconnectBlockedReason,
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE, "none"),
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST, "user-request"),
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED, "failed"),
|
||||
NM_UTILS_FLAGS2STR(NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS, "no-secrets"), );
|
||||
|
||||
NMSettingsAutoconnectBlockedReason
|
||||
nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self)
|
||||
{
|
||||
|
@ -2591,25 +2509,27 @@ nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self
|
|||
}
|
||||
|
||||
gboolean
|
||||
nm_settings_connection_autoconnect_blocked_reason_set_full(NMSettingsConnection *self,
|
||||
NMSettingsAutoconnectBlockedReason mask,
|
||||
NMSettingsAutoconnectBlockedReason value)
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(NMSettingsConnection *self,
|
||||
NMSettingsAutoconnectBlockedReason reason,
|
||||
gboolean set)
|
||||
{
|
||||
NMSettingsAutoconnectBlockedReason v;
|
||||
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
|
||||
char buf[100];
|
||||
char buf1[100];
|
||||
char buf2[100];
|
||||
|
||||
nm_assert(mask);
|
||||
nm_assert(!NM_FLAGS_ANY(value, ~mask));
|
||||
nm_assert(reason);
|
||||
|
||||
v = priv->autoconnect_blocked_reason;
|
||||
v = (v & ~mask) | (value & mask);
|
||||
v = NM_FLAGS_ASSIGN(v, reason, set);
|
||||
|
||||
if (priv->autoconnect_blocked_reason == v)
|
||||
return FALSE;
|
||||
|
||||
_LOGT("autoconnect: blocked reason: %s",
|
||||
_autoconnect_blocked_reason_to_string(v, buf, sizeof(buf)));
|
||||
_LOGD("autoconnect: %s blocked reason: %s (now %s)",
|
||||
set ? "set" : "unset",
|
||||
nm_settings_autoconnect_blocked_reason_to_string(reason, buf1, sizeof(buf1)),
|
||||
nm_settings_autoconnect_blocked_reason_to_string(v, buf2, sizeof(buf2)));
|
||||
priv->autoconnect_blocked_reason = v;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2624,9 +2544,7 @@ nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self)
|
|||
|
||||
priv = NM_SETTINGS_CONNECTION_GET_PRIVATE(self);
|
||||
|
||||
if (priv->autoconnect_blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE)
|
||||
return TRUE;
|
||||
if (priv->autoconnect_retries == 0)
|
||||
if (priv->autoconnect_blocked_reason != NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_NONE)
|
||||
return TRUE;
|
||||
|
||||
flags = priv->flags;
|
||||
|
@ -2740,14 +2658,13 @@ nm_settings_connection_init(NMSettingsConnection *self)
|
|||
self->_priv = priv;
|
||||
|
||||
c_list_init(&self->_connections_lst);
|
||||
c_list_init(&self->devcon_con_lst_head);
|
||||
c_list_init(&priv->seen_bssids_lst_head);
|
||||
c_list_init(&priv->call_ids_lst_head);
|
||||
c_list_init(&priv->auth_lst_head);
|
||||
|
||||
priv->agent_mgr = g_object_ref(nm_agent_manager_get());
|
||||
priv->settings = g_object_ref(nm_settings_get());
|
||||
|
||||
priv->autoconnect_retries = AUTOCONNECT_RETRIES_UNSET;
|
||||
}
|
||||
|
||||
NMSettingsConnection *
|
||||
|
@ -2768,6 +2685,7 @@ dispose(GObject *object)
|
|||
nm_assert(!priv->default_wired_device);
|
||||
|
||||
nm_assert(c_list_is_empty(&self->_connections_lst));
|
||||
nm_assert(c_list_is_empty(&self->devcon_con_lst_head));
|
||||
nm_assert(c_list_is_empty(&priv->auth_lst_head));
|
||||
|
||||
/* Cancel in-progress secrets requests */
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "nm-dbus-object.h"
|
||||
#include "nm-connection.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#include "nm-settings-storage.h"
|
||||
|
||||
|
@ -188,19 +189,6 @@ typedef enum _NMSettingsConnectionIntFlags {
|
|||
_NM_SETTINGS_CONNECTION_INT_FLAGS_ALL = ((_NM_SETTINGS_CONNECTION_INT_FLAGS_LAST - 1) << 1) - 1,
|
||||
} NMSettingsConnectionIntFlags;
|
||||
|
||||
typedef enum {
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE = 0,
|
||||
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST = (1LL << 0),
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED = (1LL << 1),
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS = (1LL << 2),
|
||||
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL =
|
||||
(NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST
|
||||
| NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED
|
||||
| NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS),
|
||||
} NMSettingsAutoconnectBlockedReason;
|
||||
|
||||
typedef struct _NMSettingsConnectionCallId NMSettingsConnectionCallId;
|
||||
|
||||
typedef struct _NMSettingsConnectionClass NMSettingsConnectionClass;
|
||||
|
@ -210,6 +198,7 @@ struct _NMSettingsConnectionPrivate;
|
|||
struct _NMSettingsConnection {
|
||||
NMDBusObject parent;
|
||||
CList _connections_lst;
|
||||
CList devcon_con_lst_head;
|
||||
struct _NMSettingsConnectionPrivate *_priv;
|
||||
};
|
||||
|
||||
|
@ -217,6 +206,10 @@ GType nm_settings_connection_get_type(void);
|
|||
|
||||
NMSettingsConnection *nm_settings_connection_new(void);
|
||||
|
||||
NMSettings *nm_settings_connection_get_settings(NMSettingsConnection *self);
|
||||
|
||||
NMManager *nm_settings_connection_get_manager(NMSettingsConnection *self);
|
||||
|
||||
NMConnection *nm_settings_connection_get_connection(NMSettingsConnection *self);
|
||||
|
||||
void _nm_settings_connection_set_connection(NMSettingsConnection *self,
|
||||
|
@ -345,31 +338,15 @@ gboolean nm_settings_connection_has_seen_bssid(NMSettingsConnection *self, const
|
|||
|
||||
void nm_settings_connection_add_seen_bssid(NMSettingsConnection *self, const char *seen_bssid);
|
||||
|
||||
int nm_settings_connection_autoconnect_retries_get(NMSettingsConnection *self);
|
||||
void nm_settings_connection_autoconnect_retries_set(NMSettingsConnection *self, int retries);
|
||||
void nm_settings_connection_autoconnect_retries_reset(NMSettingsConnection *self);
|
||||
|
||||
gint32 nm_settings_connection_autoconnect_retries_blocked_until(NMSettingsConnection *self);
|
||||
gboolean nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self);
|
||||
|
||||
NMSettingsAutoconnectBlockedReason
|
||||
nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self);
|
||||
gboolean nm_settings_connection_autoconnect_blocked_reason_set_full(
|
||||
NMSettingsConnection *self,
|
||||
NMSettingsAutoconnectBlockedReason mask,
|
||||
NMSettingsAutoconnectBlockedReason value);
|
||||
nm_settings_connection_autoconnect_blocked_reason_get(NMSettingsConnection *self);
|
||||
|
||||
static inline gboolean
|
||||
gboolean
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(NMSettingsConnection *self,
|
||||
NMSettingsAutoconnectBlockedReason mask,
|
||||
gboolean set)
|
||||
{
|
||||
return nm_settings_connection_autoconnect_blocked_reason_set_full(
|
||||
self,
|
||||
mask,
|
||||
set ? mask : NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE);
|
||||
}
|
||||
|
||||
gboolean nm_settings_connection_autoconnect_is_blocked(NMSettingsConnection *self);
|
||||
NMSettingsAutoconnectBlockedReason reason,
|
||||
gboolean set);
|
||||
|
||||
const char *nm_settings_connection_get_id(NMSettingsConnection *connection);
|
||||
const char *nm_settings_connection_get_uuid(NMSettingsConnection *connection);
|
||||
|
|
|
@ -451,6 +451,16 @@ static void _startup_complete_check(NMSettings *self, gint64 now_msec);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMManager *
|
||||
nm_settings_get_manager(NMSettings *self)
|
||||
{
|
||||
g_return_val_if_fail(NM_IS_SETTINGS(self), NULL);
|
||||
|
||||
return NM_SETTINGS_GET_PRIVATE(self)->manager;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_emit_connection_added(NMSettings *self, NMSettingsConnection *sett_conn)
|
||||
{
|
||||
|
@ -1109,7 +1119,7 @@ _connection_changed_update(NMSettings *self,
|
|||
if (NM_FLAGS_HAS(update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT)) {
|
||||
nm_settings_connection_autoconnect_blocked_reason_set(
|
||||
sett_conn,
|
||||
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
|
||||
NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_USER_REQUEST,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
|
@ -1237,6 +1247,8 @@ _connection_changed_delete(NMSettings *self,
|
|||
| NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL,
|
||||
FALSE);
|
||||
|
||||
nm_manager_notify_delete_settings_connections(priv->manager, sett_conn);
|
||||
|
||||
_emit_connection_removed(self, sett_conn);
|
||||
|
||||
_nm_settings_connection_cleanup_after_remove(sett_conn);
|
||||
|
|
|
@ -58,6 +58,8 @@ NMSettings *nm_settings_get(void);
|
|||
|
||||
NMSettings *nm_settings_new(NMManager *manager);
|
||||
|
||||
NMManager *nm_settings_get_manager(NMSettings *self);
|
||||
|
||||
gboolean nm_settings_start(NMSettings *self, GError **error);
|
||||
|
||||
typedef void (*NMSettingsAddCallback)(NMSettings *settings,
|
||||
|
|
Loading…
Reference in a new issue