Merge commit 'origin/master' into btdun

This commit is contained in:
Dan Williams 2009-11-06 13:34:52 -08:00
commit 7d23d8ccdb
20 changed files with 754 additions and 69 deletions

View file

@ -3,19 +3,26 @@
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.IP4Config">
<property name="Addresses" type="aau" access="read">
<tp:docstring>Tuples of IPv4 address/prefix/gateway.</tp:docstring>
<tp:docstring>Array of tuples of IPv4 address/prefix/gateway. All 3
elements of each tuple are in network byte order. Essentially:
[(addr, prefix, gateway), (addr, prefix, gateway), ...]
</tp:docstring>
</property>
<property name="Nameservers" type="au" access="read">
<tp:docstring>The nameservers in use.</tp:docstring>
</property>
<property name="WinsServers" type="au" access="read">
<tp:docstring>The Windows Internet Name Service servers associated with the connection.</tp:docstring>
<tp:docstring>The Windows Internet Name Service servers associated with the connection. Each address is in network byte order.</tp:docstring>
</property>
<property name="Domains" type="as" access="read">
<tp:docstring>A list of domains this address belongs to.</tp:docstring>
</property>
<property name="Routes" type="aau" access="read">
<tp:docstring>Tuples of IPv4 route/prefix/next-hop/metric.</tp:docstring>
<tp:docstring>Tuples of IPv4 route/prefix/next-hop/metric. All 4 elements
of each tuple are in network byte order. 'route' and 'next hop' are IPv4
addresses, while prefix and metric are simple unsigned integers. Essentially:
[(route, prefix, next-hop, metric), (route, prefix, next-hop, metric), ...]
</tp:docstring>
</property>
</interface>
</node>

View file

@ -20,6 +20,17 @@
<property name="Default" type="b" access="read">
<tp:docstring>Whether this active connection is the default connection, i.e. whether it currently owns the default route.</tp:docstring>
</property>
<property name="Vpn" type="b" access="read">
<tp:docstring>Whether this active connection is also a VPN connection.</tp:docstring>
</property>
<signal name="PropertiesChanged">
<arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
<tp:docstring>
A dictionary mapping property names to variant boxed values
</tp:docstring>
</arg>
</signal>
</interface>
<interface name="org.freedesktop.NetworkManager.VPN.Connection">

View file

@ -133,6 +133,10 @@ nm_setting_vpn_add_data_item (NMSettingVPN *setting,
const char *item)
{
g_return_if_fail (NM_IS_SETTING_VPN (setting));
g_return_if_fail (key != NULL);
g_return_if_fail (strlen (key) > 0);
g_return_if_fail (item != NULL);
g_return_if_fail (strlen (item) > 0);
g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data,
g_strdup (key), g_strdup (item));
@ -171,6 +175,10 @@ nm_setting_vpn_add_secret (NMSettingVPN *setting,
const char *secret)
{
g_return_if_fail (NM_IS_SETTING_VPN (setting));
g_return_if_fail (key != NULL);
g_return_if_fail (strlen (key) > 0);
g_return_if_fail (secret != NULL);
g_return_if_fail (strlen (secret) > 0);
g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets,
g_strdup (key), g_strdup (secret));

View file

@ -4,7 +4,11 @@ INCLUDES = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/libnm-util
noinst_PROGRAMS = test-settings-defaults test-crypto test-need-secrets
noinst_PROGRAMS = \
test-settings-defaults \
test-crypto \
test-need-secrets \
test-general
test_settings_defaults_SOURCES = \
test-settings-defaults.c
@ -42,11 +46,24 @@ test_need_secrets_LDADD = \
$(GLIB_LIBS) \
$(DBUS_LIBS)
test_general_SOURCES = \
test-general.c
test_general_CPPFLAGS = \
$(GLIB_CFLAGS) \
$(DBUS_CFLAGS)
test_general_LDADD = \
$(top_builddir)/libnm-util/libnm-util.la \
$(GLIB_LIBS) \
$(DBUS_LIBS)
if WITH_TESTS
check-local: test-settings-defaults test-crypto test-need-secrets
$(abs_builddir)/test-settings-defaults
$(abs_builddir)/test-need-secrets
$(abs_builddir)/test-general
# Cert with 8 bytes of tail padding
$(abs_builddir)/test-crypto \

View file

@ -0,0 +1,151 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 - 2009 Red Hat, Inc.
*
*/
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <string.h>
#include "nm-test-helpers.h"
#include <nm-utils.h>
#include "nm-setting-connection.h"
#include "nm-setting-vpn.h"
static void
vpn_check_func (const char *key, const char *value, gpointer user_data)
{
const char *test = user_data;
if (!strcmp (key, "foobar1")) {
ASSERT (strcmp (value, "blahblah1") == 0,
test, "unexpected vpn item '%s' / '%s'", key, value);
return;
}
if (!strcmp (key, "foobar2")) {
ASSERT (strcmp (value, "blahblah2") == 0,
test, "unexpected vpn item '%s' / '%s'", key, value);
return;
}
if (!strcmp (key, "foobar3")) {
ASSERT (strcmp (value, "blahblah3") == 0,
test, "unexpected vpn item '%s' / '%s'", key, value);
return;
}
if (!strcmp (key, "foobar4")) {
ASSERT (strcmp (value, "blahblah4") == 0,
test, "unexpected vpn item '%s' / '%s'", key, value);
return;
}
ASSERT (FALSE, test, "unexpected vpn item '%s'", key);
}
static void
vpn_check_empty_func (const char *key, const char *value, gpointer user_data)
{
const char *test = user_data;
/* We don't expect any values */
ASSERT (FALSE, test, "unexpected vpn item '%s'", key);
}
static void
test_setting_vpn_items (void)
{
NMSettingVPN *s_vpn;
s_vpn = (NMSettingVPN *) nm_setting_vpn_new ();
ASSERT (s_vpn != NULL,
"vpn-items",
"error creating vpn setting");
nm_setting_vpn_add_data_item (s_vpn, "foobar1", "blahblah1");
nm_setting_vpn_add_data_item (s_vpn, "foobar2", "blahblah2");
nm_setting_vpn_add_data_item (s_vpn, "foobar3", "blahblah3");
nm_setting_vpn_add_data_item (s_vpn, "foobar4", "blahblah4");
/* Ensure that added values are all present */
nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_func, "vpn-data");
nm_setting_vpn_remove_data_item (s_vpn, "foobar1");
nm_setting_vpn_remove_data_item (s_vpn, "foobar2");
nm_setting_vpn_remove_data_item (s_vpn, "foobar3");
nm_setting_vpn_remove_data_item (s_vpn, "foobar4");
nm_setting_vpn_add_secret (s_vpn, "foobar1", "blahblah1");
nm_setting_vpn_add_secret (s_vpn, "foobar2", "blahblah2");
nm_setting_vpn_add_secret (s_vpn, "foobar3", "blahblah3");
nm_setting_vpn_add_secret (s_vpn, "foobar4", "blahblah4");
/* Ensure that added values are all present */
nm_setting_vpn_foreach_secret (s_vpn, vpn_check_func, "vpn-secrets");
nm_setting_vpn_remove_secret (s_vpn, "foobar1");
nm_setting_vpn_remove_secret (s_vpn, "foobar2");
nm_setting_vpn_remove_secret (s_vpn, "foobar3");
nm_setting_vpn_remove_secret (s_vpn, "foobar4");
/* Try to add some blank values and make sure they are rejected */
nm_setting_vpn_add_data_item (s_vpn, NULL, NULL);
nm_setting_vpn_add_data_item (s_vpn, "", "");
nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL);
nm_setting_vpn_add_data_item (s_vpn, "foobar1", "");
nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1");
nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1");
nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, "vpn-data-empty");
/* Try to add some blank secrets and make sure they are rejected */
nm_setting_vpn_add_secret (s_vpn, NULL, NULL);
nm_setting_vpn_add_secret (s_vpn, "", "");
nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL);
nm_setting_vpn_add_secret (s_vpn, "foobar1", "");
nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1");
nm_setting_vpn_add_secret (s_vpn, "", "blahblah1");
nm_setting_vpn_foreach_secret (s_vpn, vpn_check_empty_func, "vpn-secrets-empty");
g_object_unref (s_vpn);
}
int main (int argc, char **argv)
{
GError *error = NULL;
DBusGConnection *bus;
char *base;
g_type_init ();
bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
if (!nm_utils_init (&error))
FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
/* The tests */
test_setting_vpn_items ();
base = g_path_get_basename (argv[0]);
fprintf (stdout, "%s: SUCCESS\n", base);
g_free (base);
return 0;
}

View file

@ -56,6 +56,7 @@
#define NM_DEFAULT_PID_FILE LOCALSTATEDIR"/run/NetworkManager.pid"
#define NM_DEFAULT_SYSTEM_CONF_FILE SYSCONFDIR"/NetworkManager/nm-system-settings.conf"
#define NM_DEFAULT_SYSTEM_STATE_FILE LOCALSTATEDIR"/lib/NetworkManager/NetworkManager.state"
/*
* Globals
@ -227,22 +228,77 @@ setup_signals (void)
sigaction (SIGUSR1, &action, NULL);
}
static void
static gboolean
write_pidfile (const char *pidfile)
{
char pid[16];
int fd;
gboolean success = FALSE;
if ((fd = open (pidfile, O_CREAT|O_WRONLY|O_TRUNC, 00644)) < 0)
{
if ((fd = open (pidfile, O_CREAT|O_WRONLY|O_TRUNC, 00644)) < 0) {
nm_warning ("Opening %s failed: %s", pidfile, strerror (errno));
return;
return FALSE;
}
snprintf (pid, sizeof (pid), "%d", getpid ());
if (write (fd, pid, strlen (pid)) < 0)
nm_warning ("Writing to %s failed: %s", pidfile, strerror (errno));
else
success = TRUE;
if (close (fd))
nm_warning ("Closing %s failed: %s", pidfile, strerror (errno));
return success;
}
/* Check whether the pidfile already exists and contains PID of a running NetworkManager
* Returns: FALSE - specified pidfile doesn't exist or doesn't contain PID of a running NM process
* TRUE - specified pidfile already exists and contains PID of a running NM process
*/
static gboolean
check_pidfile (const char *pidfile)
{
char *contents = NULL;
gsize len = 0;
glong pid;
char *proc_cmdline = NULL;
gboolean nm_running = FALSE;
const char *process_name;
if (!g_file_get_contents (pidfile, &contents, &len, NULL))
return FALSE;
if (len <= 0)
goto done;
errno = 0;
pid = strtol (contents, NULL, 10);
if (pid <= 0 || pid > 65536 || errno)
goto done;
g_free (contents);
proc_cmdline = g_strdup_printf ("/proc/%ld/cmdline", pid);
if (!g_file_get_contents (proc_cmdline, &contents, &len, NULL))
goto done;
process_name = strrchr (contents, '/');
if (process_name)
process_name++;
else
process_name = contents;
if (strcmp (process_name, "NetworkManager") == 0) {
/* Check that the process exists */
if (kill (pid, 0) == 0) {
g_warning ("NetworkManager is already running (pid %ld)", pid);
nm_running = TRUE;
}
}
done:
g_free (proc_cmdline);
g_free (contents);
return nm_running;
}
static gboolean
@ -269,6 +325,94 @@ parse_config_file (const char *filename, char **plugins, GError **error)
return TRUE;
}
static gboolean
parse_state_file (const char *filename,
gboolean *net_enabled,
gboolean *wifi_enabled,
GError **error)
{
GKeyFile *state_file;
GError *tmp_error = NULL;
gboolean wifi, net;
g_return_val_if_fail (net_enabled != NULL, FALSE);
g_return_val_if_fail (wifi_enabled != NULL, FALSE);
state_file = g_key_file_new ();
if (!state_file) {
g_set_error (error, 0, 0,
"Not enough memory to load state file.");
return FALSE;
}
g_key_file_set_list_separator (state_file, ',');
if (!g_key_file_load_from_file (state_file, filename, G_KEY_FILE_KEEP_COMMENTS, &tmp_error)) {
/* This is kinda ugly; create the file and directory if it doesn't
* exist yet. We can't rely on distros necessarily creating the
* /var/lib/NetworkManager for us since we have to ensure that
* users upgrading NM get this working too.
*/
if ( tmp_error->domain == G_FILE_ERROR
&& tmp_error->code == G_FILE_ERROR_NOENT) {
char *data, *dirname;
gsize len = 0;
gboolean ret = FALSE;
/* try to create the directory if it doesn't exist */
dirname = g_path_get_dirname (filename);
errno = 0;
if (mkdir (dirname, 0755) != 0) {
if (errno != EEXIST) {
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES,
"Error creating state directory %s: %d", dirname, errno);
g_free (dirname);
return FALSE;
}
}
g_free (dirname);
/* Write out the initial state to the state file */
g_key_file_set_boolean (state_file, "main", "NetworkingEnabled", *net_enabled);
g_key_file_set_boolean (state_file, "main", "WirelessEnabled", *wifi_enabled);
data = g_key_file_to_data (state_file, &len, NULL);
if (data)
ret = g_file_set_contents (filename, data, len, error);
g_free (data);
return ret;
} else {
g_set_error_literal (error, tmp_error->domain, tmp_error->code, tmp_error->message);
g_clear_error (&tmp_error);
}
/* Otherwise, file probably corrupt or inaccessible */
return FALSE;
}
/* Reading state bits of NetworkManager; an error leaves the passed-in state
* value unchanged.
*/
net = g_key_file_get_boolean (state_file, "main", "NetworkingEnabled", &tmp_error);
if (tmp_error)
g_set_error_literal (error, tmp_error->domain, tmp_error->code, tmp_error->message);
else
*net_enabled = net;
g_clear_error (&tmp_error);
wifi = g_key_file_get_boolean (state_file, "main", "WirelessEnabled", error);
if (tmp_error) {
g_clear_error (error);
g_set_error_literal (error, tmp_error->domain, tmp_error->code, tmp_error->message);
} else
*wifi_enabled = wifi;
g_clear_error (&tmp_error);
g_key_file_free (state_file);
return TRUE;
}
/*
* main
*
@ -281,6 +425,8 @@ main (int argc, char *argv[])
gboolean g_fatal_warnings = FALSE;
char *pidfile = NULL, *user_pidfile = NULL;
char *config = NULL, *plugins = NULL;
char *state_file = NM_DEFAULT_SYSTEM_STATE_FILE;
gboolean wifi_enabled = TRUE, net_enabled = TRUE;
gboolean success;
NMPolicy *policy = NULL;
NMVPNManager *vpn_manager = NULL;
@ -289,11 +435,13 @@ main (int argc, char *argv[])
NMSupplicantManager *sup_mgr = NULL;
NMDHCPManager *dhcp_mgr = NULL;
GError *error = NULL;
gboolean wrote_pidfile = FALSE;
GOptionEntry options[] = {
{ "no-daemon", 0, 0, G_OPTION_ARG_NONE, &become_daemon, "Don't become a daemon", NULL },
{ "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL },
{ "pid-file", 0, 0, G_OPTION_ARG_FILENAME, &user_pidfile, "Specify the location of a PID file", "filename" },
{ "state-file", 0, 0, G_OPTION_ARG_FILENAME, &state_file, "State file location", "/path/to/state.file" },
{ "config", 0, 0, G_OPTION_ARG_FILENAME, &config, "Config file location", "/path/to/config.file" },
{ "plugins", 0, 0, G_OPTION_ARG_STRING, &plugins, "List of plugins separated by ,", "plugin1,plugin2" },
{NULL}
@ -331,6 +479,12 @@ main (int argc, char *argv[])
exit (1);
}
pidfile = g_strdup (user_pidfile ? user_pidfile : NM_DEFAULT_PID_FILE);
/* check pid file */
if (check_pidfile (pidfile))
exit (1);
/* Parse the config file */
if (config) {
if (!parse_config_file (config, &plugins, &error)) {
@ -352,7 +506,16 @@ main (int argc, char *argv[])
}
}
pidfile = g_strdup (user_pidfile ? user_pidfile : NM_DEFAULT_PID_FILE);
g_clear_error (&error);
/* Parse the state file */
if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &error)) {
g_warning ("State file %s parsing failed: (%d) %s.",
state_file,
error ? error->code : -1,
(error && error->message) ? error->message : "unknown");
/* Not a hard failure */
}
/* Tricky: become_daemon is FALSE by default, so unless it's TRUE because
* of a CLI option, it'll become TRUE after this
@ -368,7 +531,8 @@ main (int argc, char *argv[])
saved_errno);
exit (1);
}
write_pidfile (pidfile);
if (write_pidfile (pidfile))
wrote_pidfile = TRUE;
}
if (g_fatal_warnings) {
@ -419,7 +583,7 @@ main (int argc, char *argv[])
goto done;
}
manager = nm_manager_get (config, plugins, &error);
manager = nm_manager_get (config, plugins, state_file, net_enabled, wifi_enabled, &error);
if (manager == NULL) {
nm_error ("Failed to initialize the network manager: %s",
error && error->message ? error->message : "(unknown)");
@ -490,7 +654,7 @@ done:
nm_logging_shutdown ();
if (pidfile)
if (pidfile && wrote_pidfile)
unlink (pidfile);
g_free (pidfile);

View file

@ -42,8 +42,6 @@
#include "nm-vpn-manager.h"
#include "nm-modem.h"
#define STATE_IN_ACTIVATION_PHASE(state) ((state > NM_DEVICE_STATE_DISCONNECTED) && (state < NM_DEVICE_STATE_ACTIVATED))
typedef struct LookupThread LookupThread;
typedef void (*LookupCallback) (LookupThread *thread, gpointer user_data);
@ -711,6 +709,24 @@ hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
update_system_hostname ((NMPolicy *) user_data, NULL);
}
static void
sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
{
gboolean sleeping = FALSE;
GSList *connections, *iter;
g_object_get (G_OBJECT (manager), NM_MANAGER_SLEEPING, &sleeping, NULL);
/* Clear the invalid flag on all connections so they'll get retried on wakeup */
if (sleeping) {
connections = nm_manager_get_connections (manager, NM_CONNECTION_SCOPE_SYSTEM);
connections = g_slist_concat (connections, nm_manager_get_connections (manager, NM_CONNECTION_SCOPE_USER));
for (iter = connections; iter; iter = g_slist_next (iter))
g_object_set_data (G_OBJECT (iter->data), INVALID_TAG, NULL);
g_slist_free (connections);
}
}
static void
schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds)
{
@ -770,7 +786,7 @@ device_state_changed (NMDevice *device,
/* Mark the connection invalid if it failed during activation so that
* it doesn't get automatically chosen over and over and over again.
*/
if (connection && STATE_IN_ACTIVATION_PHASE (old_state)) {
if (connection && IS_ACTIVATING_STATE (old_state)) {
g_object_set_data (G_OBJECT (connection), INVALID_TAG, GUINT_TO_POINTER (TRUE));
nm_info ("Marking connection '%s' invalid.", get_connection_id (connection));
nm_connection_clear_secrets (connection);
@ -992,10 +1008,14 @@ nm_policy_new (NMManager *manager, NMVPNManager *vpn_manager)
G_CALLBACK (global_state_changed), policy);
policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
id = g_signal_connect (manager, "notify::hostname",
id = g_signal_connect (manager, "notify::" NM_MANAGER_HOSTNAME,
G_CALLBACK (hostname_changed), policy);
policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
id = g_signal_connect (manager, "notify::" NM_MANAGER_SLEEPING,
G_CALLBACK (sleeping_changed), policy);
policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
id = g_signal_connect (manager, "device-added",
G_CALLBACK (device_added), policy);
policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);

View file

@ -135,6 +135,7 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
guint32 good_dns1 = htonl (0x04020201); /* GTE nameserver */
guint32 bad_dns2 = htonl (0x0A0B0C0E);
guint32 good_dns2 = htonl (0x04020202); /* GTE nameserver */
gboolean dns_workaround = FALSE;
/* Work around a PPP bug (#1732) which causes many mobile broadband
* providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers.
@ -162,11 +163,13 @@ ppp_ip4_config (NMPPPManager *ppp_manager,
* could actually be valid in some cases, so only substitute if ppp
* returns *only* the two bad nameservers.
*/
if (found1 && found2) {
nm_ip4_config_reset_nameservers (config);
nm_ip4_config_add_nameserver (config, good_dns1);
nm_ip4_config_add_nameserver (config, good_dns2);
}
dns_workaround = (found1 && found2);
}
if (!num || dns_workaround) {
nm_ip4_config_reset_nameservers (config);
nm_ip4_config_add_nameserver (config, good_dns1);
nm_ip4_config_add_nameserver (config, good_dns2);
}
priv->pending_ip4_config = g_object_ref (config);

View file

@ -388,14 +388,29 @@ update_resolv_conf (const char *domain,
const char *iface,
GError **error)
{
const char *tmp_resolv_conf = RESOLV_CONF ".tmp";
char tmp_resolv_conf_realpath [PATH_MAX];
char *tmp_resolv_conf;
char *tmp_resolv_conf_realpath;
char *resolv_conf_realpath;
FILE *f;
int do_rename = 1;
int old_errno = 0;
if (!realpath (tmp_resolv_conf, tmp_resolv_conf_realpath))
strcpy (tmp_resolv_conf_realpath, tmp_resolv_conf);
g_return_val_if_fail (error != NULL, FALSE);
/* Find the real path of resolv.conf; it could be a symlink to something */
resolv_conf_realpath = realpath (RESOLV_CONF, NULL);
if (!resolv_conf_realpath)
resolv_conf_realpath = strdup (RESOLV_CONF);
/* Build up the real path for the temp resolv.conf that we're about to
* write out.
*/
tmp_resolv_conf = g_strdup_printf ("%s.tmp", resolv_conf_realpath);
tmp_resolv_conf_realpath = realpath (tmp_resolv_conf, NULL);
if (!tmp_resolv_conf_realpath)
tmp_resolv_conf_realpath = strdup (tmp_resolv_conf);
g_free (tmp_resolv_conf);
tmp_resolv_conf = NULL;
if ((f = fopen (tmp_resolv_conf_realpath, "w")) == NULL) {
do_rename = 0;
@ -409,8 +424,11 @@ update_resolv_conf (const char *domain,
g_strerror (old_errno),
RESOLV_CONF,
g_strerror (errno));
return FALSE;
goto out;
}
/* Update tmp_resolv_conf_realpath so the error message on fclose()
* failure will be correct.
*/
strcpy (tmp_resolv_conf_realpath, RESOLV_CONF);
}
@ -418,25 +436,34 @@ update_resolv_conf (const char *domain,
if (fclose (f) < 0) {
if (*error == NULL) {
/* only set an error here if write_resolv_conf() was successful,
* since its error is more important.
*/
g_set_error (error,
NM_NAMED_MANAGER_ERROR,
NM_NAMED_MANAGER_ERROR_SYSTEM,
"Could not close %s: %s\n",
tmp_resolv_conf_realpath,
g_strerror (errno));
NM_NAMED_MANAGER_ERROR,
NM_NAMED_MANAGER_ERROR_SYSTEM,
"Could not close %s: %s\n",
tmp_resolv_conf_realpath,
g_strerror (errno));
}
}
/* Don't rename the tempfile over top of the existing resolv.conf if there
* was an error writing it out.
*/
if (*error == NULL && do_rename) {
if (rename (tmp_resolv_conf, RESOLV_CONF) < 0) {
if (rename (tmp_resolv_conf_realpath, resolv_conf_realpath) < 0) {
g_set_error (error,
NM_NAMED_MANAGER_ERROR,
NM_NAMED_MANAGER_ERROR_SYSTEM,
"Could not replace " RESOLV_CONF ": %s\n",
g_strerror (errno));
NM_NAMED_MANAGER_ERROR,
NM_NAMED_MANAGER_ERROR_SYSTEM,
"Could not replace " RESOLV_CONF ": %s\n",
g_strerror (errno));
}
}
out:
free (tmp_resolv_conf_realpath);
free (resolv_conf_realpath);
return *error ? FALSE : TRUE;
}

View file

@ -120,6 +120,8 @@ real_connection_secrets_updated (NMDevice *device,
NMDeviceCdmaPrivate *priv = NM_DEVICE_CDMA_GET_PRIVATE (device);
NMActRequest *req;
g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device)));
req = nm_device_get_act_request (device);
g_assert (req);

View file

@ -632,8 +632,7 @@ real_connection_secrets_updated (NMDevice *dev,
gboolean valid = FALSE;
GSList *iter;
if (nm_device_get_state (dev) != NM_DEVICE_STATE_NEED_AUTH)
return;
g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (dev)));
/* PPPoE? */
if (caller == SECRETS_CALLER_PPP) {
@ -663,6 +662,7 @@ real_connection_secrets_updated (NMDevice *dev,
/* Only caller could be ourselves for 802.1x */
g_return_if_fail (caller == SECRETS_CALLER_ETHERNET);
g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
for (iter = updated_settings; iter; iter = g_slist_next (iter)) {
const char *setting_name = (const char *) iter->data;
@ -1850,7 +1850,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
"Ifindex",
"Interface index",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
/* Signals */
signals[PROPERTIES_CHANGED] =

View file

@ -120,6 +120,8 @@ real_connection_secrets_updated (NMDevice *device,
NMDeviceGsmPrivate *priv = NM_DEVICE_GSM_GET_PRIVATE (device);
NMActRequest *req;
g_return_if_fail (IS_ACTIVATING_STATE (nm_device_get_state (device)));
req = nm_device_get_act_request (device);
g_assert (req);

View file

@ -151,7 +151,7 @@ nm_device_interface_init (gpointer g_iface)
"DeviceType",
"DeviceType",
0, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
g_object_interface_install_property
(g_iface, g_param_spec_boolean (NM_DEVICE_INTERFACE_MANAGED,

View file

@ -32,6 +32,9 @@
#define NM_IS_DEVICE_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INTERFACE))
#define NM_DEVICE_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_DEVICE_INTERFACE, NMDeviceInterface))
#define IS_ACTIVATING_STATE(state) \
(state > NM_DEVICE_STATE_DISCONNECTED && state < NM_DEVICE_STATE_ACTIVATED)
typedef enum
{
NM_DEVICE_INTERFACE_ERROR_CONNECTION_ACTIVATING = 0,

View file

@ -909,7 +909,7 @@ check_companion_cb (gpointer user_data)
if (priv->device_added_cb != 0)
return FALSE;
manager = nm_manager_get (NULL, NULL, NULL);
manager = nm_manager_get (NULL, NULL, NULL, FALSE, FALSE, NULL);
priv->device_added_cb = g_signal_connect (manager, "device-added",
G_CALLBACK (device_added_cb), self);

View file

@ -3589,7 +3589,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
"Ifindex",
"Interface index",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT));
g_object_class_install_property (object_class, PROP_SCANNING,
g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING,

View file

@ -151,6 +151,7 @@ typedef struct {
typedef struct {
char *config_file;
char *state_file;
GSList *devices;
NMState state;
@ -216,6 +217,7 @@ enum {
/* Not exported */
PROP_HOSTNAME,
PROP_SLEEPING,
LAST_PROP
};
@ -1102,11 +1104,62 @@ nm_manager_name_owner_changed (NMDBusManager *mgr,
}
}
/* Store value into key-file; supported types: boolean, int, string */
static gboolean
write_value_to_state_file (const char *filename,
const char *group,
const char *key,
GType value_type,
gpointer value,
GError **error)
{
GKeyFile *key_file;
char *data;
gsize len = 0;
gboolean ret = FALSE;
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (group != NULL, FALSE);
g_return_val_if_fail (key != NULL, FALSE);
g_return_val_if_fail (value_type == G_TYPE_BOOLEAN ||
value_type == G_TYPE_INT ||
value_type == G_TYPE_STRING,
FALSE);
key_file = g_key_file_new ();
if (!key_file)
return FALSE;
g_key_file_set_list_separator (key_file, ',');
g_key_file_load_from_file (key_file, filename, G_KEY_FILE_KEEP_COMMENTS, NULL);
switch (value_type) {
case G_TYPE_BOOLEAN:
g_key_file_set_boolean (key_file, group, key, *((gboolean *) value));
break;
case G_TYPE_INT:
g_key_file_set_integer (key_file, group, key, *((gint *) value));
break;
case G_TYPE_STRING:
g_key_file_set_string (key_file, group, key, *((const gchar **) value));
break;
}
data = g_key_file_to_data (key_file, &len, NULL);
if (data) {
ret = g_file_set_contents (filename, data, len, error);
g_free (data);
}
g_key_file_free (key_file);
return ret;
}
static void
manager_set_wireless_enabled (NMManager *manager, gboolean enabled)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
GSList *iter;
GError *error = NULL;
if (priv->wireless_enabled == enabled)
return;
@ -1119,6 +1172,19 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled)
g_object_notify (G_OBJECT (manager), NM_MANAGER_WIRELESS_ENABLED);
/* Update "WirelessEnabled" key in state file */
if (priv->state_file) {
if (!write_value_to_state_file (priv->state_file,
"main", "WirelessEnabled",
G_TYPE_BOOLEAN, (gpointer) &priv->wireless_enabled,
&error)) {
g_warning ("Writing to state file %s failed: (%d) %s.",
priv->state_file,
error ? error->code : -1,
(error && error->message) ? error->message : "unknown");
}
}
/* Don't touch devices if asleep/networking disabled */
if (priv->sleeping)
return;
@ -2401,6 +2467,23 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error)
priv->sleeping = sleep;
/* Update "NetworkingEnabled" key in state file */
if (priv->state_file) {
GError *err = NULL;
gboolean networking_enabled = !sleep;
if (!write_value_to_state_file (priv->state_file,
"main", "NetworkingEnabled",
G_TYPE_BOOLEAN, (gpointer) &networking_enabled,
&err)) {
g_warning ("Writing to state file %s failed: (%d) %s.",
priv->state_file,
err ? err->code : -1,
(err && err->message) ? err->message : "unknown");
}
}
if (sleep) {
nm_info ("Sleeping...");
@ -2432,6 +2515,8 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error)
}
nm_manager_update_state (self);
g_object_notify (G_OBJECT (self), NM_MANAGER_SLEEPING);
return TRUE;
}
@ -2569,9 +2654,10 @@ nm_manager_start (NMManager *self)
break;
}
nm_info ("Wireless now %s by radio killswitch",
(priv->wireless_hw_enabled && we) ? "enabled" : "disabled");
manager_set_wireless_enabled (self, we);
nm_info ("Wireless %s by radio killswitch; %s by state file",
(priv->wireless_hw_enabled && we) ? "enabled" : "disabled",
(priv->wireless_enabled) ? "enabled" : "disabled");
manager_set_wireless_enabled (self, priv->wireless_enabled && we);
system_unmanaged_devices_changed_cb (priv->sys_settings, NULL, self);
system_hostname_changed_cb (priv->sys_settings, NULL, self);
@ -2589,7 +2675,12 @@ nm_manager_start (NMManager *self)
}
NMManager *
nm_manager_get (const char *config_file, const char *plugins, GError **error)
nm_manager_get (const char *config_file,
const char *plugins,
const char *state_file,
gboolean initial_net_enabled,
gboolean initial_wifi_enabled,
GError **error)
{
static NMManager *singleton = NULL;
NMManagerPrivate *priv;
@ -2615,6 +2706,12 @@ nm_manager_get (const char *config_file, const char *plugins, GError **error)
priv->config_file = g_strdup (config_file);
priv->state_file = g_strdup (state_file);
priv->sleeping = !initial_net_enabled;
priv->wireless_enabled = initial_wifi_enabled;
g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS,
G_CALLBACK (system_unmanaged_devices_changed_cb), singleton);
g_signal_connect (priv->sys_settings, "notify::" NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME,
@ -2764,6 +2861,9 @@ get_property (GObject *object, guint prop_id,
case PROP_HOSTNAME:
g_value_set_string (value, priv->hostname);
break;
case PROP_SLEEPING:
g_value_set_boolean (value, priv->sleeping);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -2887,6 +2987,14 @@ nm_manager_class_init (NMManagerClass *manager_class)
NULL,
G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
g_object_class_install_property
(object_class, PROP_SLEEPING,
g_param_spec_boolean (NM_MANAGER_SLEEPING,
"Sleeping",
"Sleeping",
FALSE,
G_PARAM_READABLE | NM_PROPERTY_PARAM_NO_EXPORT));
/* signals */
signals[DEVICE_ADDED] =
g_signal_new ("device-added",

View file

@ -42,6 +42,7 @@
/* Not exported */
#define NM_MANAGER_HOSTNAME "hostname"
#define NM_MANAGER_SLEEPING "sleeping"
typedef struct {
GObject parent;
@ -73,7 +74,12 @@ typedef struct {
GType nm_manager_get_type (void);
NMManager *nm_manager_get (const char *config_file, const char *plugins, GError **error);
NMManager *nm_manager_get (const char *config_file,
const char *plugins,
const char *state_file,
gboolean initial_net_enabled,
gboolean initial_wifi_enabled,
GError **error);
void nm_manager_start (NMManager *manager);

View file

@ -42,6 +42,7 @@ G_DEFINE_TYPE_EXTENDED (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_
typedef struct {
PolkitAuthority *authority;
GSList *pk_calls;
} NMSysconfigConnectionPrivate;
/**************************************************************/
@ -167,6 +168,7 @@ typedef struct {
DBusGMethodInvocation *context;
PolkitSubject *subject;
GCancellable *cancellable;
gboolean disposed;
/* Update */
NMConnection *connection;
@ -242,11 +244,26 @@ pk_update_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigConnection *self = call->self;
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
NMSysconfigConnectionPrivate *priv;
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
GHashTable *settings;
/* If our NMSysconfigConnection is already gone, do nothing */
if (call->disposed) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Request was canceled.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
@ -321,6 +338,7 @@ dbus_update (NMExportedConnection *exported,
call->cancellable,
pk_update_cb,
call);
priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
}
static void
@ -343,10 +361,25 @@ pk_delete_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigConnection *self = call->self;
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
NMSysconfigConnectionPrivate *priv;
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
/* If our NMSysconfigConnection is already gone, do nothing */
if (call->disposed) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Request was canceled.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
@ -396,6 +429,7 @@ dbus_delete (NMExportedConnection *exported,
call->cancellable,
pk_delete_cb,
call);
priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
}
static void
@ -419,10 +453,25 @@ pk_secrets_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigConnection *self = call->self;
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
NMSysconfigConnectionPrivate *priv;
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
/* If our NMSysconfigConnection is already gone, do nothing */
if (call->disposed) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Request was canceled.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
@ -478,6 +527,7 @@ dbus_get_secrets (NMExportedConnection *exported,
call->cancellable,
pk_secrets_cb,
call);
priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
}
/**************************************************************/
@ -501,10 +551,19 @@ nm_sysconfig_connection_init (NMSysconfigConnection *self)
static void
dispose (GObject *object)
{
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (object);
NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (object);
NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
GSList *iter;
if (priv->authority)
g_object_unref (priv->authority);
/* Cancel PolicyKit requests */
for (iter = priv->pk_calls; iter; iter = g_slist_next (iter)) {
PolkitCall *call = iter->data;
call->disposed = TRUE;
g_cancellable_cancel (call->cancellable);
}
g_slist_free (priv->pk_calls);
priv->pk_calls = NULL;
G_OBJECT_CLASS (nm_sysconfig_connection_parent_class)->dispose (object);
}

View file

@ -79,8 +79,12 @@ static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer u
typedef struct {
PolkitAuthority *authority;
guint auth_changed_id;
char *config_file;
GSList *pk_calls;
GSList *permissions_calls;
GSList *plugins;
gboolean connections_loaded;
GHashTable *connections;
@ -516,6 +520,8 @@ typedef struct {
NMSysconfigSettings *self;
DBusGMethodInvocation *context;
PolkitSubject *subject;
GCancellable *cancellable;
gboolean disposed;
NMConnection *connection;
NMSettingsAddConnectionFunc callback;
@ -545,6 +551,7 @@ polkit_call_new (NMSysconfigSettings *self,
call = g_malloc0 (sizeof (PolkitCall));
call->self = self;
call->cancellable = g_cancellable_new ();
call->context = context;
if (connection)
call->connection = g_object_ref (connection);
@ -567,6 +574,7 @@ polkit_call_free (PolkitCall *call)
{
if (call->connection)
g_object_unref (call->connection);
g_object_unref (call->cancellable);
g_free (call->hostname);
g_object_unref (call->subject);
g_free (call);
@ -610,10 +618,25 @@ pk_add_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigSettings *self = call->self;
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
NMSysconfigSettingsPrivate *priv;
PolkitAuthorizationResult *pk_result;
GError *error = NULL, *add_error = NULL;
/* If NMSysconfigSettings is already gone, do nothing */
if (call->disposed) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Request was canceled.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
@ -680,9 +703,10 @@ add_connection (NMSettingsService *service,
NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
NULL,
call->cancellable,
pk_add_cb,
call);
priv->pk_calls = g_slist_append (priv->pk_calls, call);
}
static void
@ -690,12 +714,27 @@ pk_hostname_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
PolkitCall *call = user_data;
NMSysconfigSettings *self = call->self;
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
NMSysconfigSettingsPrivate *priv;
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
GSList *iter;
gboolean success = FALSE;
/* If our NMSysconfigConnection is already gone, do nothing */
if (call->disposed) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Request was canceled.");
dbus_g_method_return_error (call->context, error);
g_error_free (error);
polkit_call_free (call);
return;
}
priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
priv->pk_calls = g_slist_remove (priv->pk_calls, call);
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
@ -767,9 +806,10 @@ impl_settings_save_hostname (NMSysconfigSettings *self,
NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY,
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
NULL,
call->cancellable,
pk_hostname_cb,
call);
priv->pk_calls = g_slist_append (priv->pk_calls, call);
}
static void
@ -783,7 +823,9 @@ pk_authority_changed_cb (GObject *object, gpointer user_data)
typedef struct {
PolkitCall *pk_call;
const char *pk_action;
GCancellable *cancellable;
NMSettingsSystemPermissions permission;
gboolean disposed;
} PermissionsCall;
static void
@ -792,10 +834,18 @@ permission_call_done (GObject *object, GAsyncResult *result, gpointer user_data)
PermissionsCall *call = user_data;
PolkitCall *pk_call = call->pk_call;
NMSysconfigSettings *self = pk_call->self;
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
NMSysconfigSettingsPrivate *priv;
PolkitAuthorizationResult *pk_result;
GError *error = NULL;
/* If NMSysconfigSettings is gone, just skip to the end */
if (call->disposed)
goto done;
priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
priv->permissions_calls = g_slist_remove (priv->permissions_calls, call);
pk_result = polkit_authority_check_authorization_finish (priv->authority,
result,
&error);
@ -820,12 +870,21 @@ permission_call_done (GObject *object, GAsyncResult *result, gpointer user_data)
g_object_unref (pk_result);
done:
pk_call->permissions_calls--;
if (pk_call->permissions_calls == 0) {
/* All the permissions calls are done, return the full permissions
* bitfield back to the user.
*/
dbus_g_method_return (pk_call->context, pk_call->permissions);
if (call->disposed) {
error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
"Request was canceled.");
dbus_g_method_return_error (pk_call->context, error);
g_error_free (error);
} else {
/* All the permissions calls are done, return the full permissions
* bitfield back to the user.
*/
dbus_g_method_return (pk_call->context, pk_call->permissions);
}
polkit_call_free (pk_call);
}
@ -850,6 +909,7 @@ start_permission_check (NMSysconfigSettings *self,
call->pk_call = pk_call;
call->pk_action = pk_action;
call->permission = permission;
call->cancellable = g_cancellable_new ();
pk_call->permissions_calls++;
@ -858,9 +918,10 @@ start_permission_check (NMSysconfigSettings *self,
pk_action,
NULL,
0,
NULL,
call->cancellable,
permission_call_done,
call);
priv->permissions_calls = g_slist_append (priv->permissions_calls, call);
}
static void
@ -1261,6 +1322,41 @@ nm_sysconfig_settings_new (const char *config_file,
/***************************************************************/
static void
dispose (GObject *object)
{
NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
GSList *iter;
if (priv->auth_changed_id) {
g_signal_handler_disconnect (priv->authority, priv->auth_changed_id);
priv->auth_changed_id = 0;
}
/* Cancel PolicyKit requests */
for (iter = priv->pk_calls; iter; iter = g_slist_next (iter)) {
PolkitCall *call = iter->data;
call->disposed = TRUE;
g_cancellable_cancel (call->cancellable);
}
g_slist_free (priv->pk_calls);
priv->pk_calls = NULL;
/* Cancel PolicyKit permissions requests */
for (iter = priv->permissions_calls; iter; iter = g_slist_next (iter)) {
PermissionsCall *call = iter->data;
call->disposed = TRUE;
g_cancellable_cancel (call->cancellable);
}
g_slist_free (priv->permissions_calls);
priv->permissions_calls = NULL;
G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
@ -1274,9 +1370,6 @@ finalize (GObject *object)
g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL);
g_slist_free (priv->plugins);
if (priv->authority)
g_object_unref (priv->authority);
g_free (priv->orig_hostname);
g_free (priv->config_file);
@ -1334,6 +1427,7 @@ nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class)
/* virtual methods */
object_class->notify = notify;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
ss_class->list_connections = list_connections;
ss_class->add_connection = add_connection;
@ -1379,9 +1473,12 @@ nm_sysconfig_settings_init (NMSysconfigSettings *self)
priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
priv->authority = polkit_authority_get ();
if (priv->authority)
g_signal_connect (priv->authority, "changed", G_CALLBACK (pk_authority_changed_cb), self);
else
if (priv->authority) {
priv->auth_changed_id = g_signal_connect (priv->authority,
"changed",
G_CALLBACK (pk_authority_changed_cb),
self);
} else
g_warning ("%s: failed to create PolicyKit authority.", __func__);
/* Grab hostname on startup and use that if no plugins provide one */