merge: branch 'lr/device-conn'

https://bugzilla.gnome.org/show_bug.cgi?id=780448
This commit is contained in:
Lubomir Rintel 2017-03-28 15:27:05 +02:00
commit 29af644f9a
8 changed files with 440 additions and 423 deletions

View file

@ -1428,7 +1428,6 @@ src_libNetworkManager_la_SOURCES = \
src/nm-config.h \
src/nm-config-data.c \
src/nm-config-data.h \
src/nm-connectivity.c \
src/nm-connectivity.h \
src/nm-dcb.c \
src/nm-dcb.h \
@ -1466,6 +1465,11 @@ src_libNetworkManager_la_SOURCES = \
\
$(NULL)
if WITH_CONCHECK
src_libNetworkManager_la_SOURCES += \
src/nm-connectivity.c
endif
src_libNetworkManager_la_LIBADD = \
src/libNetworkManagerBase.la \
src/libsystemd-nm.la \

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2005 - 2013 Red Hat, Inc.
* Copyright (C) 2005 - 2017 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
@ -66,6 +66,8 @@
#include "nm-lldp-listener.h"
#include "nm-audit-manager.h"
#include "nm-arping-manager.h"
#include "nm-connectivity.h"
#include "nm-dbus-interface.h"
#include "nm-device-logging.h"
_LOG_DECLARE_SELF (NMDevice);
@ -189,6 +191,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
PROP_REFRESH_RATE_MS,
PROP_TX_BYTES,
PROP_RX_BYTES,
PROP_CONNECTIVITY,
);
typedef struct _NMDevicePrivate {
@ -442,6 +445,9 @@ typedef struct _NMDevicePrivate {
NMSettings *settings;
NMLldpListener *lldp_listener;
NMConnectivityState connectivity_state;
guint concheck_periodic_id;
guint64 concheck_seq;
guint check_delete_unrealized_id;
@ -1474,6 +1480,17 @@ nm_device_get_priority (NMDevice *self)
return 11000;
}
static int
default_route_penalty (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->connectivity_state != NM_CONNECTIVITY_FULL)
return 20000;
else
return 0;
}
static guint32
_get_ipx_route_metric (NMDevice *self,
gboolean is_v4)
@ -1697,6 +1714,172 @@ nm_device_get_physical_port_id (NMDevice *self)
/*****************************************************************************/
static void
update_connectivity_state (NMDevice *self, NMConnectivityState state)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
/* If the connectivity check is disabled, make an optimistic guess. */
if (state == NM_CONNECTIVITY_UNKNOWN) {
if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
if (priv->default_route.v4_has || priv->default_route.v6_has)
state = NM_CONNECTIVITY_FULL;
else
state = NM_CONNECTIVITY_LIMITED;
} else {
state = NM_CONNECTIVITY_NONE;
}
}
if (priv->connectivity_state != state) {
#if WITH_CONCHECK
_LOGD (LOGD_CONCHECK, "state changed from %s to %s",
nm_connectivity_state_to_string (priv->connectivity_state),
nm_connectivity_state_to_string (state));
#endif
priv->connectivity_state = state;
_notify (self, PROP_CONNECTIVITY);
if (!ip4_config_merge_and_apply (self, NULL, TRUE))
_LOGW (LOGD_IP4, "Failed to update IPv4 default route metric");
if (!ip6_config_merge_and_apply (self, TRUE))
_LOGW (LOGD_IP6, "Failed to update IPv6 default route metric");
}
}
typedef struct {
NMDevice *self;
NMDeviceConnectivityCallback callback;
gpointer user_data;
guint64 seq;
} ConnectivityCheckData;
static void
concheck_done (ConnectivityCheckData *data)
{
NMDevice *self = data->self;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
/* The unsolicited connectivity checks don't hook a callback. */
if (data->callback)
data->callback (data->self, priv->connectivity_state, data->user_data);
g_object_unref (data->self);
g_slice_free (ConnectivityCheckData, data);
}
#if WITH_CONCHECK
static void
concheck_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
{
ConnectivityCheckData *data = user_data;
NMDevice *self = data->self;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMConnectivity *connectivity = NM_CONNECTIVITY (source_object);
NMConnectivityState state;
GError *error = NULL;
state = nm_connectivity_check_finish (connectivity, result, &error);
if (error) {
_LOGW (LOGD_DEVICE, "connectivity checking on '%s' failed: %s",
nm_device_get_iface (self), error->message);
g_error_free (error);
}
if (data->seq == priv->concheck_seq)
update_connectivity_state (data->self, state);
concheck_done (data);
}
#endif /* WITH_CONCHECK */
static gboolean
no_concheck (gpointer user_data)
{
ConnectivityCheckData *data = user_data;
concheck_done (data);
return G_SOURCE_REMOVE;
}
void
nm_device_check_connectivity (NMDevice *self,
NMDeviceConnectivityCallback callback,
gpointer user_data)
{
ConnectivityCheckData *data;
#if WITH_CONCHECK
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
#endif
data = g_slice_new0 (ConnectivityCheckData);
data->self = g_object_ref (self);
data->callback = callback;
data->user_data = user_data;
#if WITH_CONCHECK
if (priv->concheck_periodic_id) {
data->seq = ++priv->concheck_seq;
/* Kick off a real connectivity check. */
nm_connectivity_check_async (nm_connectivity_get (),
nm_device_get_iface (self),
concheck_cb,
data);
return;
}
#endif
/* Fake one. */
g_idle_add (no_concheck, data);
}
NMConnectivityState
nm_device_get_connectivity_state (NMDevice *self)
{
g_return_val_if_fail (NM_IS_DEVICE (self), NM_CONNECTIVITY_UNKNOWN);
return NM_DEVICE_GET_PRIVATE (self)->connectivity_state;
}
#if WITH_CONCHECK
static void
concheck_periodic (NMConnectivity *connectivity, NMDevice *self)
{
nm_device_check_connectivity (self, NULL, NULL);
}
#endif
static void
concheck_periodic_update (NMDevice *self)
{
#if WITH_CONCHECK
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean check_enable;
check_enable = (priv->state == NM_DEVICE_STATE_ACTIVATED)
&& (priv->default_route.v4_has || priv->default_route.v6_has);
if (check_enable && !priv->concheck_periodic_id) {
/* We just gained a default route. Enable periodic checking. */
priv->concheck_periodic_id = g_signal_connect (nm_connectivity_get (),
NM_CONNECTIVITY_PERIODIC_CHECK,
G_CALLBACK (concheck_periodic), self);
/* Also kick off a check right away. */
nm_device_check_connectivity (self, NULL, NULL);
} else if (!check_enable && priv->concheck_periodic_id) {
/* The default route has gone off, and so has connectivity. */
g_signal_handler_disconnect (nm_connectivity_get (), priv->concheck_periodic_id);
priv->concheck_periodic_id = 0;
update_connectivity_state (self, NM_CONNECTIVITY_NONE);
}
#else
/* update_connectivity_state() figures out how to lie about
* connectivity state if the actual state is not really known. */
update_connectivity_state (self, NM_CONNECTIVITY_UNKNOWN);
#endif
}
/*****************************************************************************/
static SlaveInfo *
find_slave_info (NMDevice *self, NMDevice *slave)
{
@ -5322,7 +5505,7 @@ ip4_config_merge_and_apply (NMDevice *self,
memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4));
priv->default_route.v4.rt_source = NM_IP_CONFIG_SOURCE_USER;
priv->default_route.v4.gateway = gateway;
priv->default_route.v4.metric = default_route_metric;
priv->default_route.v4.metric = default_route_metric + default_route_penalty (self);
priv->default_route.v4.mss = nm_ip4_config_get_mss (composite);
if (!has_direct_route) {
@ -6069,7 +6252,7 @@ ip6_config_merge_and_apply (NMDevice *self,
memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6));
priv->default_route.v6.rt_source = NM_IP_CONFIG_SOURCE_USER;
priv->default_route.v6.gateway = *gateway;
priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self);
priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self) + default_route_penalty (self);
priv->default_route.v6.mss = nm_ip6_config_get_mss (composite);
if (!has_direct_route) {
@ -9483,6 +9666,8 @@ nm_device_set_ip4_config (NMDevice *self,
}
nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self);
concheck_periodic_update (self);
if (!nm_device_sys_iface_state_is_external_or_assume (self))
ip4_rp_filter_update (self);
@ -12445,6 +12630,8 @@ _set_state_full (NMDevice *self,
if (ip_config_valid (old_state) && !ip_config_valid (state))
notify_ip_properties (self);
concheck_periodic_update (self);
/* Dispose of the cached activation request */
if (req)
g_object_unref (req);
@ -13837,6 +14024,9 @@ get_property (GObject *object, guint prop_id,
case PROP_RX_BYTES:
g_value_set_uint64 (value, priv->stats.rx_bytes);
break;
case PROP_CONNECTIVITY:
g_value_set_uint (value, priv->connectivity_state);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -14107,6 +14297,13 @@ nm_device_class_init (NMDeviceClass *klass)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
/* Connectivity */
obj_properties[PROP_CONNECTIVITY] =
g_param_spec_uint (NM_DEVICE_CONNECTIVITY, "", "",
NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[STATE_CHANGED] =

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2005 - 2013 Red Hat, Inc.
* Copyright (C) 2005 - 2017 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
@ -135,6 +135,8 @@ nm_device_state_reason_check (NMDeviceStateReason reason)
#define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes"
#define NM_DEVICE_STATISTICS_RX_BYTES "rx-bytes"
#define NM_DEVICE_CONNECTIVITY "connectivity"
#define NM_TYPE_DEVICE (nm_device_get_type ())
#define NM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice))
#define NM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE, NMDeviceClass))
@ -689,4 +691,12 @@ gboolean nm_device_hw_addr_get_cloned (NMDevice *self,
gboolean *preserve,
GError **error);
typedef void (*NMDeviceConnectivityCallback) (NMDevice *self,
NMConnectivityState state,
gpointer user_data);
void nm_device_check_connectivity (NMDevice *self,
NMDeviceConnectivityCallback callback,
gpointer user_data);
NMConnectivityState nm_device_get_connectivity_state (NMDevice *self);
#endif /* __NETWORKMANAGER_DEVICE_H__ */

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2004 - 2012 Red Hat, Inc.
* Copyright (C) 2004 - 2017 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
*/
@ -49,6 +49,7 @@
#include "nm-auth-manager.h"
#include "nm-core-internal.h"
#include "nm-exported-object.h"
#include "nm-connectivity.h"
#include "dns/nm-dns-manager.h"
#include "systemd/nm-sd.h"
@ -391,6 +392,9 @@ main (int argc, char *argv[])
nm_linux_platform_setup ();
NM_UTILS_KEEP_ALIVE (config, NM_PLATFORM_GET, "NMConfig-depends-on-NMPlatform");
#if WITH_CONCHECK
NM_UTILS_KEEP_ALIVE (nm_manager_get (), nm_connectivity_get (), "NMManager-depends-on-NMConnectivity");
#endif
nm_dispatcher_init ();

View file

@ -25,37 +25,21 @@
#include "nm-connectivity.h"
#include <string.h>
#if WITH_CONCHECK
#include <curl/curl.h>
#endif
#include "nm-config.h"
#include "nm-dispatcher.h"
#include "NetworkManagerUtils.h"
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE (NMConnectivity,
PROP_URI,
PROP_INTERVAL,
PROP_RESPONSE,
PROP_STATE,
);
typedef struct {
char *uri;
char *response;
guint interval;
gboolean online; /* whether periodic connectivity checking is enabled. */
#if WITH_CONCHECK
NMConfig *config;
guint periodic_check_id;
CURLM *curl_mhandle;
guint curl_timer;
gboolean initial_check_obsoleted;
guint check_id;
#endif
NMConnectivityState state;
} NMConnectivityPrivate;
struct _NMConnectivity {
@ -71,21 +55,38 @@ G_DEFINE_TYPE (NMConnectivity, nm_connectivity, G_TYPE_OBJECT)
#define NM_CONNECTIVITY_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMConnectivity, NM_IS_CONNECTIVITY)
NM_DEFINE_SINGLETON_GETTER (NMConnectivity, nm_connectivity_get, NM_TYPE_CONNECTIVITY);
enum {
PERIODIC_CHECK,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/*****************************************************************************/
#define _NMLOG_DOMAIN LOGD_CONCHECK
#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "connectivity", __VA_ARGS__)
#define _NMLOG2_DOMAIN LOGD_CONCHECK
#define _NMLOG2(level, ...) \
G_STMT_START { \
const NMLogLevel __level = (level); \
\
if (nm_logging_enabled (__level, _NMLOG2_DOMAIN)) { \
_nm_log (__level, _NMLOG2_DOMAIN, 0, \
&cb_data->ifspec[3], NULL, \
"connectivity: (%s) " \
_NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
&cb_data->ifspec[3] \
_NM_UTILS_MACRO_REST (__VA_ARGS__)); \
} \
} G_STMT_END
/*****************************************************************************/
NMConnectivityState
nm_connectivity_get_state (NMConnectivity *connectivity)
{
g_return_val_if_fail (NM_IS_CONNECTIVITY (connectivity), NM_CONNECTIVITY_UNKNOWN);
return NM_CONNECTIVITY_GET_PRIVATE (connectivity)->state;
}
NM_UTILS_LOOKUP_STR_DEFINE (nm_connectivity_state_to_string, NMConnectivityState,
NM_UTILS_LOOKUP_DEFAULT_WARN ("???"),
NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_UNKNOWN, "UNKNOWN"),
@ -95,139 +96,22 @@ NM_UTILS_LOOKUP_STR_DEFINE (nm_connectivity_state_to_string, NMConnectivityState
NM_UTILS_LOOKUP_STR_ITEM (NM_CONNECTIVITY_FULL, "FULL"),
);
static void
update_state (NMConnectivity *self, NMConnectivityState state)
{
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
if (priv->state != state) {
_LOGD ("state changed from %s to %s",
nm_connectivity_state_to_string (priv->state),
nm_connectivity_state_to_string (state));
priv->state = state;
_notify (self, PROP_STATE);
nm_dispatcher_call_connectivity (state, NULL, NULL, NULL);
}
}
/*****************************************************************************/
#if WITH_CONCHECK
static void
run_check_complete (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMConnectivity *self = NM_CONNECTIVITY (object);
GError *error = NULL;
nm_connectivity_check_finish (self, result, &error);
if (error) {
_LOGE ("check failed: %s", error->message);
g_error_free (error);
}
}
static gboolean
run_check (gpointer user_data)
{
NMConnectivity *self = NM_CONNECTIVITY (user_data);
nm_connectivity_check_async (self, run_check_complete, NULL);
return TRUE;
}
static gboolean
idle_start_periodic_checks (gpointer user_data)
{
NMConnectivity *self = user_data;
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
priv->check_id = g_timeout_add_seconds (priv->interval, run_check, self);
if (!priv->initial_check_obsoleted)
run_check (self);
return FALSE;
}
#endif
static void
_reschedule_periodic_checks (NMConnectivity *self, gboolean force_reschedule)
{
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
#if WITH_CONCHECK
if (priv->online && priv->uri && priv->interval) {
if (force_reschedule || !priv->check_id) {
if (priv->check_id)
g_source_remove (priv->check_id);
priv->check_id = g_timeout_add (0, idle_start_periodic_checks, self);
priv->initial_check_obsoleted = FALSE;
}
} else {
nm_clear_g_source (&priv->check_id);
}
if (priv->check_id)
return;
#endif
/* Either @online is %TRUE but we aren't checking connectivity, or
* @online is %FALSE. Either way we can update our status immediately.
*/
update_state (self, priv->online ? NM_CONNECTIVITY_FULL : NM_CONNECTIVITY_NONE);
}
void
nm_connectivity_set_online (NMConnectivity *self,
gboolean online)
{
NMConnectivityPrivate *priv= NM_CONNECTIVITY_GET_PRIVATE (self);
online = !!online;
if (priv->online != online) {
_LOGD ("set %s", online ? "online" : "offline");
priv->online = online;
_reschedule_periodic_checks (self, FALSE);
}
}
/*****************************************************************************/
#if WITH_CONCHECK
typedef struct {
GSimpleAsyncResult *simple;
char *uri;
char *response;
guint check_id_when_scheduled;
CURL *curl_ehandle;
size_t msg_size;
char *msg;
struct curl_slist *request_headers;
guint timeout_id;
char *ifspec;
} ConCheckCbData;
static void
finish_cb_data (ConCheckCbData *cb_data, NMConnectivityState new_state)
{
NMConnectivity *self = NM_CONNECTIVITY (g_async_result_get_source_object (G_ASYNC_RESULT (cb_data->simple)));
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
/* Only update the state, if the call was done from external, or if the periodic check
* is still the one that called this async check. */
if (!cb_data->check_id_when_scheduled || cb_data->check_id_when_scheduled == priv->check_id) {
/* Only update the state, if the URI and response parameters did not change
* since invocation.
* The interval does not matter for exernal calls, and for internal calls
* we don't reach this line if the interval changed. */
if ( !g_strcmp0 (cb_data->uri, priv->uri)
&& !g_strcmp0 (cb_data->response, priv->response)) {
_LOGT ("Update to connectivity state %s",
nm_connectivity_state_to_string (new_state));
update_state (self, new_state);
}
}
/* Contrary to what cURL manual claim it is *not* safe to remove
* the easy handle "at any moment"; specifically not from the
* write function. Thus here we just dissociate the cb_data from
@ -239,7 +123,6 @@ finish_cb_data (ConCheckCbData *cb_data, NMConnectivityState new_state)
g_simple_async_result_complete (cb_data->simple);
g_object_unref (cb_data->simple);
curl_slist_free_all (cb_data->request_headers);
g_free (cb_data->uri);
g_free (cb_data->response);
g_source_remove (cb_data->timeout_id);
g_slice_free (ConCheckCbData, cb_data);
@ -254,7 +137,7 @@ curl_check_connectivity (CURLM *mhandle, CURLMcode ret)
gint m_left;
if (ret != CURLM_OK)
_LOGW ("Connectivity check failed");
_LOGW ("connectivity check failed");
while ((msg = curl_multi_info_read (mhandle, &m_left))) {
if (msg->msg != CURLMSG_DONE)
@ -263,7 +146,7 @@ curl_check_connectivity (CURLM *mhandle, CURLMcode ret)
/* Here we have completed a session. Check easy session result. */
eret = curl_easy_getinfo (msg->easy_handle, CURLINFO_PRIVATE, &cb_data);
if (eret != CURLE_OK) {
_LOGE ("curl cannot extract cb_data for easy handle %p, skipping msg", msg->easy_handle);
_LOG2E ("curl cannot extract cb_data for easy handle %p, skipping msg", msg->easy_handle);
continue;
}
@ -273,11 +156,11 @@ curl_check_connectivity (CURLM *mhandle, CURLMcode ret)
if (msg->data.result == CURLE_OK) {
/* If we get here, it means that easy_write_cb() didn't read enough
* bytes to be able to do a match. */
_LOGI ("Check for uri '%s' returned a shorter response than expected '%s'; assuming captive portal.",
cb_data->uri, cb_data->response);
_LOG2I ("response shorter than expected '%s'; assuming captive portal.",
cb_data->response);
finish_cb_data (cb_data, NM_CONNECTIVITY_PORTAL);
} else {
_LOGD ("Check for uri '%s' failed", cb_data->uri);
_LOG2D ("check failed (%d)", msg->data.result);
finish_cb_data (cb_data, NM_CONNECTIVITY_LIMITED);
}
}
@ -393,7 +276,7 @@ easy_header_cb (char *buffer, size_t size, size_t nitems, void *userdata)
if ( len >= sizeof (HEADER_STATUS_ONLINE) - 1
&& !g_ascii_strncasecmp (buffer, HEADER_STATUS_ONLINE, sizeof (HEADER_STATUS_ONLINE) - 1)) {
_LOGD ("check for uri '%s' with Status header successful.", cb_data->uri);
_LOG2D ("status header found, check successful");
finish_cb_data (cb_data, NM_CONNECTIVITY_FULL);
return 0;
}
@ -414,11 +297,11 @@ easy_write_cb (void *buffer, size_t size, size_t nmemb, void *userdata)
if (cb_data->msg_size >= strlen (cb_data->response)) {
/* We already have enough data -- check response */
if (g_str_has_prefix (cb_data->msg, cb_data->response)) {
_LOGD ("Check for uri '%s' successful.", cb_data->uri);
_LOG2D ("check successful.");
finish_cb_data (cb_data, NM_CONNECTIVITY_FULL);
} else {
_LOGI ("Check for uri '%s' did not match expected response '%s'; assuming captive portal.",
cb_data->uri, cb_data->response);
_LOG2I ("response did not match expected response '%s'; assuming captive portal.",
cb_data->response);
finish_cb_data (cb_data, NM_CONNECTIVITY_PORTAL);
}
return 0;
@ -435,27 +318,23 @@ timeout_cb (gpointer user_data)
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
CURL *ehandle = cb_data->curl_ehandle;
_LOGI ("Check for uri '%s' timed out.", cb_data->uri);
_LOG2I ("timed out");
finish_cb_data (cb_data, NM_CONNECTIVITY_LIMITED);
curl_multi_remove_handle (priv->curl_mhandle, ehandle);
curl_easy_cleanup (ehandle);
return G_SOURCE_REMOVE;
}
#endif
#define IS_PERIODIC_CHECK(callback) ((callback) == run_check_complete)
void
nm_connectivity_check_async (NMConnectivity *self,
const char *iface,
GAsyncReadyCallback callback,
gpointer user_data)
{
NMConnectivityPrivate *priv;
GSimpleAsyncResult *simple;
#if WITH_CONCHECK
CURL *ehandle = NULL;
#endif
g_return_if_fail (NM_IS_CONNECTIVITY (self));
priv = NM_CONNECTIVITY_GET_PRIVATE (self);
@ -463,7 +342,6 @@ nm_connectivity_check_async (NMConnectivity *self,
simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
nm_connectivity_check_async);
#if WITH_CONCHECK
if (priv->uri && priv->interval && priv->curl_mhandle)
ehandle = curl_easy_init ();
@ -472,16 +350,13 @@ nm_connectivity_check_async (NMConnectivity *self,
cb_data->curl_ehandle = ehandle;
cb_data->request_headers = curl_slist_append (NULL, "Connection: close");
cb_data->ifspec = g_strdup_printf ("if!%s", iface);
cb_data->simple = simple;
cb_data->uri = g_strdup (priv->uri);
if (priv->response)
cb_data->response = g_strdup (priv->response);
else
cb_data->response = g_strdup (NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE);
/* For internal calls (periodic), remember the check-id at time of scheduling. */
cb_data->check_id_when_scheduled = IS_PERIODIC_CHECK (callback) ? priv->check_id : 0;
curl_easy_setopt (ehandle, CURLOPT_URL, priv->uri);
curl_easy_setopt (ehandle, CURLOPT_WRITEFUNCTION, easy_write_cb);
curl_easy_setopt (ehandle, CURLOPT_WRITEDATA, cb_data);
@ -489,23 +364,18 @@ nm_connectivity_check_async (NMConnectivity *self,
curl_easy_setopt (ehandle, CURLOPT_HEADERDATA, cb_data);
curl_easy_setopt (ehandle, CURLOPT_PRIVATE, cb_data);
curl_easy_setopt (ehandle, CURLOPT_HTTPHEADER, cb_data->request_headers);
curl_easy_setopt (ehandle, CURLOPT_INTERFACE, cb_data->ifspec);
curl_multi_add_handle (priv->curl_mhandle, ehandle);
cb_data->timeout_id = g_timeout_add_seconds (30, timeout_cb, cb_data);
priv->initial_check_obsoleted = TRUE;
_LOGD ("check: send %s request to '%s'", IS_PERIODIC_CHECK (callback) ? "periodic " : "", priv->uri);
_LOG2D ("sending request to '%s'", priv->uri);
return;
} else {
g_warn_if_fail (!IS_PERIODIC_CHECK (callback));
_LOGD ("check: faking request. Connectivity check disabled");
_LOGD ("(%s) faking request. Connectivity check disabled", iface);
}
#else
_LOGD ("check: faking request. Compiled without connectivity-check support");
#endif
g_simple_async_result_set_op_res_gssize (simple, priv->state);
g_simple_async_result_set_op_res_gssize (simple, NM_CONNECTIVITY_UNKNOWN);
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
}
@ -527,117 +397,99 @@ nm_connectivity_check_finish (NMConnectivity *self,
/*****************************************************************************/
static void
get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
static gboolean
periodic_check (gpointer user_data)
{
NMConnectivity *self = NM_CONNECTIVITY (object);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
switch (property_id) {
case PROP_URI:
g_value_set_string (value, priv->uri);
break;
case PROP_INTERVAL:
g_value_set_uint (value, priv->interval);
break;
case PROP_RESPONSE:
if (priv->response)
g_value_set_string (value, priv->response);
else
g_value_set_static_string (value, NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE);
break;
case PROP_STATE:
g_value_set_uint (value, priv->state);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
g_signal_emit (NM_CONNECTIVITY (user_data), signals[PERIODIC_CHECK], 0);
return G_SOURCE_CONTINUE;
}
static void
set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
update_config (NMConnectivity *self, NMConfigData *config_data)
{
NMConnectivity *self = NM_CONNECTIVITY (object);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
const char *uri, *response;
guint interval;
gboolean changed;
gboolean changed = FALSE;
switch (property_id) {
case PROP_URI:
uri = g_value_get_string (value);
if (uri && !*uri)
/* Set the URI. */
uri = nm_config_data_get_connectivity_uri (config_data);
if (uri && !*uri)
uri = NULL;
changed = g_strcmp0 (uri, priv->uri) != 0;
if (uri) {
char *scheme = g_uri_parse_scheme (uri);
if (!scheme) {
_LOGE ("invalid URI '%s' for connectivity check.", uri);
uri = NULL;
changed = g_strcmp0 (uri, priv->uri) != 0;
#if WITH_CONCHECK
if (uri) {
char *scheme = g_uri_parse_scheme (uri);
} else if (strcasecmp (scheme, "https") == 0) {
_LOGW ("use of HTTPS for connectivity checking is not reliable and is discouraged (URI: %s)", uri);
} else if (strcasecmp (scheme, "http") != 0) {
_LOGE ("scheme of '%s' uri does't use a scheme that is allowed for connectivity check.", uri);
uri = NULL;
}
if (!scheme) {
_LOGE ("invalid URI '%s' for connectivity check.", uri);
uri = NULL;
} else if (strcasecmp (scheme, "https") == 0) {
_LOGW ("use of HTTPS for connectivity checking is not reliable and is discouraged (URI: %s)", uri);
} else if (strcasecmp (scheme, "http") != 0) {
_LOGE ("scheme of '%s' uri does't use a scheme that is allowed for connectivity check.", uri);
uri = NULL;
}
if (scheme)
g_free (scheme);
}
if (changed) {
g_free (priv->uri);
priv->uri = g_strdup (uri);
}
if (scheme)
g_free (scheme);
}
#endif
if (changed) {
g_free (priv->uri);
priv->uri = g_strdup (uri);
_reschedule_periodic_checks (self, TRUE);
}
break;
case PROP_INTERVAL:
interval = g_value_get_uint (value);
if (priv->interval != interval) {
priv->interval = interval;
_reschedule_periodic_checks (self, TRUE);
}
break;
case PROP_RESPONSE:
response = g_value_get_string (value);
if (g_strcmp0 (response, priv->response) != 0) {
/* a response %NULL means, NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE. Any other response
* (including "") is accepted. */
g_free (priv->response);
priv->response = g_strdup (response);
_reschedule_periodic_checks (self, TRUE);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
/* Set the interval. */
interval = nm_config_data_get_connectivity_interval (config_data);
if (priv->interval != interval) {
priv->interval = interval;
changed = TRUE;
}
/* Set the response. */
response = nm_config_data_get_connectivity_response (config_data);
if (g_strcmp0 (response, priv->response) != 0) {
/* a response %NULL means, NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE. Any other response
* (including "") is accepted. */
g_free (priv->response);
priv->response = g_strdup (response);
changed = TRUE;
}
if (changed) {
nm_clear_g_source (&priv->periodic_check_id);
priv->periodic_check_id = g_timeout_add_seconds (priv->interval, periodic_check, self);
}
}
/*****************************************************************************/
static void
config_changed_cb (NMConfig *config,
NMConfigData *config_data,
NMConfigChangeFlags changes,
NMConfigData *old_data,
NMConnectivity *self)
{
update_config (self, config_data);
}
static void
nm_connectivity_init (NMConnectivity *self)
{
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
#if WITH_CONCHECK
CURLcode retv;
#endif
priv->state = NM_CONNECTIVITY_NONE;
#if WITH_CONCHECK
priv->config = g_object_ref (nm_config_get ());
update_config (self, nm_config_get_data (priv->config));
g_signal_connect (G_OBJECT (priv->config),
NM_CONFIG_SIGNAL_CONFIG_CHANGED,
G_CALLBACK (config_changed_cb),
self);
retv = curl_global_init (CURL_GLOBAL_ALL);
if (retv == CURLE_OK)
priv->curl_mhandle = curl_multi_init ();
if (priv->curl_mhandle == NULL) {
_LOGE ("Unable to init cURL, connectivity check will not work");
_LOGE ("cnable to init cURL, connectivity check will not work");
return;
}
@ -646,19 +498,6 @@ nm_connectivity_init (NMConnectivity *self)
curl_multi_setopt (priv->curl_mhandle, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
curl_multi_setopt (priv->curl_mhandle, CURLMOPT_TIMERDATA, self);
curl_multi_setopt (priv->curl_mhandle, CURLOPT_VERBOSE, 1);
#endif
}
NMConnectivity *
nm_connectivity_new (const char *uri,
guint interval,
const char *response)
{
return g_object_new (NM_TYPE_CONNECTIVITY,
NM_CONNECTIVITY_URI, uri,
NM_CONNECTIVITY_INTERVAL, interval,
NM_CONNECTIVITY_RESPONSE, response,
NULL);
}
static void
@ -670,12 +509,14 @@ dispose (GObject *object)
g_clear_pointer (&priv->uri, g_free);
g_clear_pointer (&priv->response, g_free);
#if WITH_CONCHECK
if (priv->config) {
g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self);
g_clear_object (&priv->config);
}
curl_multi_cleanup (priv->curl_mhandle);
curl_global_cleanup ();
nm_clear_g_source (&priv->check_id);
#endif
nm_clear_g_source (&priv->periodic_check_id);
G_OBJECT_CLASS (nm_connectivity_parent_class)->dispose (object);
}
@ -685,36 +526,12 @@ nm_connectivity_class_init (NMConnectivityClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = set_property;
object_class->get_property = get_property;
signals[PERIODIC_CHECK] =
g_signal_new (NM_CONNECTIVITY_PERIODIC_CHECK,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
object_class->dispose = dispose;
obj_properties[PROP_URI] =
g_param_spec_string (NM_CONNECTIVITY_URI, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_INTERVAL] =
g_param_spec_uint (NM_CONNECTIVITY_INTERVAL, "", "",
0, G_MAXUINT, NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_RESPONSE] =
g_param_spec_string (NM_CONNECTIVITY_RESPONSE, "", "",
NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_STATE] =
g_param_spec_uint (NM_CONNECTIVITY_STATE, "", "",
NM_CONNECTIVITY_UNKNOWN, NM_CONNECTIVITY_FULL, NM_CONNECTIVITY_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}

View file

@ -16,6 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2011 Thomas Bechtold <thomasbechtold@jpberlin.de>
* Copyright (C) 2017 Red Hat, Inc.
*/
#ifndef __NETWORKMANAGER_CONNECTIVITY_H__
@ -30,27 +31,18 @@
#define NM_IS_CONNECTIVITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONNECTIVITY))
#define NM_CONNECTIVITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONNECTIVITY, NMConnectivityClass))
#define NM_CONNECTIVITY_URI "uri"
#define NM_CONNECTIVITY_INTERVAL "interval"
#define NM_CONNECTIVITY_RESPONSE "response"
#define NM_CONNECTIVITY_STATE "state"
#define NM_CONNECTIVITY_PERIODIC_CHECK "nm-connectivity-periodic-check"
typedef struct _NMConnectivityClass NMConnectivityClass;
GType nm_connectivity_get_type (void);
NMConnectivity *nm_connectivity_get (void);
const char *nm_connectivity_state_to_string (NMConnectivityState state);
NMConnectivity *nm_connectivity_new (const char *uri,
guint interval,
const char *response);
void nm_connectivity_set_online (NMConnectivity *self,
gboolean online);
NMConnectivityState nm_connectivity_get_state (NMConnectivity *self);
void nm_connectivity_check_async (NMConnectivity *self,
const char *iface,
GAsyncReadyCallback callback,
gpointer user_data);
NMConnectivityState nm_connectivity_check_finish (NMConnectivity *self,

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2004 - 2012 Red Hat, Inc.
* Copyright (C) 2004 - 2017 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
*/
@ -507,6 +507,7 @@ _dispatcher_call (NMDispatcherAction action,
GError *error = NULL;
static guint request_counter = 0;
guint reqid = ++request_counter;
const char *connectivity_state_string = "UNKNOWN";
if (!dispatcher_proxy)
return FALSE;
@ -616,6 +617,10 @@ _dispatcher_call (NMDispatcherAction action,
if (!device_dhcp6_props)
device_dhcp6_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0));
#if WITH_CONCHECK
connectivity_state_string = nm_connectivity_state_to_string (connectivity_state);
#endif
/* Send the action to the dispatcher */
if (blocking) {
GVariant *ret;
@ -632,7 +637,7 @@ _dispatcher_call (NMDispatcherAction action,
&device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
nm_connectivity_state_to_string (connectivity_state),
connectivity_state_string,
vpn_iface ? vpn_iface : "",
&vpn_proxy_props,
&vpn_ip4_props,
@ -670,7 +675,7 @@ _dispatcher_call (NMDispatcherAction action,
&device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
nm_connectivity_state_to_string (connectivity_state),
connectivity_state_string,
vpn_iface ? vpn_iface : "",
&vpn_proxy_props,
&vpn_ip4_props,

View file

@ -16,7 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2007 - 2009 Novell, Inc.
* Copyright (C) 2007 - 2012 Red Hat, Inc.
* Copyright (C) 2007 - 2017 Red Hat, Inc.
*/
#include "nm-default.h"
@ -54,6 +54,7 @@
#include "nm-dbus-compat.h"
#include "nm-checkpoint.h"
#include "nm-checkpoint-manager.h"
#include "nm-dispatcher.h"
#include "NetworkManagerUtils.h"
#include "introspection/org.freedesktop.NetworkManager.h"
@ -117,7 +118,7 @@ typedef struct {
GSList *devices;
NMState state;
NMConfig *config;
NMConnectivity *connectivity;
NMConnectivityState connectivity_state;
NMPolicy *policy;
@ -497,12 +498,6 @@ active_connection_get_by_path (NMManager *manager, const char *path)
static void
_config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeFlags changes, NMConfigData *old_data, NMManager *self)
{
g_object_set (NM_MANAGER_GET_PRIVATE (self)->connectivity,
NM_CONNECTIVITY_URI, nm_config_data_get_connectivity_uri (config_data),
NM_CONNECTIVITY_INTERVAL, nm_config_data_get_connectivity_interval (config_data),
NM_CONNECTIVITY_RESPONSE, nm_config_data_get_connectivity_response (config_data),
NULL);
if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG))
_notify (self, PROP_GLOBAL_DNS_CONFIGURATION);
}
@ -770,27 +765,8 @@ set_state (NMManager *self, NMState state)
g_signal_emit (self, signals[STATE_CHANGED], 0, priv->state);
}
static void
checked_connectivity (GObject *object, GAsyncResult *result, gpointer user_data)
{
NMManager *manager = user_data;
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
NMConnectivityState connectivity;
if (priv->state == NM_STATE_CONNECTING || priv->state == NM_STATE_CONNECTED_SITE) {
connectivity = nm_connectivity_check_finish (priv->connectivity, result, NULL);
if (connectivity == NM_CONNECTIVITY_FULL)
set_state (manager, NM_STATE_CONNECTED_GLOBAL);
_notify (manager, PROP_CONNECTIVITY);
}
g_object_unref (manager);
}
static NMState
find_best_device_state (NMManager *manager, gboolean *force_connectivity_check)
find_best_device_state (NMManager *manager)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
NMState best_state = NM_STATE_DISCONNECTED;
@ -804,11 +780,10 @@ find_best_device_state (NMManager *manager, gboolean *force_connectivity_check)
case NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
if ( nm_active_connection_get_default (ac)
|| nm_active_connection_get_default6 (ac)) {
if (nm_connectivity_get_state (priv->connectivity) == NM_CONNECTIVITY_FULL)
if (priv->connectivity_state)
return NM_STATE_CONNECTED_GLOBAL;
best_state = NM_STATE_CONNECTED_SITE;
NM_SET_OUT (force_connectivity_check, TRUE);
} else {
if (best_state < NM_STATE_CONNECTING)
best_state = NM_STATE_CONNECTED_LOCAL;
@ -866,7 +841,6 @@ nm_manager_update_state (NMManager *manager)
{
NMManagerPrivate *priv;
NMState new_state = NM_STATE_DISCONNECTED;
gboolean force_connectivity_check = FALSE;
g_return_if_fail (NM_IS_MANAGER (manager));
@ -875,27 +849,11 @@ nm_manager_update_state (NMManager *manager)
if (manager_sleeping (manager))
new_state = NM_STATE_ASLEEP;
else
new_state = find_best_device_state (manager, &force_connectivity_check);
new_state = find_best_device_state (manager);
nm_connectivity_set_online (priv->connectivity, new_state >= NM_STATE_CONNECTED_LOCAL);
if (new_state == NM_STATE_CONNECTED_SITE) {
/* We have a default route, let's see if we can reach the Internet or a
* captive portal. */
force_connectivity_check = TRUE;
}
if (new_state == NM_STATE_CONNECTED_LOCAL) {
/* If we just lost a default route, let's retrigger the connectivity check
* so that the connectivity property would be updated to indicate we can't
* reach the Internet anymore. */
force_connectivity_check = TRUE;
}
if (force_connectivity_check) {
nm_connectivity_check_async (priv->connectivity,
checked_connectivity,
g_object_ref (manager));
if ( new_state >= NM_STATE_CONNECTED_LOCAL
&& priv->connectivity_state == NM_CONNECTIVITY_FULL) {
new_state = NM_STATE_CONNECTED_GLOBAL;
}
set_state (manager, new_state);
@ -2008,6 +1966,36 @@ device_realized (NMDevice *device,
_notify (self, PROP_DEVICES);
}
#if WITH_CONCHECK
static void
device_connectivity_changed (NMDevice *device,
GParamSpec *pspec,
NMManager *self)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMConnectivityState best_state = NM_CONNECTIVITY_UNKNOWN;
NMConnectivityState state;
const GSList *devices;
for (devices = priv->devices; devices; devices = devices->next) {
state = nm_device_get_connectivity_state (NM_DEVICE (devices->data));
if (state > best_state)
best_state = state;
}
if (best_state != priv->connectivity_state) {
priv->connectivity_state = best_state;
_LOGD (LOGD_CORE, "connectivity checking indicates %s",
nm_connectivity_state_to_string (priv->connectivity_state));
nm_manager_update_state (self);
_notify (self, PROP_CONNECTIVITY);
nm_dispatcher_call_connectivity (priv->connectivity_state, NULL, NULL, NULL);
}
}
#endif
static void
_device_realize_finish (NMManager *self,
NMDevice *device,
@ -2112,6 +2100,12 @@ add_device (NMManager *self, NMDevice *device, GError **error)
G_CALLBACK (device_realized),
self);
#if WITH_CONCHECK
g_signal_connect (device, "notify::" NM_DEVICE_CONNECTIVITY,
G_CALLBACK (device_connectivity_changed),
self);
#endif
if (priv->startup) {
g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION,
G_CALLBACK (device_has_pending_action_changed),
@ -4826,24 +4820,36 @@ impl_manager_get_logging (NMManager *manager,
nm_logging_domains_to_string ()));
}
static void
connectivity_check_done (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GDBusMethodInvocation *context = user_data;
typedef struct {
guint remaining;
GDBusMethodInvocation *context;
NMConnectivityState state;
GError *error = NULL;
} ConnectivityCheckData;
state = nm_connectivity_check_finish (NM_CONNECTIVITY (object), result, &error);
if (error)
g_dbus_method_invocation_take_error (context, error);
else {
g_dbus_method_invocation_return_value (context,
g_variant_new ("(u)", state));
static void
device_connectivity_done (NMDevice *device, NMConnectivityState state, gpointer user_data)
{
ConnectivityCheckData *data = user_data;
data->remaining--;
/* We check if the state is already FULL so that we can provide the
* response without waiting for slower devices that are not going to
* affect the overall state anyway. */
if (data->state != NM_CONNECTIVITY_FULL) {
if (state > data->state)
data->state = state;
if (data->state == NM_CONNECTIVITY_FULL || !data->remaining) {
g_dbus_method_invocation_return_value (data->context,
g_variant_new ("(u)", data->state));
}
}
}
if (!data->remaining)
g_slice_free (ConnectivityCheckData, data);
}
static void
check_connectivity_auth_done_cb (NMAuthChain *chain,
@ -4855,6 +4861,8 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *error = NULL;
NMAuthCallResult result;
ConnectivityCheckData *data;
const GSList *devices;
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
@ -4872,9 +4880,15 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
"Not authorized to recheck connectivity");
} else {
/* it's allowed */
nm_connectivity_check_async (priv->connectivity,
connectivity_check_done,
context);
data = g_slice_new0 (ConnectivityCheckData);
data->context = context;
for (devices = priv->devices; devices; devices = devices->next) {
data->remaining++;
nm_device_check_connectivity (NM_DEVICE (devices->data),
device_connectivity_done,
data);
}
}
if (error)
@ -5085,20 +5099,6 @@ handle_firmware_changed (gpointer user_data)
return FALSE;
}
static void
connectivity_changed (NMConnectivity *connectivity,
GParamSpec *pspec,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
_LOGD (LOGD_CORE, "connectivity checking indicates %s",
nm_connectivity_state_to_string (nm_connectivity_get_state (connectivity)));
nm_manager_update_state (self);
_notify (self, PROP_CONNECTIVITY);
}
static void
firmware_dir_changed (GFileMonitor *monitor,
GFile *file,
@ -5906,7 +5906,6 @@ constructed (GObject *object)
{
NMManager *self = NM_MANAGER (object);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMConfigData *config_data;
const NMConfigState *state;
G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object);
@ -5949,13 +5948,6 @@ constructed (GObject *object)
G_CALLBACK (_config_changed_cb),
self);
config_data = nm_config_get_data (priv->config);
priv->connectivity = nm_connectivity_new (nm_config_data_get_connectivity_uri (config_data),
nm_config_data_get_connectivity_interval (config_data),
nm_config_data_get_connectivity_response (config_data));
g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE,
G_CALLBACK (connectivity_changed), self);
state = nm_config_state_get (priv->config);
priv->net_enabled = state->net_enabled;
@ -6111,7 +6103,7 @@ get_property (GObject *object, guint prop_id,
nm_utils_g_value_set_object_path_array (value, priv->active_connections, NULL, NULL);
break;
case PROP_CONNECTIVITY:
g_value_set_uint (value, nm_connectivity_get_state (priv->connectivity));
g_value_set_uint (value, priv->connectivity_state);
break;
case PROP_PRIMARY_CONNECTION:
nm_utils_g_value_set_object_path (value, priv->primary_connection);
@ -6240,10 +6232,6 @@ dispose (GObject *object)
g_signal_handlers_disconnect_by_func (priv->config, _config_changed_cb, manager);
g_clear_object (&priv->config);
}
if (priv->connectivity) {
g_signal_handlers_disconnect_by_func (priv->connectivity, connectivity_changed, manager);
g_clear_object (&priv->connectivity);
}
g_free (priv->hostname);