Merge remote branch 'origin/master' into gsoc
authorDan Williams <dcbw@redhat.com>
Thu, 26 Aug 2010 14:18:37 +0000 (09:18 -0500)
committerDan Williams <dcbw@redhat.com>
Thu, 26 Aug 2010 14:18:37 +0000 (09:18 -0500)
15 files changed:
1  2 
libnm-glib/nm-client.c
libnm-glib/nm-remote-settings.c
po/POTFILES.in
src/nm-device.c
src/nm-manager-auth.c
src/nm-manager-auth.h
src/nm-manager.c
src/nm-policy.c
src/system-settings/nm-polkit-helpers.h
src/system-settings/nm-session-manager.c
src/system-settings/nm-sysconfig-connection.c
src/system-settings/nm-sysconfig-settings.c
src/vpn-manager/nm-vpn-connection.c
system-settings/plugins/ifcfg-rh/plugin.c
system-settings/plugins/ifupdown/plugin.c

Simple merge
@@@ -192,11 -165,27 +192,18 @@@ fetch_connections_done (DBusGProxy *pro
        int i;
  
        if (error) {
-               g_warning ("%s: error fetching connections: (%d) %s.",
-                          __func__,
-                          error->code,
-                          error->message ? error->message : "(unknown)");
 -              gboolean is_spawn_error = FALSE;
 -
 -              /* Don't warn if the user settings service wasn't running since that's
 -               * just annoying when running headless.
 -               */
 -              if (   g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)
 -                  || g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NAME_HAS_NO_OWNER))
 -                      is_spawn_error = TRUE;
 -
 -              if (!is_spawn_error || priv->scope == NM_CONNECTION_SCOPE_SYSTEM) {
 -                      g_warning ("%s: error fetching %s connections: (%d) %s.",
 -                                     __func__,
 -                                     priv->scope == NM_CONNECTION_SCOPE_USER ? "user" : "system",
++              /* Ignore settings service spawn errors */
++              if (   !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)
++                  && !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NAME_HAS_NO_OWNER)) {
++                      g_warning ("%s: error fetching connections: (%d) %s.",
++                                 __func__,
+                                      error->code,
+                                      error->message ? error->message : "(unknown)");
+               }
                g_clear_error (&error);
 -              g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_CONNECTIONS_READ);
+               /* We tried to read connections and failed */
++              g_signal_emit (self, signals[CONNECTIONS_READ], 0);
                return;
        }
  
diff --cc po/POTFILES.in
Simple merge
diff --cc src/nm-device.c
Simple merge
Simple merge
Simple merge
@@@ -822,6 -1415,7 +838,7 @@@ system_internal_new_connection (NMManag
        path = nm_connection_get_path (NM_CONNECTION (connection));
        g_hash_table_insert (priv->system_connections, g_strdup (path),
                             g_object_ref (connection));
 -      g_signal_emit (manager, signals[CONNECTION_ADDED], 0, connection, NM_CONNECTION_SCOPE_SYSTEM);
++      g_signal_emit (manager, signals[CONNECTION_ADDED], 0, connection);
  }
  
  static void
@@@ -2992,7 -4144,18 +3166,18 @@@ nm_manager_get (const char *config_file
  
        priv = NM_MANAGER_GET_PRIVATE (singleton);
  
 -      priv->sys_settings = nm_sysconfig_settings_new (config_file, plugins, bus, error);
+       bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
+       g_assert (bus);
+       dbus_connection = dbus_g_connection_get_connection (bus);
+       g_assert (dbus_connection);
+       if (!dbus_connection_add_filter (dbus_connection, prop_filter, singleton, NULL)) {
+               nm_log_err (LOGD_CORE, "failed to register DBus connection filter");
+               g_object_unref (singleton);
+               return NULL;
+     }
 +      priv->sys_settings = nm_sysconfig_settings_new (config_file, plugins, error);
        if (!priv->sys_settings) {
                g_object_unref (singleton);
                return NULL;
@@@ -3052,6 -4221,9 +3237,8 @@@ dispose (GObject *object
  {
        NMManager *manager = NM_MANAGER (object);
        NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
 -      GSList *iter;
+       DBusGConnection *bus;
+       DBusConnection *dbus_connection;
  
        if (priv->disposed) {
                G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
                priv->devices = remove_one_device (manager,
                                                   priv->devices,
                                                   NM_DEVICE (priv->devices->data),
-                                                  TRUE,
-                                                  FALSE);
+                                                  TRUE);
        }
  
 -      user_proxy_cleanup (manager, FALSE);
 -      g_hash_table_destroy (priv->user_connections);
 -      priv->user_connections = NULL;
 -
        g_hash_table_foreach (priv->system_connections, emit_removed, manager);
        g_hash_table_remove_all (priv->system_connections);
        g_hash_table_destroy (priv->system_connections);
diff --cc src/nm-policy.c
Simple merge
  #ifndef NM_POLKIT_HELPERS_H
  #define NM_POLKIT_HELPERS_H
  
+ #include <config.h>
  #include <polkit/polkit.h>
  
 -#define NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY    "org.freedesktop.network-manager-settings.system.modify"
 -#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED "org.freedesktop.network-manager-settings.system.wifi.share.protected"
 -#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN      "org.freedesktop.network-manager-settings.system.wifi.share.open"
 -#define NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY      "org.freedesktop.network-manager-settings.system.hostname.modify"
 +#define NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY "org.freedesktop.NetworkManager.settings.modify"
 +#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED "org.freedesktop.NetworkManager.settings.wifi.share.protected"
 +#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN      "org.freedesktop.NetworkManager.settings.wifi.share.open"
 +#define NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY      "org.freedesktop.NetworkManager.settings.hostname.modify"
  
+ /* Fix for polkit 0.97 and later */
+ #if !HAVE_POLKIT_AUTHORITY_GET_SYNC
+ static inline PolkitAuthority *
+ polkit_authority_get_sync (GCancellable *cancellable, GError **error)
+ {
+       PolkitAuthority *authority;
+       authority = polkit_authority_get ();
+       if (!authority)
+               g_set_error (error, 0, 0, "failed to get the PolicyKit authority");
+       return authority;
+ }
+ #endif
  #endif /* NM_POLKIT_HELPERS_H */
index e089cf6,0000000..3b36a08
mode 100644,000000..100644
--- /dev/null
@@@ -1,781 -1,0 +1,781 @@@
-       guint group_ids_size;
 +/* NetworkManager user session tracker
 + *
 + * 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.
 + *
 + * (C) Copyright 2010 Daniel Gnoutcheff <daniel@gnoutcheff.name>
 + */
 +
 +#include <sys/types.h>
 +#include <pwd.h>
 +#include <grp.h>
 +#include <dbus/dbus-glib-lowlevel.h>
 +#include <nm-utils.h>
 +#include <nm-dbus-glib-types.h>
 +#include "nm-dbus-manager.h"
 +#include "nm-session-manager.h"
 +
 +G_DEFINE_TYPE (NMSessionManager, nm_session_manager, G_TYPE_OBJECT);
 +
 +/* NMSessionManager data */
 +typedef struct {
 +      gboolean disposed;
 +      gboolean initalized;
 +
 +      /* The master table of NMSessionInfo instances, keyed by session id. */
 +      GHashTable *sessions;
 +
 +      /* DBus proxy of the ConsoleKit manager */
 +      DBusGProxy *ck_manager;
 +
 +      /* Table of PendingSessionInfo structs, representing sessions for which we
 +       * are waiting for information on. Keyed by session id. */
 +      GHashTable *pending_sessions;
 +
 +      /* List of PendingCallerInfo structs, representing ongoing
 +       * get_session_of_caller calls. */
 +      GSList *pending_callers;
 +} NMSessionManagerPrivate;
 +
 +#define NM_SESSION_MANAGER_GET_PRIVATE(self) (G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_SESSION_MANAGER, NMSessionManagerPrivate))
 +
 +
 +enum {
 +      ADDED,
 +      INIT_DONE,
 +
 +      LAST_SIGNAL
 +};
 +static guint signals[LAST_SIGNAL] = { 0 };
 +
 +
 +/**** general utilities for managing callbacks *******************************/
 +
 +typedef struct {
 +      NMSessionFunc callback;
 +      gpointer user_data;
 +} CallbackInfo;
 +
 +/* Allocate a new CallbackInfo for the given callback & data */
 +static CallbackInfo *
 +callback_info_new (NMSessionFunc callback, gpointer user_data)
 +{
 +      CallbackInfo *info = g_slice_new (CallbackInfo);
 +      info->callback = callback;
 +      info->user_data = user_data;
 +      return info;
 +}
 +
 +/* Run the callback represented by cb_info and free it. */
 +static void
 +callback_info_run (CallbackInfo *cb_info, NMSessionInfo *session, GError *error)
 +{
 +      if (cb_info->callback) {
 +              (cb_info->callback) (session, error, cb_info->user_data);
 +      }
 +      g_slice_free (CallbackInfo, cb_info);
 +}
 +
 +/* Run the callback with an error message indicating that we've been disposed. */
 +static void
 +callback_info_fail_disposed (CallbackInfo *cb_info)
 +{
 +      GError *error = g_error_new (NM_SESSION_MANAGER_ERROR,
 +                                   NM_SESSION_MANAGER_ERROR_DISPOSED,
 +                                   "NMSessionManager was disposed before operation completed.");
 +      callback_info_run (cb_info, NULL, error);
 +      g_error_free (error);
 +}
 +
 +
 +/**** get_session stuff ******************************************************/
 +
 +typedef struct {
 +      NMSessionManager *manager;
 +      DBusGProxy *session_proxy;
 +      DBusGProxyCall *session_call;
 +      char *session_id;
 +
 +      GSList *callbacks; /* List of CallbackInfo structs */
 +} PendingSessionInfo;
 +
 +/* Called by the pending_sessions GHashTable when removing a PendingSession */
 +static void
 +pending_session_destroy (gpointer data)
 +{
 +      PendingSessionInfo *pending = (PendingSessionInfo *) data;
 +
 +      // FIXME this is ugly copy-and-paste
 +      // If any callbacks remain, send failure messages to them.
 +      while (pending->callbacks) {
 +              CallbackInfo *cb_info = (CallbackInfo *) pending->callbacks->data;
 +              callback_info_fail_disposed (cb_info);
 +              pending->callbacks = g_slist_remove (pending->callbacks, cb_info);
 +      }
 +
 +      g_free (pending->session_id);
 +      g_object_unref (pending->session_proxy);
 +      g_object_unref (pending->session_call);
 +      g_slice_free (PendingSessionInfo, pending);
 +}
 +
 +static void
 +pending_session_finish (PendingSessionInfo *pending, 
 +                        NMSessionInfo *session,
 +                        GError *error)
 +{
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (pending->manager);
 +
 +      while (pending->callbacks) {
 +              CallbackInfo *cb_info = (CallbackInfo *) pending->callbacks->data;
 +              callback_info_run (cb_info, session, error);
 +              pending->callbacks = g_slist_remove (pending->callbacks, cb_info);
 +      }
 +
 +      g_hash_table_remove (priv->pending_sessions, pending->session_id);
 +      // pending_session_destroy() will be called by GHashTable
 +}
 +
 +static void
 +pending_session_cancel (PendingSessionInfo *pending, GError *error)
 +{
 +      dbus_g_proxy_cancel_call (pending->session_proxy, pending->session_call);
 +      pending_session_finish (pending, NULL, error);
 +}
 +
 +static void
 +get_unix_user_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
 +{
 +      PendingSessionInfo *pending = (PendingSessionInfo *) user_data;
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (pending->manager);
 +      guint user_id;
 +      struct passwd *pw_info = NULL;
 +      int ngroups;
-       group_ids_size = ngroups * sizeof(gid_t);
++      guint group_ids_size = 0;
 +      gid_t *group_ids = NULL;
 +      GSList *group_names = NULL;
 +      NMSessionInfo *session = NULL;
 +      GError *error = NULL;
 +      int i;
 +
 +      if (!dbus_g_proxy_end_call (proxy, call_id, NULL, 
 +                                  G_TYPE_UINT, &user_id, G_TYPE_NONE)) {
 +          error = g_error_new (NM_SESSION_MANAGER_ERROR,
 +                               NM_SESSION_MANAGER_ERROR_INFO_GATHERING_FAILED,
 +                               "session %s: failed to get uid", 
 +                               pending->session_id);
 +          goto out;
 +      }
 +
 +      pw_info = getpwuid (user_id);
 +      if (!pw_info) {
 +          error = g_error_new (NM_SESSION_MANAGER_ERROR,
 +                               NM_SESSION_MANAGER_ERROR_INFO_GATHERING_FAILED,
 +                               "session %s: failed to get username for uid %u", 
 +                               pending->session_id, user_id);
 +          goto out;
 +      }
 +
 +      // Figure out how many groups the user is in
 +      group_ids = g_slice_alloc (0);
 +      ngroups = 0;
 +      getgrouplist (pw_info->pw_name, pw_info->pw_gid, group_ids, &ngroups);
 +      g_slice_free1 (0, group_ids);
 +
 +      // Get the list of group IDs
 +      // FIXME what happens if the group list changes in the window between the
 +      // two getgrouplist calls?
++      group_ids_size = ngroups * sizeof (gid_t);
 +      group_ids = g_slice_alloc (group_ids_size);
 +      if (getgrouplist (pw_info->pw_name, pw_info->pw_gid, group_ids, &ngroups) == -1) {
 +          error = g_error_new (NM_SESSION_MANAGER_ERROR,
 +                               NM_SESSION_MANAGER_ERROR_INFO_GATHERING_FAILED,
 +                               "session %s: failed to get groups for user %s", 
 +                               pending->session_id, pw_info->pw_name);
 +          goto out;
 +      }
 +
 +      for (i = 0; i < ngroups; i++) {
 +              struct group *gr_info = getgrgid (group_ids[i]);
 +              group_names = g_slist_prepend (group_names, g_strdup (gr_info->gr_name));
 +      }
 +
 +      session = g_object_new (NM_TYPE_SESSION_INFO, 
 +                              NM_SESSION_INFO_ID, pending->session_id,
 +                              NM_SESSION_INFO_UNIX_USER, pw_info->pw_name,
 +                              NM_SESSION_INFO_UNIX_GROUPS, group_names,
 +                              NULL);
 +      g_assert (session);
 +
 +      g_hash_table_insert (priv->sessions, nm_session_info_get_id (session), session);
 +      g_signal_emit (pending->manager, signals[ADDED], 0, session);
 +
 +out:
 +      if (group_names)
 +              nm_utils_slist_free (group_names, g_free);
 +      if (group_ids)
 +              g_slice_free1 (group_ids_size, group_ids);
 +
 +      pending_session_finish (pending, session, error);
 +
 +      g_clear_error (&error);
 +}
 +
 +/* Start the process of loading information about the given session, and return
 + * the PendingSessionInfo struct that represents it.
 + */ 
 +static PendingSessionInfo *
 +pending_session_start (NMSessionManager *self, char *session_id)
 +{
 +      PendingSessionInfo *pending = g_slice_new (PendingSessionInfo);
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (self);
 +      DBusGConnection *connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ());
 +
 +      pending->session_id = g_strdup (session_id);
 +      pending->manager = self;
 +      pending->callbacks = NULL;
 +              
 +      pending->session_proxy = dbus_g_proxy_new_for_name (connection,
 +                                                          "org.freedesktop.ConsoleKit",
 +                                                          pending->session_id,
 +                                                          "org.freedesktop.ConsoleKit.Session");
 +
 +      pending->session_call = dbus_g_proxy_begin_call (pending->session_proxy,
 +                                                       "GetUnixUser",
 +                                                       get_unix_user_cb,
 +                                                       pending,
 +                                                       NULL,
 +                                                       G_TYPE_INVALID);
 +
 +      g_hash_table_insert (priv->pending_sessions, pending->session_id, pending);
 +
 +      return pending;
 +}
 +
 +static PendingSessionInfo *
 +pending_session_find (NMSessionManager *self, char *session_id) {
 +      GHashTable *pending_sessions = NM_SESSION_MANAGER_GET_PRIVATE (self)->pending_sessions;
 +      return g_hash_table_lookup (pending_sessions, session_id);
 +}
 +
 +static void
 +pending_session_add_callback (PendingSessionInfo *pending, CallbackInfo *cb_info)
 +{
 +      pending->callbacks = g_slist_prepend (pending->callbacks, cb_info);
 +}
 +
 +static void
 +get_session_internal (NMSessionManager *self,
 +                      char *session_id,
 +                      CallbackInfo *cb_info)
 +{
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (self);
 +      NMSessionInfo *session;
 +      
 +      if (priv->disposed) {
 +              callback_info_fail_disposed (cb_info);
 +              return;
 +      }
 +      
 +      session = g_hash_table_lookup (priv->sessions, session_id);
 +      if (session) {
 +              callback_info_run (cb_info, session, NULL);
 +      } else {
 +              PendingSessionInfo *pending = pending_session_find (self, session_id);
 +              if (!pending) {
 +                      pending = pending_session_start (self, session_id);
 +              }
 +              pending_session_add_callback (pending, cb_info);
 +      }
 +}
 +
 +void
 +nm_session_manager_get_session (NMSessionManager *self,
 +                                char *session_id,
 +                                NMSessionFunc callback,
 +                                gpointer user_data)
 +{
 +      CallbackInfo *cb_info;
 +      
 +      g_return_if_fail (NM_IS_SESSION_MANAGER (self));
 +      g_return_if_fail (session_id != NULL);
 +      g_return_if_fail (callback != NULL);
 +
 +      cb_info = callback_info_new (callback, user_data);
 +
 +      get_session_internal (self, session_id, cb_info);
 +}
 +
 +/**** get_sessions stuff *****************************************************/
 +
 +static void
 +prepend_slist (gpointer key, gpointer value, gpointer user_data)
 +{
 +      GSList **sessions = (GSList **) user_data;
 +
 +      *sessions = g_slist_prepend (*sessions, value);
 +}
 +
 +GSList *
 +nm_session_manager_get_sessions (NMSessionManager *self)
 +{
 +      NMSessionManagerPrivate *priv;
 +      GSList *sessions;
 +
 +      g_return_val_if_fail (NM_IS_SESSION_MANAGER (self), NULL);
 +
 +      priv = NM_SESSION_MANAGER_GET_PRIVATE (self);
 +      g_hash_table_foreach (priv->sessions, prepend_slist, &sessions);
 +
 +      return sessions;
 +}
 +
 +/**** ConsoleKit signal handling *********************************************/
 +
 +/* ConsoleKit reports a new session. Pull it into our cache. */
 +static void
 +session_added (NMSessionManager *self, char *new_session) 
 +{
 +      nm_session_manager_get_session (self, new_session, NULL, NULL);
 +}
 +
 +/* ConsoleKit reports that a session has been removed. */
 +static void
 +session_removed (NMSessionManager *self, char *removed_id)
 +{
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (self);
 +      NMSessionInfo *removed = g_hash_table_lookup (priv->sessions, removed_id);
 +
 +      if (removed) {
 +              g_signal_emit_by_name (removed, NM_SESSION_INFO_REMOVED);
 +              g_hash_table_remove (priv->sessions, removed_id);
 +      } else {
 +              PendingSessionInfo *removed_pending = pending_session_find (self, removed_id);
 +              if (removed_pending) {
 +                      GError *error = g_error_new (NM_SESSION_MANAGER_ERROR,
 +                                                   NM_SESSION_MANAGER_ERROR_NOT_FOUND,
 +                                                   "session %s removed moments ago",
 +                                                   removed_id);
 +                      pending_session_cancel (removed_pending, error);
 +                      g_error_free (error);
 +              }
 +      }               
 +}
 +
 +/* A DBus signal filter for picking up ConsoleKit signals indicating that
 + * sessions have been added or removed. We use this custom message filter as
 + * we'd otherwise have to keep track of all the seats and register signal
 + * handlers in every one. */
 +static DBusHandlerResult
 +ck_session_signal_filter (DBusConnection *connection,
 +                          DBusMessage *message,
 +                          void *user_data)
 +{
 +      NMSessionManager *self = NM_SESSION_MANAGER (user_data);
 +      char *session_id;
 +
 +      // TODO: filter by sender?
 +
 +      if (dbus_message_is_signal (message, 
 +                                  "org.freedesktop.ConsoleKit.Seat",
 +                                  "SessionAdded")) {
 +              if (dbus_message_get_args (message, NULL, 
 +                                             DBUS_TYPE_OBJECT_PATH, &session_id,
 +                                             DBUS_TYPE_INVALID)) {
 +                      session_added (self, session_id);
 +              }
 +      }
 +      else
 +      if (dbus_message_is_signal (message,
 +                                      "org.freedesktop.ConsoleKit.Seat",
 +                                      "SessionRemoved")) {
 +              if (dbus_message_get_args (message, NULL,
 +                                         DBUS_TYPE_OBJECT_PATH, &session_id,
 +                                         DBUS_TYPE_INVALID)) {
 +                      session_removed (self, session_id);
 +              }
 +      }
 +
 +      // If anything else registers message filters for these signals for some
 +      // reason, we want to be sure not to step on them.
 +      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 +}
 +
 +/**** get_session_of_caller stuff ********************************************/
 +
 +typedef struct {
 +      NMSessionManager *manager;
 +      CallbackInfo *cb_info;
 +      DBusGProxy *bus_proxy;
 +      DBusGProxy *current_call_proxy;
 +      DBusGProxyCall *current_call;
 +      char *caller_bus_name;
 +      char *session_id;
 +} PendingCallerInfo;
 +
 +static void
 +pending_caller_free (PendingCallerInfo *info)
 +{
 +      if (info->bus_proxy)
 +              g_object_unref (info->bus_proxy);
 +
 +      if (info->caller_bus_name)
 +              g_free (info->caller_bus_name);
 +
 +      if (info->session_id)
 +              g_free (info->session_id);
 +
 +      // cb_info gets freed when the callback it wraps is run
 +
 +      g_slice_free (PendingCallerInfo, info);
 +}
 +
 +static void
 +pending_caller_dispose (gpointer data)
 +{
 +      PendingCallerInfo *info = (PendingCallerInfo *) data;
 +
 +      if (info->current_call)
 +              dbus_g_proxy_cancel_call (info->current_call_proxy, info->current_call);
 +
 +      callback_info_fail_disposed (info->cb_info);
 +      pending_caller_free (info);
 +}
 +
 +static void
 +pending_caller_cb (NMSessionInfo *session, GError *error, gpointer user_data)
 +{
 +      PendingCallerInfo *info = (PendingCallerInfo *) user_data;
 +
 +      if (!session) {
 +              get_session_internal (info->manager, NM_SESSION_INFO_DEFAULT_ID, info->cb_info);
 +      } else {
 +              callback_info_run (info->cb_info, session, error);
 +      }
 +
 +      pending_caller_free (info);
 +}
 +
 +static void
 +pending_caller_abort (PendingCallerInfo *info, GError *error)
 +{
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (info->manager);
 +
 +      priv->pending_callers = g_slist_remove (priv->pending_callers, info);
 +      pending_caller_cb (NULL, error, info);
 +}
 +
 +static void
 +dbus_name_has_owner_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
 +{
 +      PendingCallerInfo *info = (PendingCallerInfo *) user_data;
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (info->manager);
 +      gboolean has_owner;
 +
 +      if (!dbus_g_proxy_end_call (proxy, call_id, NULL,
 +                                  G_TYPE_BOOLEAN, &has_owner, G_TYPE_INVALID)
 +              || !has_owner) {
 +          pending_caller_abort (info, NULL);
 +          return;
 +      }
 +
 +      info->current_call = NULL;
 +      info->current_call_proxy = NULL;
 +      priv->pending_callers = g_slist_remove (priv->pending_callers, info);
 +
 +      nm_session_manager_get_session (info->manager, info->session_id,
 +                                      pending_caller_cb, info);
 +}
 +
 +static void
 +ck_get_session_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
 +{
 +      PendingCallerInfo *info = (PendingCallerInfo *) user_data;
 +
 +      if (!dbus_g_proxy_end_call (proxy, call_id, NULL,
 +                                  G_TYPE_STRING, &(info->session_id),
 +                                  G_TYPE_INVALID)) {
 +              pending_caller_abort (info, NULL);
 +          return;
 +      }
 +
 +      // Finally, ensure that the calling process is still there, so we are sure
 +      // that the process we've just examined is indeed the calling process.
 +      info->current_call = dbus_g_proxy_begin_call (info->bus_proxy,
 +                                                    "NameHasOwner",
 +                                                    dbus_name_has_owner_cb,
 +                                                    info,
 +                                                    NULL,
 +                                                    G_TYPE_STRING, info->caller_bus_name,
 +                                                    G_TYPE_INVALID);
 +      info->current_call_proxy = info->bus_proxy;
 +}
 +
 +static void
 +dbus_get_pid_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
 +{
 +      PendingCallerInfo *info = (PendingCallerInfo *) user_data;
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (info->manager);
 +      guint pid;
 +
 +      if (!dbus_g_proxy_end_call (proxy, call_id, NULL,
 +                                  G_TYPE_UINT, &pid, G_TYPE_INVALID)) {
 +              pending_caller_abort (info, NULL);
 +          return;
 +      }
 +
 +      info->current_call = dbus_g_proxy_begin_call (priv->ck_manager,
 +                                                    "GetSessionForUnixProcess",
 +                                                    ck_get_session_cb,
 +                                                    info,
 +                                                    NULL,
 +                                                    G_TYPE_UINT, pid,
 +                                                    G_TYPE_INVALID);
 +      info->current_call_proxy = priv->ck_manager;
 +}
 +
 +static void
 +get_session_of_caller_internal (NMSessionManager *manager, 
 +                                DBusGMethodInvocation *method_call,
 +                                CallbackInfo *cb_info)
 +{
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (manager);
 +      DBusGConnection *connection;
 +      PendingCallerInfo *info;
 +
 +      if (priv->disposed) {
 +              callback_info_fail_disposed (cb_info);
 +              return;
 +      }
 +      connection = nm_dbus_manager_get_connection (nm_dbus_manager_get());
 +
 +      info = g_slice_new (PendingCallerInfo);
 +      info->manager = manager;
 +      info->cb_info = cb_info;
 +      info->caller_bus_name = dbus_g_method_get_sender (method_call);
 +      info->bus_proxy = dbus_g_proxy_new_for_name (connection,
 +                                                   "org.freedesktop.DBus",
 +                                                   "/org/freedesktop/DBus",
 +                                                   "org.freedesktop.DBus");
 +
 +      info->current_call = dbus_g_proxy_begin_call (info->bus_proxy,
 +                                                    "GetConnectionUnixProcessID",
 +                                                    dbus_get_pid_cb,
 +                                                    info,
 +                                                    NULL,
 +                                                    G_TYPE_STRING, info->caller_bus_name,
 +                                                    G_TYPE_INVALID);
 +      info->current_call_proxy = info->bus_proxy;
 +
 +      priv->pending_callers = g_slist_prepend (priv->pending_callers, info);
 +
 +      g_object_unref (connection);
 +}
 +
 +void
 +nm_session_manager_get_session_of_caller (NMSessionManager *manager, 
 +                                          DBusGMethodInvocation *method_call,
 +                                          NMSessionFunc callback, 
 +                                          gpointer user_data)
 +{
 +      CallbackInfo *cb_info;
 +
 +      g_return_if_fail (NM_IS_SESSION_MANAGER (manager));
 +      g_return_if_fail (method_call != NULL);
 +
 +      cb_info = callback_info_new (callback, user_data);
 +
 +      get_session_of_caller_internal (manager, method_call, cb_info);
 +}
 +
 +
 +/**** Initialization & disposal **********************************************/
 +
 +gboolean
 +nm_session_manager_is_initalized (NMSessionManager *self)
 +{
 +      g_return_val_if_fail (NM_IS_SESSION_MANAGER (self), FALSE);
 +
 +      return NM_SESSION_MANAGER_GET_PRIVATE (self)->initalized;
 +}
 +
 +typedef struct {
 +      NMSessionManager *manager;
 +      guint sessions_left;
 +} InitInfo;
 +
 +/* Callback run for sessions loaded during initialization. Emits the
 + * "initialized" signal when all sessions are loaded. */
 +static void
 +init_session_load_cb (NMSessionInfo *session, GError *error, gpointer user_data)
 +{
 +      InitInfo *info = (InitInfo *) user_data;
 +      info->sessions_left--;
 +
 +      if (info->sessions_left == 0) {
 +              NM_SESSION_MANAGER_GET_PRIVATE (info->manager)->initalized = TRUE;
 +              g_signal_emit (info->manager, signals[INIT_DONE], 0);
 +              g_slice_free (InitInfo, info);
 +      }
 +}
 +
 +static void
 +ck_get_sessions_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
 +{
 +      NMSessionManager *manager = NM_SESSION_MANAGER (user_data);
 +      GPtrArray *session_ids;
 +      InitInfo *info;
 +      int i;
 +      
 +      if (!dbus_g_proxy_end_call (proxy, call_id, NULL,
 +                                  DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &session_ids,
 +                                  G_TYPE_INVALID)) {
 +          g_warning ("NMSessionManager: error getting sessions list!");
 +          return;
 +      }
 +
 +      info = g_slice_new (InitInfo);
 +      info->manager = manager;
 +      info->sessions_left = session_ids->len;
 +
 +      for (i = 0; i < session_ids->len; i++) {
 +              char *session_id = g_ptr_array_index (session_ids, i);
 +              nm_session_manager_get_session (manager, session_id, init_session_load_cb, info);
 +              g_free (session_id);
 +      }
 +      g_ptr_array_free (session_ids, TRUE);
 +}
 +
 +static void
 +nm_session_manager_init (NMSessionManager *self)
 +{
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (self);
 +      NMSessionInfo *default_session;
 +      DBusGConnection *g_connection = nm_dbus_manager_get_connection (nm_dbus_manager_get());
 +      DBusConnection *connection = dbus_g_connection_get_connection (g_connection);
 +
 +      priv->disposed = FALSE;
 +      priv->initalized = FALSE;
 +      priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, 
 +                                              NULL, g_object_unref);
 +      priv->pending_sessions = g_hash_table_new_full (g_str_hash, g_str_equal, 
 +                                                      NULL, pending_session_destroy);
 +      priv->pending_callers = NULL;
 +
 +      default_session = NM_SESSION_INFO (g_object_new (NM_TYPE_SESSION_INFO,
 +                                                       NM_SESSION_INFO_IS_DEFAULT, TRUE,
 +                                                       NM_SESSION_INFO_ID, NM_SESSION_INFO_DEFAULT_ID,
 +                                                       NULL));
 +      g_hash_table_insert (priv->sessions, 
 +                           NM_SESSION_INFO_DEFAULT_ID, default_session);
 +
 +
 +      priv->ck_manager = dbus_g_proxy_new_for_name (g_connection,
 +                                                    "org.freedesktop.ConsoleKit",
 +                                                    "/org/freedesktop/ConsoleKit/Manager",
 +                                                    "org.freedesktop.ConsoleKit.Manager");
 +
 +      // Setup a signal handler to catch SessionAdded/Removed signals for *all*
 +      // seats, all in one shot.
 +      dbus_connection_add_filter (connection,
 +                                  ck_session_signal_filter,
 +                                  self,
 +                                  NULL);
 +      dbus_bus_add_match (connection,
 +                          "type='signal',sender='org.freedesktop.ConsoleKit',"
 +                          "interface='org.freedesktop.ConsoleKit.Seat',member='SessionAdded'",
 +                          NULL);
 +      dbus_bus_add_match (connection,
 +                          "type='signal',sender='org.freedesktop.ConsoleKit',"
 +                          "interface='org.freedesktop.ConsoleKit.Seat',member='SessionRemoved'",
 +                          NULL);
 +
 +      dbus_g_proxy_begin_call (priv->ck_manager,
 +                               "GetSessions",
 +                               ck_get_sessions_cb,
 +                               self,
 +                               NULL,
 +                               G_TYPE_INVALID);
 +}
 +
 +static void
 +dispose (GObject *object)
 +{
 +      NMSessionManagerPrivate *priv = NM_SESSION_MANAGER_GET_PRIVATE (object);
 +      DBusConnection *connection = nm_dbus_manager_get_dbus_connection (nm_dbus_manager_get ());
 +
 +      if (priv->disposed)
 +              return;
 +
 +      priv->disposed = TRUE;
 +
 +      dbus_connection_remove_filter (connection, ck_session_signal_filter, object);
 +      nm_utils_slist_free (priv->pending_callers, pending_caller_dispose);
 +      g_hash_table_unref (priv->pending_sessions);
 +      g_hash_table_unref (priv->sessions);
 +      g_object_unref(priv->ck_manager);
 +
 +      G_OBJECT_CLASS (nm_session_manager_parent_class)->dispose (object);     
 +}
 +
 +static void
 +nm_session_manager_class_init (NMSessionManagerClass *manager_class) {
 +      GObjectClass *g_class = G_OBJECT_CLASS (manager_class);
 +      g_type_class_add_private (g_class, sizeof(NMSessionManagerPrivate));    
 +      g_class->dispose = dispose;
 +
 +      signals[ADDED] = 
 +              g_signal_new (NM_SESSION_MANAGER_SESSION_ADDED,
 +                            NM_TYPE_SESSION_MANAGER,
 +                            G_SIGNAL_RUN_FIRST,
 +                            0,
 +                            NULL, NULL,
 +                            g_cclosure_marshal_VOID__OBJECT,
 +                            G_TYPE_NONE,
 +                            1, NM_TYPE_SESSION_INFO);
 +
 +      signals[INIT_DONE] =
 +              g_signal_new (NM_SESSION_MANAGER_INIT_DONE,
 +                            NM_TYPE_SESSION_MANAGER,
 +                            G_SIGNAL_RUN_FIRST,
 +                            0,
 +                            NULL, NULL,
 +                            g_cclosure_marshal_VOID__VOID,
 +                            G_TYPE_NONE,
 +                            0);
 +}
 +
 +NMSessionManager *
 +nm_session_manager_get (void)
 +{
 +      static NMSessionManager *singleton = NULL;
 +
 +      if (!singleton) {
 +              singleton = NM_SESSION_MANAGER (g_object_new (NM_TYPE_SESSION_MANAGER, NULL));
 +      }
 +
 +      return singleton;
 +}
 +
 +GQuark
 +nm_session_manager_error_quark (void)
 +{
 +      static GQuark ret = 0;
 +
 +      if (ret == 0) {
 +              ret = g_quark_from_string ("nm-session-manager-error");
 +      }
 +
 +      return ret;
 +}
@@@ -1001,34 -612,15 +1001,38 @@@ static voi
  nm_sysconfig_connection_init (NMSysconfigConnection *self)
  {
        NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
 +      NMSessionManager *session_manager;
 +      static guint32 dbus_counter = 0;
 +      char *dbus_path;
+       GError *error = NULL;
  
-       priv->authority = polkit_authority_get ();
+       priv->authority = polkit_authority_get_sync (NULL, NULL);
        if (!priv->authority) {
-               nm_log_err (LOGD_SYS_SET, "%s:error creating PolicyKit authority");
+               nm_log_warn (LOGD_SYS_SET, "failed to create PolicyKit authority: (%d) %s",
+                            error ? error->code : -1,
+                            error && error->message ? error->message : "(unknown)");
+               g_clear_error (&error);
        }
 +
 +      dbus_path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, dbus_counter++);
 +      nm_connection_set_path (NM_CONNECTION (self), dbus_path);       
 +      g_free (dbus_path);
 +      priv->visible = FALSE;
 +
 +      priv->access_list = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
 +      session_manager = nm_session_manager_get();
 +      g_signal_connect (session_manager, NM_SESSION_MANAGER_SESSION_ADDED,
 +                        G_CALLBACK (session_added_cb), self);
 +
 +}
 +
 +static void
 +access_list_dispose (gpointer key, gpointer value, gpointer user_data)
 +{
 +      NMSysconfigConnection *connection = (NMSysconfigConnection *) user_data;
 +      NMSessionInfo *session = (NMSessionInfo *) value;
 +
 +      g_signal_handlers_disconnect_by_func (session, session_removed_cb, connection);
  }
  
  static void
@@@ -1601,11 -1505,11 +1601,12 @@@ static voi
  nm_sysconfig_settings_init (NMSysconfigSettings *self)
  {
        NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+       GError *error = NULL;
  
 -      priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
 +      priv->visible_connections = g_hash_table_new (g_direct_hash, g_direct_equal);
 +      priv->all_connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
  
-       priv->authority = polkit_authority_get ();
+       priv->authority = polkit_authority_get_sync (NULL, &error);
        if (priv->authority) {
                priv->auth_changed_id = g_signal_connect (priv->authority,
                                                          "changed",
Simple merge
@@@ -551,10 -544,10 +551,10 @@@ impl_ifcfgrh_get_ifcfg_details (SCPlugi
        }
  
        connection = g_hash_table_lookup (priv->connections, in_ifcfg);
-       if (!connection) {
+       if (!connection || nm_ifcfg_connection_get_unmanaged_spec (connection)) {
                g_set_error (error,
 -                           NM_SETTINGS_INTERFACE_ERROR,
 -                           NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
 +                           NM_SYSCONFIG_SETTINGS_ERROR,
 +                           NM_SYSCONFIG_SETTINGS_ERROR_INVALID_CONNECTION,
                             "ifcfg file '%s' unknown", in_ifcfg);
                return FALSE;
        }