mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-11 09:30:44 +01:00
Merge commit 'origin/master' into btdun
This commit is contained in:
commit
7d23d8ccdb
20 changed files with 754 additions and 69 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
151
libnm-util/tests/test-general.c
Normal file
151
libnm-util/tests/test-general.c
Normal 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;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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] =
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
116
src/nm-manager.c
116
src/nm-manager.c
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue