From 312c7c952cbb3f20bcb1092db9bfbb51485fcebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Tue, 2 Aug 2011 09:15:37 +0200 Subject: [PATCH 01/14] ifcfg-rh: emit "updated" signal when connection file is changed (rh #727501) Chain up to parent's commit_changes() even if in-memory and on-disk data are the same; they are the same when another process changes the on-disk file. Just make sure not to write out the data needlessly when same. This fixes a regression caused by 9cba854fa0a32022a44e922dd4e70aaaf3c00dd2. It exhibits e.g. by not auto-activating connection when ONBOOT is changed from "no" to "yes". Connection "updated" signal was not emitted and listeners like NMPolicy was not prodded. --- src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index 534f44d9ff..04d3d3e453 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 - 2010 Red Hat, Inc. + * Copyright (C) 2008 - 2011 Red Hat, Inc. */ #include @@ -181,7 +181,7 @@ nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self) static void commit_changes (NMSettingsConnection *connection, NMSettingsConnectionCommitFunc callback, - gpointer user_data) + gpointer user_data) { NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection); GError *error = NULL; @@ -208,9 +208,12 @@ commit_changes (NMSettingsConnection *connection, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS); g_object_unref (reread); - /* Don't bother writing anything out if nothing really changed */ - if (same == TRUE) + /* Don't bother writing anything out if in-memory and on-disk data are the same */ + if (same) { + /* But chain up to parent to handle success - emits updated signal */ + NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data); return; + } } if (writer_update_connection (NM_CONNECTION (connection), @@ -227,7 +230,7 @@ commit_changes (NMSettingsConnection *connection, } } -static void +static void do_delete (NMSettingsConnection *connection, NMSettingsConnectionDeleteFunc callback, gpointer user_data) From adc7ec170d429b6b8cdeb302c8afa96fbd3ba907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Tue, 2 Aug 2011 10:45:43 +0200 Subject: [PATCH 02/14] ifcfg-rh: make NM_CONTROLLED changes function properly (rh #727501) Changing NM_CONTROLED from "no" to "yes" worked just the first time. Fix that by storing unmanaged spec when interface becomes unmanaged and adjust condition identifying "no-change" updates to the ifcfg file. --- src/settings/plugins/ifcfg-rh/plugin.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index 7d2765651a..ed0dceca31 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -269,20 +269,24 @@ connection_new_or_changed (SCPluginIfcfg *self, /* Successfully read connection changes */ - /* When the connections are the same, nothing is done */ - if (nm_connection_compare (NM_CONNECTION (existing), - NM_CONNECTION (new), - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { + old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (existing)); + new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new)); + + /* When interface is unmanaged or the connections and unmanaged specs are the same + * there's nothing to do */ + if ( (g_strcmp0 (old_unmanaged, new_unmanaged) == 0 && new_unmanaged != NULL) + || ( nm_connection_compare (NM_CONNECTION (existing), + NM_CONNECTION (new), + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) + && g_strcmp0 (old_unmanaged, new_unmanaged) == 0)) { + g_object_unref (new); return; } PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path); - old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (existing)); - new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new)); - if (new_unmanaged) { if (!old_unmanaged) { /* Unexport the connection by telling the settings service it's @@ -290,6 +294,11 @@ connection_new_or_changed (SCPluginIfcfg *self, * unmanaged specs have changed. */ nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (existing)); + /* Remove the path so that claim_connection() doesn't complain later when + * interface gets managed and connection is re-added. */ + nm_connection_set_path (NM_CONNECTION (existing), NULL); + + g_object_set (existing, NM_IFCFG_CONNECTION_UNMANAGED, new_unmanaged, NULL); g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } } else { From 9a112d8eebb2bdd9ad26aa9a971b7fd5dfe42ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Tue, 2 Aug 2011 15:25:40 +0200 Subject: [PATCH 03/14] man: updated man pages --- man/NetworkManager.8.in | 33 ++++++++++++++---- man/NetworkManager.conf.5.in | 66 ++++++++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/man/NetworkManager.8.in b/man/NetworkManager.8.in index c5f44513d8..127c72bf37 100644 --- a/man/NetworkManager.8.in +++ b/man/NetworkManager.8.in @@ -1,14 +1,16 @@ .\" NetworkManager(8) manual page .\" -.\" Copyright (C) 2005 - 2010 Red Hat, Inc. +.\" Copyright (C) 2005 - 2011 Red Hat, Inc. .\" Copyright (C) 2005 - 2009 Novell, Inc. .\" Copyright (C) 2005 Robert Love .\" -.TH NETWORKMANAGER "8" "January 29, 2010" +.TH NETWORKMANAGER "8" "2 August 2011" .SH NAME NetworkManager \- network management daemon .SH SYNOPSIS -.B NetworkManager [\-\-version] [\-\-no\-daemon] [\-\-pid\-file=] [\-\-state\-file=] [\-\-config=] [\-\-plugins=,plugin2>,...] [\-\-log\-level=] [\-\-log\-domains=,,...] +.B NetworkManager [\-\-version] | [\-\-help] +.PP +.B NetworkManager [\-\-no\-daemon] [\-\-pid\-file=] [\-\-state\-file=] [\-\-config=] [\-\-plugins=,plugin2>,...] [\-\-log\-level=] [\-\-log\-domains=,,...] .SH DESCRIPTION The \fINetworkManager\fP daemon attempts to make networking configuration and operation as painless and automatic as possible by managing the primary network @@ -21,10 +23,22 @@ settings and operation. .P NetworkManager will execute scripts in the /etc/NetworkManager/dispatcher.d directory in alphabetical order in response to network events. Each script -should be (a) a regular file, (b) owned by root, (c) not writable by group or -other, (d) not set-uid, (e) and executable by the owner. Each script receives -two arguments, the first being the interface name of the device just activated, -and second an action. +should be: +.IP "(a)" 4 +a regular file +.IP "(b)" 4 +owned by root +.IP "(c)" 4 +not writable by group or other +.IP "(d)" 4 +not set-uid +.IP "(e)" 4 +and executable by the owner +.PP +Each script receives two arguments, the first being the interface name of the +device just activated, and second an action. +.PP +Actions: .TP .I "up" The interface has been activated. The environment contains more information @@ -64,6 +78,9 @@ The following options are supported: .I "\-\-version" Print the NetworkManager software version and exit. .TP +.I "\-\-help" +Print NetworkManager's available options and exit. +.TP .I "\-\-no\-daemon" Do not daemonize. This is useful for debugging, and directs log output to the controlling terminal in addition to syslog. @@ -113,5 +130,7 @@ When set to anything, causes NetworkManager to turn on PPP debugging in pppd, which logs all PPP and PPTP frames and client/server exchanges. .SH SEE ALSO .BR nm\-tool (1), +.BR nm\-online (1), +.BR nmcli (1), .BR NetworkManager.conf (5). diff --git a/man/NetworkManager.conf.5.in b/man/NetworkManager.conf.5.in index d047f39391..9fe722c4c9 100644 --- a/man/NetworkManager.conf.5.in +++ b/man/NetworkManager.conf.5.in @@ -1,8 +1,8 @@ .\" NetworkManager.conf(5) manual page .\" -.\" Copyright (C) 2010 Red Hat, Inc. +.\" Copyright (C) 2010 - 2011 Red Hat, Inc. .\" -.TH "NetworkManager.conf" "5" "23 November 2010" "" +.TH "NetworkManager.conf" "5" "2 August 2011" "" .SH NAME NetworkManager.conf \- NetworkManager configuration file .SH SYNOPSIS @@ -20,9 +20,6 @@ is a configuration file for NetworkManager. It is used to set up various aspects of NetworkManager's behavior. The location of the file may be changed through use of the "\-\-config=" argument for \fBNetworkManager\fP (8). - -It is not necessary to restart NetworkManager when making changes, as the -configuration file is watched for changes and reloaded automatically when necessary. .SH "FILE FORMAT" .P The configuration file format is so-called key file (sort of ini-style format). @@ -163,12 +160,61 @@ warning messages. The following log domains are available: [NONE, HW, RFKILL, ETHER, WIFI, BT, MB, DHCP4, DHCP6, PPP, WIFI_SCAN, IP4, IP6, AUTOIP4, DNS, VPN, SHARING, SUPPLICANT, AGENTS, SETTINGS, SUSPEND, CORE, DEVICE, OLPC, WIMAX]. When "NONE" is given by -itself, logging is disabled. MB = Mobile Broadband, AGENTS = secret agents -operations and communication, SETTINGS = settings/config service operations, -OLPC = OLPC Mesh device operations, CORE = core daemon operations, DEVICE = -activation and general interface operations. +itself, logging is disabled. +.PP +.RS +HW = Hardware related operations +.br +RFKILL = RFKill subsystem operations +.br +ETHER = Ethernet device operations +.br +WIFI = Wi-Fi device operations +.br +BT = Bluetooth +.br +MB = Mobile Broadband +.br +DHCP4 = DHCP for IPv4 +.br +DHCP6 = DHCP for IPv6 +.br +PPP = Point-to-point protocol operations +.br +WIFI_SCAN = Wi-Fi scanning operations +.br +IP4 = Domain for IPv4 logging +.br +IP6 = Domain for IPv6 logging +.br +AUTOIP4 = AutoIP (avahi) operations +.br +DNS = Domain Name System related operations +.br +VPN = Virtual Private Network connections and operaions +.br +SHARING = Connection sharing +.br +SUPPLICANT = WPA supplicant related operations +.br +AGENTS = Secret agents operations and communication +.br +SETTINGS = Settings/config service operations +.br +SUSPEND = Suspend/resume +.br +CORE = Core daemon operations +.br +DEVICE = Activation and general interface operations +.br +OLPC = OLPC Mesh device operations +.br +WIMAX = Wimax device operations +.br .SH "SEE ALSO" .BR http://live.gnome.org/NetworkManager/SystemSettings .sp .BR NetworkManager (8), -.BR nm\-tool (1). +.BR nmcli (1), +.BR nm\-tool (1), +.BR nm\-online (1). From f1a82274361a328c1553d1f841335d4966b42d68 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Aug 2011 14:22:15 -0500 Subject: [PATCH 04/14] nm-tool: show WiMAX info when available libnm-glib will always be built with WiMAX enabled so we might as well show it. It's only NM itself that gets built with/without WiMAX support. --- test/nm-tool.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/nm-tool.c b/test/nm-tool.c index ffe70af9ff..9ce44f88a5 100644 --- a/test/nm-tool.c +++ b/test/nm-tool.c @@ -39,9 +39,7 @@ #include #include #include -#if WITH_WIMAX #include -#endif #include #include #include @@ -198,7 +196,6 @@ detail_access_point (gpointer data, gpointer user_data) g_free (tmp); } -#if WITH_WIMAX static const char * wimax_network_type_to_str (NMWimaxNspNetworkType type) { @@ -238,7 +235,6 @@ detail_nsp (gpointer data, gpointer user_data) g_free (label); g_free (data_str); } -#endif static gchar * ip4_address_as_string (guint32 ip) @@ -370,10 +366,8 @@ detail_device (gpointer data, gpointer user_data) print_string ("Type", "Mobile Broadband (unknown)"); } else if (NM_IS_DEVICE_BT (device)) print_string ("Type", "Bluetooth"); -#if WITH_WIMAX else if (NM_IS_DEVICE_WIMAX (device)) print_string ("Type", "WiMAX"); -#endif print_string ("Driver", nm_device_get_driver (device) ? nm_device_get_driver (device) : "(unknown)"); @@ -390,10 +384,8 @@ detail_device (gpointer data, gpointer user_data) tmp = g_strdup (nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device))); else if (NM_IS_DEVICE_WIFI (device)) tmp = g_strdup (nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (device))); -#if WITH_WIMAX else if (NM_IS_DEVICE_WIMAX (device)) tmp = g_strdup (nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device))); -#endif if (tmp) { print_string ("HW Address", tmp); @@ -459,7 +451,6 @@ detail_device (gpointer data, gpointer user_data) print_string (" Carrier", "on"); else print_string (" Carrier", "off"); -#if WITH_WIMAX } else if (NM_IS_DEVICE_WIMAX (device)) { NMDeviceWimax *wimax = NM_DEVICE_WIMAX (device); NMWimaxNsp *active_nsp = NULL; @@ -520,7 +511,6 @@ detail_device (gpointer data, gpointer user_data) nsps = nm_device_wimax_get_nsps (NM_DEVICE_WIMAX (device)); if (nsps && nsps->len) g_ptr_array_foreach ((GPtrArray *) nsps, detail_nsp, (gpointer) active_name); -#endif } /* IP Setup info */ From dab37276d2baee6508894f25c2517b6cbdd2d90f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Aug 2011 15:55:14 +0200 Subject: [PATCH 05/14] examples: new example for printing active connection list --- examples/python/Makefile.am | 3 +- .../python/get-active-connection-uuids.py | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100755 examples/python/get-active-connection-uuids.py diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am index 5650ed8333..7fa376ef75 100644 --- a/examples/python/Makefile.am +++ b/examples/python/Makefile.am @@ -5,6 +5,7 @@ EXTRA_DIST = \ vpn.py \ list-connections.py \ show-bssids.py \ - disconnect-device.py + disconnect-device.py \ + get-active-connections.py diff --git a/examples/python/get-active-connection-uuids.py b/examples/python/get-active-connection-uuids.py new file mode 100755 index 0000000000..229a12eba8 --- /dev/null +++ b/examples/python/get-active-connection-uuids.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# 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) 2010 Red Hat, Inc. +# + +import dbus, sys + +# This example takes a device interface name as a parameter and tells +# NetworkManager to disconnect that device, closing down any network +# connection it may have + +bus = dbus.SystemBus() + +# Get a proxy for the base NetworkManager object +proxy = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager") +manager = dbus.Interface(proxy, "org.freedesktop.NetworkManager") +settings = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings") +mgr_props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties") + +# Find the device the user wants to disconnect +active = mgr_props.Get("org.freedesktop.NetworkManager", "ActiveConnections") +for a in active: + a_proxy = bus.get_object("org.freedesktop.NetworkManager", a) + a_props = dbus.Interface(a_proxy, "org.freedesktop.DBus.Properties") + uuid = prop_iface.Get("org.freedesktop.NetworkManager.Connection.Active", "Uuid") + connection = settings.GetConnectionByUuid(uuid) + print "%s (%s)" % (connection['connection']['id'], uuid) + +if len(active) == 0: + print "No active connections" + From c957fdfb5255aa50cf7bde19dc6ff2baa9706cc4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Aug 2011 15:55:51 +0200 Subject: [PATCH 06/14] examples: make some examples executable --- examples/python/list-connections.py | 0 examples/python/show-bssids.py | 0 examples/python/vpn.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 examples/python/list-connections.py mode change 100644 => 100755 examples/python/show-bssids.py mode change 100644 => 100755 examples/python/vpn.py diff --git a/examples/python/list-connections.py b/examples/python/list-connections.py old mode 100644 new mode 100755 diff --git a/examples/python/show-bssids.py b/examples/python/show-bssids.py old mode 100644 new mode 100755 diff --git a/examples/python/vpn.py b/examples/python/vpn.py old mode 100644 new mode 100755 From bf89da140cf25606b84e48321f4eb2e018f7fa8d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 6 Aug 2011 10:44:50 +0200 Subject: [PATCH 07/14] examples: fix up active connection example --- .../python/get-active-connection-uuids.py | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/examples/python/get-active-connection-uuids.py b/examples/python/get-active-connection-uuids.py index 229a12eba8..9eefac20b2 100755 --- a/examples/python/get-active-connection-uuids.py +++ b/examples/python/get-active-connection-uuids.py @@ -27,19 +27,29 @@ import dbus, sys bus = dbus.SystemBus() # Get a proxy for the base NetworkManager object -proxy = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager") -manager = dbus.Interface(proxy, "org.freedesktop.NetworkManager") -settings = dbus.Interface(proxy, "org.freedesktop.NetworkManager.Settings") -mgr_props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties") +m_proxy = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager") +manager = dbus.Interface(m_proxy, "org.freedesktop.NetworkManager") +mgr_props = dbus.Interface(m_proxy, "org.freedesktop.DBus.Properties") + +s_proxy = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings") +settings = dbus.Interface(s_proxy, "org.freedesktop.NetworkManager.Settings") # Find the device the user wants to disconnect active = mgr_props.Get("org.freedesktop.NetworkManager", "ActiveConnections") for a in active: a_proxy = bus.get_object("org.freedesktop.NetworkManager", a) + + # Get the UUID directly; apps could use this to perform certain operations + # based on which network you're connected too a_props = dbus.Interface(a_proxy, "org.freedesktop.DBus.Properties") - uuid = prop_iface.Get("org.freedesktop.NetworkManager.Connection.Active", "Uuid") - connection = settings.GetConnectionByUuid(uuid) - print "%s (%s)" % (connection['connection']['id'], uuid) + uuid = a_props.Get("org.freedesktop.NetworkManager.Connection.Active", "Uuid") + + # Grab the connection object path so we can get all the connection's settings + connection_path = a_props.Get("org.freedesktop.NetworkManager.Connection.Active", "Connection") + c_proxy = bus.get_object("org.freedesktop.NetworkManager", connection_path) + connection = dbus.Interface(c_proxy, "org.freedesktop.NetworkManager.Settings.Connection") + settings = connection.GetSettings() + print "%s (%s)" % (settings['connection']['id'], uuid) if len(active) == 0: print "No active connections" From 310880a104e784a442391a58f6511c1848b11be4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 6 Aug 2011 10:46:21 +0200 Subject: [PATCH 08/14] api: fix up node names Not sure if it really makes a difference, but... --- introspection/nm-agent-manager.xml | 2 +- introspection/nm-manager.xml | 9 +-------- introspection/nm-settings.xml | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/introspection/nm-agent-manager.xml b/introspection/nm-agent-manager.xml index 0b1e3e6e86..e26caacf42 100644 --- a/introspection/nm-agent-manager.xml +++ b/introspection/nm-agent-manager.xml @@ -1,6 +1,6 @@ - + diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml index 1bb76d09fd..f5fd7abcf4 100644 --- a/introspection/nm-manager.xml +++ b/introspection/nm-manager.xml @@ -1,13 +1,6 @@ - - - + diff --git a/introspection/nm-settings.xml b/introspection/nm-settings.xml index 64163534a5..301cde76dd 100644 --- a/introspection/nm-settings.xml +++ b/introspection/nm-settings.xml @@ -1,6 +1,6 @@ - + The Settings interface allows clients to view and administrate the connections stored and used by NetworkManager. From 6c901ab040ea5f2bf2e17b7edf178500ab75e32e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 6 Aug 2011 10:59:19 +0200 Subject: [PATCH 09/14] api: update version based on configure version Instead of manually which is error-prone. --- configure.ac | 1 + docs/api/Makefile.am | 4 ++-- introspection/Makefile.am | 2 +- introspection/{all.xml => all.xml.in} | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) rename introspection/{all.xml => all.xml.in} (98%) diff --git a/configure.ac b/configure.ac index 2a33ebd9cb..4e9790497b 100644 --- a/configure.ac +++ b/configure.ac @@ -664,6 +664,7 @@ initscript/Mandriva/networkmanager initscript/linexa/Makefile initscript/linexa/networkmanager introspection/Makefile +introspection/all.xml man/Makefile man/NetworkManager.8 man/NetworkManager.conf.5 diff --git a/docs/api/Makefile.am b/docs/api/Makefile.am index 687d9cfb1c..276b4aefef 100644 --- a/docs/api/Makefile.am +++ b/docs/api/Makefile.am @@ -27,7 +27,7 @@ XSLTPROC = xsltproc --xinclude --nonet XMLS = $(wildcard $(top_srcdir)/introspection/nm-*.xml) OTHER_FILES= \ - $(top_srcdir)/introspection/all.xml \ + $(top_builddir)/introspection/all.xml \ $(top_srcdir)/introspection/generic-types.xml \ $(top_srcdir)/introspection/errors.xml \ $(top_srcdir)/introspection/vpn-errors.xml \ @@ -37,7 +37,7 @@ OTHER_FILES= \ GENERATED_FILES = spec.html settings-spec.xml spec.html: $(XMLS) $(OTHER_FILES) html-build.stamp - $(XSLTPROC) $(top_srcdir)/tools/doc-generator.xsl $(top_srcdir)/introspection/all.xml > $@ + $(XSLTPROC) $(top_srcdir)/tools/doc-generator.xsl $(top_builddir)/introspection/all.xml > $@ mkdir -p $(builddir)/html/ cp $@ $(builddir)/html/ diff --git a/introspection/Makefile.am b/introspection/Makefile.am index 320245eee1..7b549c1269 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -1,5 +1,5 @@ EXTRA_DIST = \ - all.xml \ + all.xml.in \ generic-types.xml \ errors.xml \ vpn-errors.xml \ diff --git a/introspection/all.xml b/introspection/all.xml.in similarity index 98% rename from introspection/all.xml rename to introspection/all.xml.in index 5d1baf01c9..4d2c272179 100644 --- a/introspection/all.xml +++ b/introspection/all.xml.in @@ -3,7 +3,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude"> NetworkManager D-Bus Interface Specification -0.9 +@VERSION@ Copyright (C) 2008 - 2011 Red Hat, Inc. From 0cb27772f38281c14ca8b3b11db2fb8e78554589 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 12 Aug 2011 10:23:25 -0500 Subject: [PATCH 10/14] docs: update VPN setting 'user-name' property documentation Lamarque wanted clarification about how it's supposed to be used. --- libnm-util/nm-setting-vpn.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/libnm-util/nm-setting-vpn.c b/libnm-util/nm-setting-vpn.c index c04b974160..50091cb9a6 100644 --- a/libnm-util/nm-setting-vpn.c +++ b/libnm-util/nm-setting-vpn.c @@ -756,23 +756,27 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class) /** * NMSettinVPN:user-name: * - * User name of the currently logged in user for connections provided by the - * user settings service. This name is provided to the VPN plugin to use in - * lieu of a custom username provided by that VPN plugins specific - * configuration. The VPN plugin itself decides which user name to use. + * If the VPN connection requires a user name for authentication, that name + * should be provided here. If the connection is available to more than + * one user, and the VPN requires each user to supply a different name, then + * leave this property empty. If this property is empty, NetworkManager + * will automatically supply the username of the user which requested the + * VPN connection. **/ g_object_class_install_property (object_class, PROP_USER_NAME, g_param_spec_string (NM_SETTING_VPN_USER_NAME, - "User name", - "User name of the currently logged in user for " - "connections provided by the user settings service. " - "This name is provided to the VPN plugin to use in " - "lieu of a custom username provided by that VPN " - "plugins specific configuration. The VPN plugin " - "itself decides which user name to use.", - NULL, - G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); + "User name", + "If the VPN connection requires a user name for " + "authentication, that name should be provided here. " + "If the connection is available to more than one " + "user, and the VPN requires each user to supply a " + "different name, then leave this property empty. If " + "this property is empty, NetworkManager will " + "automatically supply the username of the user which " + "requested the VPN connection.", + NULL, + G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE)); /** * NMSettingVPN:data: From 4d635844ec900f6d422b12b2d848b6705e937e76 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 12 Aug 2011 11:05:08 -0500 Subject: [PATCH 11/14] cli: remove unused libraries from the makefile Nothing in cli uses the marshalller stuff. --- cli/src/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/cli/src/Makefile.am b/cli/src/Makefile.am index 572e122fb6..f49d0127a5 100644 --- a/cli/src/Makefile.am +++ b/cli/src/Makefile.am @@ -4,7 +4,6 @@ bin_PROGRAMS = \ INCLUDES = \ -I${top_srcdir} \ -I${top_srcdir}/include \ - -I${top_builddir}/marshallers \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/libnm-glib @@ -31,7 +30,6 @@ nmcli_CPPFLAGS = \ nmcli_LDADD = \ $(DBUS_LIBS) \ $(GLIB_LIBS) \ - $(top_builddir)/marshallers/libmarshallers.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(top_builddir)/libnm-glib/libnm-glib.la From e2d88f59e6b95edfbd0b5ae7e7e396e8ab462664 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 16 Aug 2011 15:47:12 -0500 Subject: [PATCH 12/14] settings: preserve agent secrets over Update operation The core problem was that the Update would trigger a write to disk to save the connection's new settings, which called nm_settings_connection_replace_settings(). Which saved existing transient (agent/unsaved) secrets, replaced settings with the new ones from Update(), then copied back the old transient secrets. This was to ensure that changes triggered from getting agent secrets during activation (which might write the connection out to disk if new system secrets were provided, which triggered an inotify read-back of the connection, which blew away the transient secrets just returned from the agent) didn't blow away transient secrets. Unfortunately that fix was too general. As a quick hack for now, copy the new secrets and re-apply them after nm_connection_replace_settings() has run. We'll do the actual fix later, but it's more involved and needs more testing so we don't want to apply it this close to release. --- libnm-util/nm-connection.c | 79 +++++++++++++++---------- libnm-util/nm-connection.h | 5 +- libnm-util/tests/test-secrets.c | 83 ++++++++++++++++++++++++++- src/settings/nm-settings-connection.c | 75 ++++++++++++++---------- 4 files changed, 180 insertions(+), 62 deletions(-) diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index 6e9f92b59c..91fc3afac4 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c @@ -99,6 +99,7 @@ nm_connection_error_get_type (void) ENUM_ENTRY (NM_CONNECTION_ERROR_UNKNOWN, "UnknownError"), ENUM_ENTRY (NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, "ConnectionSettingNotFound"), ENUM_ENTRY (NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID, "ConnectionTypeInvalid"), + ENUM_ENTRY (NM_CONNECTION_ERROR_SETTING_NOT_FOUND, "SettingNotFound"), { 0, 0, 0 } }; etype = g_enum_register_static ("NMConnectionError", values); @@ -790,60 +791,76 @@ nm_connection_verify (NMConnection *connection, GError **error) * nm_connection_update_secrets: * @connection: the #NMConnection * @setting_name: the setting object name to which the secrets apply - * @setting_secrets: (element-type utf8 GObject.Value): a #GHashTable mapping + * @secrets: (element-type utf8 GObject.Value): a #GHashTable mapping * string:#GValue of setting property names and secrets of the given @setting_name * @error: location to store error, or %NULL * * Update the specified setting's secrets, given a hash table of secrets * intended for that setting (deserialized from D-Bus for example). Will also * extract the given setting's secrets hash if given a hash of hashes, as would - * be returned from nm_connection_to_hash(). + * be returned from nm_connection_to_hash(). If @setting_name is %NULL, expects + * a fully serialized #NMConnection as returned by nm_connection_to_hash() and + * will update all secrets from all settings contained in @secrets. * - * Returns: %TRUE if the secrets were successfully updated and the connection - * is valid, %FALSE on failure or if the setting was never added to the connection + * Returns: %TRUE if the secrets were successfully updated, %FALSE if the update + * failed (tried to update secrets for a setting that doesn't exist, etc) **/ gboolean nm_connection_update_secrets (NMConnection *connection, const char *setting_name, - GHashTable *setting_secrets, + GHashTable *secrets, GError **error) { NMSetting *setting; gboolean success; GHashTable *tmp; - GType setting_type; g_return_val_if_fail (connection != NULL, FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - g_return_val_if_fail (setting_name != NULL, FALSE); - g_return_val_if_fail (setting_secrets != NULL, FALSE); + g_return_val_if_fail (secrets != NULL, FALSE); if (error) g_return_val_if_fail (*error == NULL, FALSE); - setting_type = nm_connection_lookup_setting_type (setting_name); - if (!setting_type) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, - setting_name); - return FALSE; + if (setting_name) { + /* Update just one setting */ + setting = nm_connection_get_setting_by_name (connection, setting_name); + if (!setting) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_SETTING_NOT_FOUND, + setting_name); + return FALSE; + } + + /* Check if this is a hash of hashes, ie a full deserialized connection, + * not just a single hashed setting. + */ + tmp = g_hash_table_lookup (secrets, setting_name); + success = nm_setting_update_secrets (setting, tmp ? tmp : secrets, error); + } else { + GHashTableIter iter; + const char *name; + + success = TRUE; /* Just in case 'secrets' has no elements */ + + /* Try as a serialized connection (GHashTable of GHashTables) */ + g_hash_table_iter_init (&iter, secrets); + while (g_hash_table_iter_next (&iter, (gpointer) &name, (gpointer) &tmp)) { + setting = nm_connection_get_setting_by_name (connection, name); + if (!setting) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_SETTING_NOT_FOUND, + name); + return FALSE; + } + + /* Update the secrets for this setting */ + success = nm_setting_update_secrets (setting, tmp, error); + if (success == FALSE) + break; + } } - - setting = nm_connection_get_setting (connection, setting_type); - if (!setting) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, - setting_name); - return FALSE; - } - - /* Check if this is a hash of hashes, ie a full deserialized connection, - * not just a single hashed setting. - */ - tmp = g_hash_table_lookup (setting_secrets, setting_name); - - success = nm_setting_update_secrets (setting, tmp ? tmp : setting_secrets, error); if (success) g_signal_emit (connection, signals[SECRETS_UPDATED], 0, setting_name); return success; diff --git a/libnm-util/nm-connection.h b/libnm-util/nm-connection.h index 87b053c101..a7e0721cc1 100644 --- a/libnm-util/nm-connection.h +++ b/libnm-util/nm-connection.h @@ -66,6 +66,8 @@ G_BEGIN_DECLS * 'connection' setting did not point to a valid connection base type; ie * it was not a hardware-related setting like #NMSettingWired or * #NMSettingWireless. + * @NM_CONNECTION_ERROR_SETTING_NOT_FOUND: the #NMConnection object + * did not contain the specified #NMSetting object * * Describes errors that may result from operations involving a #NMConnection. * @@ -74,7 +76,8 @@ typedef enum { NM_CONNECTION_ERROR_UNKNOWN = 0, NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND, - NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID + NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID, + NM_CONNECTION_ERROR_SETTING_NOT_FOUND } NMConnectionError; #define NM_TYPE_CONNECTION_ERROR (nm_connection_error_get_type ()) diff --git a/libnm-util/tests/test-secrets.c b/libnm-util/tests/test-secrets.c index f1d105fcd2..1fe3c43823 100644 --- a/libnm-util/tests/test-secrets.c +++ b/libnm-util/tests/test-secrets.c @@ -591,7 +591,84 @@ test_update_secrets_wifi_bad_setting_name (void) "asdfasdfasdfasf", secrets, &error); - g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_SETTING_NOT_FOUND); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND); + g_assert (success == FALSE); + + g_object_unref (connection); +} + +static void +test_update_secrets_whole_connection (void) +{ + NMConnection *connection; + NMSettingWirelessSecurity *s_wsec; + GHashTable *secrets, *wsec_hash; + GError *error = NULL; + gboolean success; + const char *wepkey = "11111111111111111111111111"; + + connection = wifi_connection_new (); + + /* Build up the secrets hash */ + secrets = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL); + wsec_hash = g_hash_table_lookup (secrets, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + g_assert (wsec_hash); + g_hash_table_insert (wsec_hash, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, string_to_gvalue (wepkey)); + + success = nm_connection_update_secrets (connection, NULL, secrets, &error); + g_assert_no_error (error); + g_assert (success == TRUE); + + s_wsec = nm_connection_get_setting_wireless_security (connection); + g_assert (s_wsec); + g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, wepkey); + + g_object_unref (connection); +} + +static void +test_update_secrets_whole_connection_empty_hash (void) +{ + NMConnection *connection; + GHashTable *secrets; + GError *error = NULL; + gboolean success; + + connection = wifi_connection_new (); + secrets = g_hash_table_new (g_str_hash, g_str_equal); + success = nm_connection_update_secrets (connection, NULL, secrets, &error); + g_assert_no_error (error); + g_assert (success == TRUE); + g_object_unref (connection); +} + +static void +test_update_secrets_whole_connection_bad_setting (void) +{ + NMConnection *connection; + GHashTable *secrets, *wsec_hash; + GError *error = NULL; + gboolean success; + const char *wepkey = "11111111111111111111111111"; + + connection = wifi_connection_new (); + + /* Build up the secrets hash */ + secrets = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL); + wsec_hash = g_hash_table_lookup (secrets, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + g_assert (wsec_hash); + g_hash_table_insert (wsec_hash, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, string_to_gvalue (wepkey)); + + /* Steal the wsec setting hash so it's not deallocated, and stuff it back + * in with a different name so we ensure libnm-util is returning the right + * error when it finds an entry in the connection hash that doesn't match + * any setting in the connection. + */ + g_hash_table_steal (secrets, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + g_hash_table_insert (secrets, "asdfasdfasdfasdf", wsec_hash); + + success = nm_connection_update_secrets (connection, NULL, secrets, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND); g_assert (success == FALSE); g_object_unref (connection); @@ -617,6 +694,10 @@ int main (int argc, char **argv) test_update_secrets_wifi_full_hash (); test_update_secrets_wifi_bad_setting_name (); + test_update_secrets_whole_connection (); + test_update_secrets_whole_connection_empty_hash (); + test_update_secrets_whole_connection_bad_setting (); + base = g_path_get_basename (argv[0]); fprintf (stdout, "%s: SUCCESS\n", base); g_free (base); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index f0f9c1a6d7..4b3a56cd6d 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -382,25 +382,14 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, new_settings = nm_connection_to_hash (new, NM_SETTING_HASH_FLAG_ALL); g_assert (new_settings); if (nm_connection_replace_settings (NM_CONNECTION (self), new_settings, error)) { - GHashTableIter iter; - NMSetting *setting; - const char *setting_name; - GHashTable *setting_hash; - /* Copy the connection to keep its secrets around even if NM * calls nm_connection_clear_secrets(). */ update_secrets_cache (self); /* And add the transient secrets back */ - if (transient_secrets) { - g_hash_table_iter_init (&iter, transient_secrets); - while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting_hash)) { - setting = nm_connection_get_setting_by_name (NM_CONNECTION (self), setting_name); - if (setting) - nm_setting_update_secrets (setting, setting_hash, NULL); - } - } + if (transient_secrets) + nm_connection_update_secrets (NM_CONNECTION (self), NULL, transient_secrets, NULL); nm_settings_connection_recheck_visibility (self); success = TRUE; @@ -1109,31 +1098,30 @@ con_update_cb (NMSettingsConnection *connection, } static void -only_agent_secrets_cb (NMSetting *setting, - const char *key, - const GValue *value, - GParamFlags flags, - gpointer user_data) +secrets_filter_cb (NMSetting *setting, + const char *key, + const GValue *value, + GParamFlags flags, + gpointer user_data) { + NMSettingSecretFlags filter_flags = GPOINTER_TO_UINT (user_data); + NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; + const char *secret_name = NULL; + GHashTableIter iter; + if (flags & NM_SETTING_PARAM_SECRET) { - NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - - /* Clear out system-owned or always-ask secrets */ if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) { - GHashTableIter iter; - const char *secret_name = NULL; - /* VPNs are special; need to handle each secret separately */ g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value)); - while (g_hash_table_iter_next (&iter, (gpointer *) &secret_name, NULL)) { + while (g_hash_table_iter_next (&iter, (gpointer) &secret_name, NULL)) { secret_flags = NM_SETTING_SECRET_FLAG_NONE; nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL); - if (secret_flags != NM_SETTING_SECRET_FLAG_AGENT_OWNED) + if (!(secret_flags & filter_flags)) nm_setting_vpn_remove_secret (NM_SETTING_VPN (setting), secret_name); } } else { nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); - if (secret_flags != NM_SETTING_SECRET_FLAG_AGENT_OWNED) + if (!(secret_flags & filter_flags)) g_object_set (G_OBJECT (setting), key, NULL, NULL); } } @@ -1148,23 +1136,52 @@ update_auth_cb (NMSettingsConnection *self, { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMConnection *new_settings = data; - NMConnection *for_agent; + NMConnection *for_agent, *dup; + NMSettingSecretFlags filter_flags; + GHashTable *hash; + GError *local = NULL; if (error) dbus_g_method_return_error (context, error); else { + /* Cache the new secrets since they may get overwritten by the replace + * when transient secrets are copied back. + */ + dup = nm_connection_duplicate (new_settings); + /* Update and commit our settings. */ nm_settings_connection_replace_and_commit (self, new_settings, con_update_cb, context); + /* Copy new agent secrets back to the connection */ + filter_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED; + nm_connection_for_each_setting_value (dup, + secrets_filter_cb, + GUINT_TO_POINTER (filter_flags)); + hash = nm_connection_to_hash (dup, NM_SETTING_HASH_FLAG_ONLY_SECRETS); + g_object_unref (dup); + + if (hash) { + if (!nm_connection_update_secrets (NM_CONNECTION (self), NULL, hash, &local)) { + nm_log_warn (LOGD_SETTINGS, "Failed to update connection secrets: (%d) %s", + local ? local->code : -1, + local && local->message ? local->message : "(unknown)"); + g_clear_error (&local); + } + g_hash_table_destroy (hash); + } + /* Dupe the connection and clear out non-agent-owned secrets so we can * send the agent-owned ones to agents to be saved. Only send them to * agents of the same UID as the Update() request sender. */ for_agent = nm_connection_duplicate (NM_CONNECTION (self)); - nm_connection_for_each_setting_value (for_agent, only_agent_secrets_cb, NULL); + filter_flags = NM_SETTING_SECRET_FLAG_AGENT_OWNED; + nm_connection_for_each_setting_value (for_agent, + secrets_filter_cb, + GUINT_TO_POINTER (filter_flags)); nm_agent_manager_save_secrets (priv->agent_mgr, for_agent, TRUE, sender_uid); g_object_unref (for_agent); } From ac27e33f0c948cad916305ff9e32d1ac59cfb27e Mon Sep 17 00:00:00 2001 From: Daniel Gnoutcheff Date: Tue, 2 Aug 2011 15:48:24 -0400 Subject: [PATCH 13/14] policy: don't autoconnect disabled modems Normally, a device disabled via nm_device_interface_set_enabled() will shift into the UNAVAILABLE state. Modems, however, don't do that. Rather, they pretend that they are in the DISCONNECTED state, presumably to make it easier to re-enable them. To avoid accidentally re-enabling and autoconnecting a disabled modem, we need to explicitly make nm_device_interface_get_enabled() == true a prerequisite for autoconnecting. --- src/nm-policy.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/nm-policy.c b/src/nm-policy.c index 20729fdc94..a42a0fa9bc 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -896,6 +896,9 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds if (state < NM_DEVICE_STATE_DISCONNECTED) return; + if (!nm_device_interface_get_enabled (NM_DEVICE_INTERFACE (device))) + return; + if (!nm_device_autoconnect_allowed (device)) return; @@ -1054,6 +1057,12 @@ nsps_changed (NMDeviceWimax *device, NMWimaxNsp *nsp, gpointer user_data) } #endif +static void +modem_enabled_changed (NMDeviceModem *device, gpointer user_data) +{ + schedule_activate_check ((NMPolicy *) (user_data), NM_DEVICE (device), 0); +} + typedef struct { gulong id; NMDevice *device; @@ -1088,6 +1097,8 @@ device_added (NMManager *manager, NMDevice *device, gpointer user_data) _connect_device_signal (policy, device, "nsp-added", nsps_changed); _connect_device_signal (policy, device, "nsp-removed", nsps_changed); #endif + } else if (NM_IS_DEVICE_MODEM (device)) { + _connect_device_signal (policy, device, NM_DEVICE_MODEM_ENABLE_CHANGED, modem_enabled_changed); } } From f14d8b18ee6412089a8a872b6133e13ed9c5266b Mon Sep 17 00:00:00 2001 From: Daniel Gnoutcheff Date: Tue, 2 Aug 2011 17:23:21 -0400 Subject: [PATCH 14/14] modem: fix race with nm_modem_set_mm_enabled Once we've sent a method call over DBus requesting that the modem be disabled, we should assume that the modem is disabled unless we hear otherwise. Otherwise, code that checks the modem state immediately after it gets disabled might think that it's enabled when it almost certainly is not. --- src/modem-manager/nm-modem.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 33f10789ce..1823e5e6d8 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -86,6 +86,17 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +static void +update_mm_enabled (NMModem *self, gboolean new_enabled) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + if (priv->mm_enabled != new_enabled) { + priv->mm_enabled = new_enabled; + g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + } +} + gboolean nm_modem_get_mm_enabled (NMModem *self) { @@ -822,8 +833,7 @@ get_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d } if (G_VALUE_HOLDS_BOOLEAN (&value)) { - NM_MODEM_GET_PRIVATE (self)->mm_enabled = g_value_get_boolean (&value); - g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + update_mm_enabled (self, g_value_get_boolean (&value)); } else nm_log_warn (LOGD_MB, "failed get modem enabled state: unexpected reply type"); @@ -880,6 +890,9 @@ nm_modem_set_mm_enabled (NMModem *self, gboolean enabled) self, NULL, G_TYPE_BOOLEAN, enabled, G_TYPE_INVALID); + /* If we are disabling the modem, stop saying that it's enabled. */ + if (!enabled) + update_mm_enabled (self, enabled); } } @@ -898,8 +911,7 @@ modem_properties_changed (DBusGProxy *proxy, value = g_hash_table_lookup (props, "Enabled"); if (value && G_VALUE_HOLDS_BOOLEAN (value)) { - priv->mm_enabled = g_value_get_boolean (value); - g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + update_mm_enabled (self, g_value_get_boolean (value)); } value = g_hash_table_lookup (props, "IpMethod");