Home | History | Annotate | Download | only in bus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* services.c  Service management
      3  *
      4  * Copyright (C) 2003  Red Hat, Inc.
      5  * Copyright (C) 2003  CodeFactory AB
      6  *
      7  * Licensed under the Academic Free License version 2.1
      8  *
      9  * This program is free software; you can redistribute it and/or modify
     10  * it under the terms of the GNU General Public License as published by
     11  * the Free Software Foundation; either version 2 of the License, or
     12  * (at your option) any later version.
     13  *
     14  * This program is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  * GNU General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU General Public License
     20  * along with this program; if not, write to the Free Software
     21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     22  *
     23  */
     24 
     25 #include <config.h>
     26 #include <dbus/dbus-hash.h>
     27 #include <dbus/dbus-list.h>
     28 #include <dbus/dbus-mempool.h>
     29 #include <dbus/dbus-marshal-validate.h>
     30 
     31 #include "driver.h"
     32 #include "services.h"
     33 #include "connection.h"
     34 #include "utils.h"
     35 #include "activation.h"
     36 #include "policy.h"
     37 #include "bus.h"
     38 #include "selinux.h"
     39 
     40 struct BusService
     41 {
     42   int refcount;
     43 
     44   BusRegistry *registry;
     45   char *name;
     46   DBusList *owners;
     47 };
     48 
     49 struct BusOwner
     50 {
     51   int refcount;
     52 
     53   BusService *service;
     54   DBusConnection *conn;
     55 
     56   unsigned int allow_replacement : 1;
     57   unsigned int do_not_queue : 1;
     58 };
     59 
     60 struct BusRegistry
     61 {
     62   int refcount;
     63 
     64   BusContext *context;
     65 
     66   DBusHashTable *service_hash;
     67   DBusMemPool   *service_pool;
     68   DBusMemPool   *owner_pool;
     69 
     70   DBusHashTable *service_sid_table;
     71 };
     72 
     73 BusRegistry*
     74 bus_registry_new (BusContext *context)
     75 {
     76   BusRegistry *registry;
     77 
     78   registry = dbus_new0 (BusRegistry, 1);
     79   if (registry == NULL)
     80     return NULL;
     81 
     82   registry->refcount = 1;
     83   registry->context = context;
     84 
     85   registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
     86                                                  NULL, NULL);
     87   if (registry->service_hash == NULL)
     88     goto failed;
     89 
     90   registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
     91                                                TRUE);
     92 
     93   if (registry->service_pool == NULL)
     94     goto failed;
     95 
     96   registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
     97                                              TRUE);
     98 
     99   if (registry->owner_pool == NULL)
    100     goto failed;
    101 
    102   registry->service_sid_table = NULL;
    103 
    104   return registry;
    105 
    106  failed:
    107   bus_registry_unref (registry);
    108   return NULL;
    109 }
    110 
    111 BusRegistry *
    112 bus_registry_ref (BusRegistry *registry)
    113 {
    114   _dbus_assert (registry->refcount > 0);
    115   registry->refcount += 1;
    116 
    117   return registry;
    118 }
    119 
    120 void
    121 bus_registry_unref  (BusRegistry *registry)
    122 {
    123   _dbus_assert (registry->refcount > 0);
    124   registry->refcount -= 1;
    125 
    126   if (registry->refcount == 0)
    127     {
    128       if (registry->service_hash)
    129         _dbus_hash_table_unref (registry->service_hash);
    130       if (registry->service_pool)
    131         _dbus_mem_pool_free (registry->service_pool);
    132       if (registry->owner_pool)
    133         _dbus_mem_pool_free (registry->owner_pool);
    134       if (registry->service_sid_table)
    135         _dbus_hash_table_unref (registry->service_sid_table);
    136 
    137       dbus_free (registry);
    138     }
    139 }
    140 
    141 BusService*
    142 bus_registry_lookup (BusRegistry      *registry,
    143                      const DBusString *service_name)
    144 {
    145   BusService *service;
    146 
    147   service = _dbus_hash_table_lookup_string (registry->service_hash,
    148                                             _dbus_string_get_const_data (service_name));
    149 
    150   return service;
    151 }
    152 
    153 static DBusList *
    154 _bus_service_find_owner_link (BusService *service,
    155                               DBusConnection *connection)
    156 {
    157   DBusList *link;
    158 
    159   link = _dbus_list_get_first_link (&service->owners);
    160 
    161   while (link != NULL)
    162     {
    163       BusOwner *bus_owner;
    164 
    165       bus_owner = (BusOwner *) link->data;
    166       if (bus_owner->conn == connection)
    167         break;
    168 
    169       link = _dbus_list_get_next_link (&service->owners, link);
    170     }
    171 
    172   return link;
    173 }
    174 
    175 static void
    176 bus_owner_set_flags (BusOwner *owner,
    177                      dbus_uint32_t flags)
    178 {
    179    owner->allow_replacement =
    180         (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
    181 
    182    owner->do_not_queue =
    183         (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
    184 }
    185 
    186 static BusOwner *
    187 bus_owner_new (BusService *service,
    188                DBusConnection *conn,
    189 	       dbus_uint32_t flags)
    190 {
    191   BusOwner *result;
    192 
    193   result = _dbus_mem_pool_alloc (service->registry->owner_pool);
    194   if (result != NULL)
    195     {
    196       result->refcount = 1;
    197       /* don't ref the connection because we don't want
    198          to block the connection from going away.
    199          transactions take care of reffing the connection
    200          but we need to use refcounting on the owner
    201          so that the owner does not get freed before
    202          we can deref the connection in the transaction
    203        */
    204       result->conn = conn;
    205       result->service = service;
    206 
    207       if (!bus_connection_add_owned_service (conn, service))
    208         {
    209           _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
    210           return NULL;
    211         }
    212 
    213       bus_owner_set_flags (result, flags);
    214     }
    215   return result;
    216 }
    217 
    218 static BusOwner *
    219 bus_owner_ref (BusOwner *owner)
    220 {
    221   _dbus_assert (owner->refcount > 0);
    222   owner->refcount += 1;
    223 
    224   return owner;
    225 }
    226 
    227 static void
    228 bus_owner_unref  (BusOwner *owner)
    229 {
    230   _dbus_assert (owner->refcount > 0);
    231   owner->refcount -= 1;
    232 
    233   if (owner->refcount == 0)
    234     {
    235       bus_connection_remove_owned_service (owner->conn, owner->service);
    236       _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
    237     }
    238 }
    239 
    240 BusService*
    241 bus_registry_ensure (BusRegistry               *registry,
    242                      const DBusString          *service_name,
    243                      DBusConnection            *owner_connection_if_created,
    244                      dbus_uint32_t              flags,
    245                      BusTransaction            *transaction,
    246                      DBusError                 *error)
    247 {
    248   BusService *service;
    249 
    250   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    251 
    252   _dbus_assert (owner_connection_if_created != NULL);
    253   _dbus_assert (transaction != NULL);
    254 
    255   service = _dbus_hash_table_lookup_string (registry->service_hash,
    256                                             _dbus_string_get_const_data (service_name));
    257   if (service != NULL)
    258     return service;
    259 
    260   service = _dbus_mem_pool_alloc (registry->service_pool);
    261   if (service == NULL)
    262     {
    263       BUS_SET_OOM (error);
    264       return NULL;
    265     }
    266 
    267   service->registry = registry;
    268   service->refcount = 1;
    269 
    270   _dbus_verbose ("copying string %p '%s' to service->name\n",
    271                  service_name, _dbus_string_get_const_data (service_name));
    272   if (!_dbus_string_copy_data (service_name, &service->name))
    273     {
    274       _dbus_mem_pool_dealloc (registry->service_pool, service);
    275       BUS_SET_OOM (error);
    276       return NULL;
    277     }
    278   _dbus_verbose ("copied string %p '%s' to '%s'\n",
    279                  service_name, _dbus_string_get_const_data (service_name),
    280                  service->name);
    281 
    282   if (!bus_driver_send_service_owner_changed (service->name,
    283 					      NULL,
    284 					      bus_connection_get_name (owner_connection_if_created),
    285 					      transaction, error))
    286     {
    287       bus_service_unref (service);
    288       return NULL;
    289     }
    290 
    291   if (!bus_activation_service_created (bus_context_get_activation (registry->context),
    292 				       service->name, transaction, error))
    293     {
    294       bus_service_unref (service);
    295       return NULL;
    296     }
    297 
    298   if (!bus_service_add_owner (service, owner_connection_if_created, flags,
    299                                               transaction, error))
    300     {
    301       bus_service_unref (service);
    302       return NULL;
    303     }
    304 
    305   if (!_dbus_hash_table_insert_string (registry->service_hash,
    306                                        service->name,
    307                                        service))
    308     {
    309       /* The add_owner gets reverted on transaction cancel */
    310       BUS_SET_OOM (error);
    311       return NULL;
    312     }
    313 
    314   return service;
    315 }
    316 
    317 void
    318 bus_registry_foreach (BusRegistry               *registry,
    319                       BusServiceForeachFunction  function,
    320                       void                      *data)
    321 {
    322   DBusHashIter iter;
    323 
    324   _dbus_hash_iter_init (registry->service_hash, &iter);
    325   while (_dbus_hash_iter_next (&iter))
    326     {
    327       BusService *service = _dbus_hash_iter_get_value (&iter);
    328 
    329       (* function) (service, data);
    330     }
    331 }
    332 
    333 dbus_bool_t
    334 bus_registry_list_services (BusRegistry *registry,
    335                             char      ***listp,
    336                             int         *array_len)
    337 {
    338   int i, j, len;
    339   char **retval;
    340   DBusHashIter iter;
    341 
    342   len = _dbus_hash_table_get_n_entries (registry->service_hash);
    343   retval = dbus_new (char *, len + 1);
    344 
    345   if (retval == NULL)
    346     return FALSE;
    347 
    348   _dbus_hash_iter_init (registry->service_hash, &iter);
    349   i = 0;
    350   while (_dbus_hash_iter_next (&iter))
    351     {
    352       BusService *service = _dbus_hash_iter_get_value (&iter);
    353 
    354       retval[i] = _dbus_strdup (service->name);
    355       if (retval[i] == NULL)
    356 	goto error;
    357 
    358       i++;
    359     }
    360 
    361   retval[i] = NULL;
    362 
    363   if (array_len)
    364     *array_len = len;
    365 
    366   *listp = retval;
    367   return TRUE;
    368 
    369  error:
    370   for (j = 0; j < i; j++)
    371     dbus_free (retval[i]);
    372   dbus_free (retval);
    373 
    374   return FALSE;
    375 }
    376 
    377 dbus_bool_t
    378 bus_registry_acquire_service (BusRegistry      *registry,
    379                               DBusConnection   *connection,
    380                               const DBusString *service_name,
    381                               dbus_uint32_t     flags,
    382                               dbus_uint32_t    *result,
    383                               BusTransaction   *transaction,
    384                               DBusError        *error)
    385 {
    386   dbus_bool_t retval;
    387   DBusConnection *old_owner_conn;
    388   BusClientPolicy *policy;
    389   BusService *service;
    390   BusActivation  *activation;
    391   BusSELinuxID *sid;
    392   BusOwner *primary_owner;
    393 
    394   retval = FALSE;
    395 
    396   if (!_dbus_validate_bus_name (service_name, 0,
    397                                 _dbus_string_get_length (service_name)))
    398     {
    399       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
    400                       "Requested bus name \"%s\" is not valid",
    401                       _dbus_string_get_const_data (service_name));
    402 
    403       _dbus_verbose ("Attempt to acquire invalid service name\n");
    404 
    405       goto out;
    406     }
    407 
    408   if (_dbus_string_get_byte (service_name, 0) == ':')
    409     {
    410       /* Not allowed; only base services can start with ':' */
    411       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
    412                       "Cannot acquire a service starting with ':' such as \"%s\"",
    413                       _dbus_string_get_const_data (service_name));
    414 
    415       _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
    416                      _dbus_string_get_const_data (service_name));
    417 
    418       goto out;
    419     }
    420 
    421   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
    422     {
    423       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
    424                       "Connection \"%s\" is not allowed to own the service \"%s\"because "
    425                       "it is reserved for D-Bus' use only",
    426                       bus_connection_is_active (connection) ?
    427                       bus_connection_get_name (connection) :
    428                       "(inactive)",
    429                       DBUS_SERVICE_DBUS);
    430       goto out;
    431     }
    432 
    433   policy = bus_connection_get_policy (connection);
    434   _dbus_assert (policy != NULL);
    435 
    436   /* Note that if sid is #NULL then the bus's own context gets used
    437    * in bus_connection_selinux_allows_acquire_service()
    438    */
    439   sid = bus_selinux_id_table_lookup (registry->service_sid_table,
    440                                      service_name);
    441 
    442   if (!bus_selinux_allows_acquire_service (connection, sid,
    443 					   _dbus_string_get_const_data (service_name), error))
    444     {
    445 
    446       if (dbus_error_is_set (error) &&
    447 	  dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
    448 	{
    449 	  goto out;
    450 	}
    451 
    452       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
    453                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
    454                       "to SELinux policy",
    455                       bus_connection_is_active (connection) ?
    456                       bus_connection_get_name (connection) :
    457                       "(inactive)",
    458                       _dbus_string_get_const_data (service_name));
    459       goto out;
    460     }
    461 
    462   if (!bus_client_policy_check_can_own (policy, service_name))
    463     {
    464       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
    465                       "Connection \"%s\" is not allowed to own the service \"%s\" due "
    466                       "to security policies in the configuration file",
    467                       bus_connection_is_active (connection) ?
    468                       bus_connection_get_name (connection) :
    469                       "(inactive)",
    470                       _dbus_string_get_const_data (service_name));
    471       goto out;
    472     }
    473 
    474   if (bus_connection_get_n_services_owned (connection) >=
    475       bus_context_get_max_services_per_connection (registry->context))
    476     {
    477       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
    478                       "Connection \"%s\" is not allowed to own more services "
    479                       "(increase limits in configuration file if required)",
    480                       bus_connection_is_active (connection) ?
    481                       bus_connection_get_name (connection) :
    482                       "(inactive)");
    483       goto out;
    484     }
    485 
    486   service = bus_registry_lookup (registry, service_name);
    487 
    488   if (service != NULL)
    489     {
    490       primary_owner = bus_service_get_primary_owner (service);
    491       if (primary_owner != NULL)
    492         old_owner_conn = primary_owner->conn;
    493       else
    494         old_owner_conn = NULL;
    495     }
    496   else
    497     old_owner_conn = NULL;
    498 
    499   if (service == NULL)
    500     {
    501       service = bus_registry_ensure (registry,
    502                                      service_name, connection, flags,
    503                                      transaction, error);
    504       if (service == NULL)
    505         goto out;
    506     }
    507 
    508   primary_owner = bus_service_get_primary_owner (service);
    509   if (primary_owner == NULL)
    510     goto out;
    511 
    512   if (old_owner_conn == NULL)
    513     {
    514       _dbus_assert (primary_owner->conn == connection);
    515 
    516       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
    517     }
    518   else if (old_owner_conn == connection)
    519     {
    520       bus_owner_set_flags (primary_owner, flags);
    521       *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
    522     }
    523   else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
    524            !(bus_service_get_allow_replacement (service))) ||
    525 	   ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
    526            !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
    527     {
    528       DBusList *link;
    529       BusOwner *temp_owner;
    530     /* Since we can't be queued if we are already in the queue
    531        remove us */
    532 
    533       link = _bus_service_find_owner_link (service, connection);
    534       if (link != NULL)
    535         {
    536           _dbus_list_unlink (&service->owners, link);
    537           temp_owner = (BusOwner *)link->data;
    538           bus_owner_unref (temp_owner);
    539           _dbus_list_free_link (link);
    540         }
    541 
    542       *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
    543     }
    544   else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
    545            (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
    546 	    !(bus_service_get_allow_replacement (service))))
    547     {
    548       /* Queue the connection */
    549       if (!bus_service_add_owner (service, connection,
    550                                   flags,
    551                                   transaction, error))
    552         goto out;
    553 
    554       *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
    555     }
    556   else
    557     {
    558       /* Replace the current owner */
    559 
    560       /* We enqueue the new owner and remove the first one because
    561        * that will cause NameAcquired and NameLost messages to
    562        * be sent.
    563        */
    564 
    565       if (!bus_service_add_owner (service, connection,
    566                                   flags,
    567                                   transaction, error))
    568         goto out;
    569 
    570       if (primary_owner->do_not_queue)
    571         {
    572           if (!bus_service_remove_owner (service, old_owner_conn,
    573                                          transaction, error))
    574             goto out;
    575         }
    576       else
    577         {
    578           if (!bus_service_swap_owner (service, old_owner_conn,
    579                                        transaction, error))
    580             goto out;
    581         }
    582 
    583 
    584       _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
    585       *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
    586     }
    587 
    588   activation = bus_context_get_activation (registry->context);
    589   retval = bus_activation_send_pending_auto_activation_messages (activation,
    590 								 service,
    591 								 transaction,
    592 								 error);
    593 
    594  out:
    595   return retval;
    596 }
    597 
    598 dbus_bool_t
    599 bus_registry_release_service (BusRegistry      *registry,
    600                               DBusConnection   *connection,
    601                               const DBusString *service_name,
    602                               dbus_uint32_t    *result,
    603                               BusTransaction   *transaction,
    604                               DBusError        *error)
    605 {
    606   dbus_bool_t retval;
    607   BusService *service;
    608 
    609   retval = FALSE;
    610 
    611   if (!_dbus_validate_bus_name (service_name, 0,
    612                                 _dbus_string_get_length (service_name)))
    613     {
    614       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
    615                       "Given bus name \"%s\" is not valid",
    616                       _dbus_string_get_const_data (service_name));
    617 
    618       _dbus_verbose ("Attempt to release invalid service name\n");
    619 
    620       goto out;
    621     }
    622 
    623   if (_dbus_string_get_byte (service_name, 0) == ':')
    624     {
    625       /* Not allowed; the base service name cannot be created or released */
    626       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
    627                       "Cannot release a service starting with ':' such as \"%s\"",
    628                       _dbus_string_get_const_data (service_name));
    629 
    630       _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
    631                      _dbus_string_get_const_data (service_name));
    632 
    633       goto out;
    634     }
    635 
    636    if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
    637     {
    638       /* Not allowed; the base service name cannot be created or released */
    639       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
    640                       "Cannot release the %s service because it is owned by the bus",
    641                      DBUS_SERVICE_DBUS);
    642 
    643       _dbus_verbose ("Attempt to release service name \"%s\"",
    644                      DBUS_SERVICE_DBUS);
    645 
    646       goto out;
    647     }
    648 
    649   service = bus_registry_lookup (registry, service_name);
    650 
    651   if (service == NULL)
    652     {
    653       *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
    654     }
    655   else if (!bus_service_has_owner (service, connection))
    656     {
    657       *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
    658     }
    659   else
    660     {
    661       if (!bus_service_remove_owner (service, connection,
    662                                      transaction, error))
    663         goto out;
    664 
    665       _dbus_assert (!bus_service_has_owner (service, connection));
    666       *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
    667     }
    668 
    669   retval = TRUE;
    670 
    671  out:
    672   return retval;
    673 }
    674 
    675 dbus_bool_t
    676 bus_registry_set_service_context_table (BusRegistry   *registry,
    677 					DBusHashTable *table)
    678 {
    679   DBusHashTable *new_table;
    680   DBusHashIter iter;
    681 
    682   new_table = bus_selinux_id_table_new ();
    683   if (!new_table)
    684     return FALSE;
    685 
    686   _dbus_hash_iter_init (table, &iter);
    687   while (_dbus_hash_iter_next (&iter))
    688     {
    689       const char *service = _dbus_hash_iter_get_string_key (&iter);
    690       const char *context = _dbus_hash_iter_get_value (&iter);
    691 
    692       if (!bus_selinux_id_table_insert (new_table,
    693 					service,
    694 					context))
    695 	return FALSE;
    696     }
    697 
    698   if (registry->service_sid_table)
    699     _dbus_hash_table_unref (registry->service_sid_table);
    700   registry->service_sid_table = new_table;
    701   return TRUE;
    702 }
    703 
    704 static void
    705 bus_service_unlink_owner (BusService      *service,
    706                           BusOwner        *owner)
    707 {
    708   _dbus_list_remove_last (&service->owners, owner);
    709   bus_owner_unref (owner);
    710 }
    711 
    712 static void
    713 bus_service_unlink (BusService *service)
    714 {
    715   _dbus_assert (service->owners == NULL);
    716 
    717   /* the service may not be in the hash, if
    718    * the failure causing transaction cancel
    719    * was in the right place, but that's OK
    720    */
    721   _dbus_hash_table_remove_string (service->registry->service_hash,
    722                                   service->name);
    723 
    724   bus_service_unref (service);
    725 }
    726 
    727 static void
    728 bus_service_relink (BusService           *service,
    729                     DBusPreallocatedHash *preallocated)
    730 {
    731   _dbus_assert (service->owners == NULL);
    732   _dbus_assert (preallocated != NULL);
    733 
    734   _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
    735                                                preallocated,
    736                                                service->name,
    737                                                service);
    738 
    739   bus_service_ref (service);
    740 }
    741 
    742 /**
    743  * Data used to represent an ownership cancellation in
    744  * a bus transaction.
    745  */
    746 typedef struct
    747 {
    748   BusOwner *owner;            /**< the owner */
    749   BusService *service;        /**< service to cancel ownership of */
    750 } OwnershipCancelData;
    751 
    752 static void
    753 cancel_ownership (void *data)
    754 {
    755   OwnershipCancelData *d = data;
    756 
    757   /* We don't need to send messages notifying of these
    758    * changes, since we're reverting something that was
    759    * cancelled (effectively never really happened)
    760    */
    761   bus_service_unlink_owner (d->service, d->owner);
    762 
    763   if (d->service->owners == NULL)
    764     bus_service_unlink (d->service);
    765 }
    766 
    767 static void
    768 free_ownership_cancel_data (void *data)
    769 {
    770   OwnershipCancelData *d = data;
    771 
    772   dbus_connection_unref (d->owner->conn);
    773   bus_owner_unref (d->owner);
    774   bus_service_unref (d->service);
    775 
    776   dbus_free (d);
    777 }
    778 
    779 static dbus_bool_t
    780 add_cancel_ownership_to_transaction (BusTransaction *transaction,
    781                                      BusService     *service,
    782                                      BusOwner       *owner)
    783 {
    784   OwnershipCancelData *d;
    785 
    786   d = dbus_new (OwnershipCancelData, 1);
    787   if (d == NULL)
    788     return FALSE;
    789 
    790   d->service = service;
    791   d->owner = owner;
    792 
    793   if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
    794                                         free_ownership_cancel_data))
    795     {
    796       dbus_free (d);
    797       return FALSE;
    798     }
    799 
    800   bus_service_ref (d->service);
    801   bus_owner_ref (owner);
    802   dbus_connection_ref (d->owner->conn);
    803 
    804   return TRUE;
    805 }
    806 
    807 /* this function is self-cancelling if you cancel the transaction */
    808 dbus_bool_t
    809 bus_service_add_owner (BusService     *service,
    810                        DBusConnection *connection,
    811                        dbus_uint32_t  flags,
    812                        BusTransaction *transaction,
    813                        DBusError      *error)
    814 {
    815   BusOwner *bus_owner;
    816   DBusList *bus_owner_link;
    817 
    818   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    819 
    820  /* Send service acquired message first, OOM will result
    821   * in cancelling the transaction
    822   */
    823   if (service->owners == NULL)
    824     {
    825       if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
    826         return FALSE;
    827     }
    828 
    829   bus_owner_link = _bus_service_find_owner_link (service, connection);
    830 
    831   if (bus_owner_link == NULL)
    832     {
    833       bus_owner = bus_owner_new (service, connection, flags);
    834       if (bus_owner == NULL)
    835         {
    836           BUS_SET_OOM (error);
    837           return FALSE;
    838         }
    839 
    840       bus_owner_set_flags (bus_owner, flags);
    841       if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
    842         {
    843           if (!_dbus_list_append (&service->owners,
    844                                   bus_owner))
    845             {
    846               bus_owner_unref (bus_owner);
    847               BUS_SET_OOM (error);
    848               return FALSE;
    849             }
    850         }
    851       else
    852         {
    853           if (!_dbus_list_insert_after (&service->owners,
    854                                          _dbus_list_get_first_link (&service->owners),
    855                                          bus_owner))
    856             {
    857               bus_owner_unref (bus_owner);
    858               BUS_SET_OOM (error);
    859               return FALSE;
    860             }
    861         }
    862     }
    863   else
    864     {
    865       /* Update the link since we are already in the queue
    866        * No need for operations that can produce OOM
    867        */
    868 
    869       bus_owner = (BusOwner *) bus_owner_link->data;
    870       if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
    871         {
    872 	  DBusList *link;
    873           _dbus_list_unlink (&service->owners, bus_owner_link);
    874 	  link = _dbus_list_get_first_link (&service->owners);
    875 	  _dbus_assert (link != NULL);
    876 
    877           _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
    878         }
    879 
    880       bus_owner_set_flags (bus_owner, flags);
    881       return TRUE;
    882     }
    883 
    884   if (!add_cancel_ownership_to_transaction (transaction,
    885                                             service,
    886                                             bus_owner))
    887     {
    888       bus_service_unlink_owner (service, bus_owner);
    889       BUS_SET_OOM (error);
    890       return FALSE;
    891     }
    892 
    893   return TRUE;
    894 }
    895 
    896 typedef struct
    897 {
    898   BusOwner       *owner;
    899   BusService     *service;
    900   BusOwner       *before_owner; /* restore to position before this connection in owners list */
    901   DBusList       *owner_link;
    902   DBusList       *service_link;
    903   DBusPreallocatedHash *hash_entry;
    904 } OwnershipRestoreData;
    905 
    906 static void
    907 restore_ownership (void *data)
    908 {
    909   OwnershipRestoreData *d = data;
    910   DBusList *link;
    911 
    912   _dbus_assert (d->service_link != NULL);
    913   _dbus_assert (d->owner_link != NULL);
    914 
    915   if (d->service->owners == NULL)
    916     {
    917       _dbus_assert (d->hash_entry != NULL);
    918       bus_service_relink (d->service, d->hash_entry);
    919     }
    920   else
    921     {
    922       _dbus_assert (d->hash_entry == NULL);
    923     }
    924 
    925   /* We don't need to send messages notifying of these
    926    * changes, since we're reverting something that was
    927    * cancelled (effectively never really happened)
    928    */
    929   link = _dbus_list_get_first_link (&d->service->owners);
    930   while (link != NULL)
    931     {
    932       if (link->data == d->before_owner)
    933         break;
    934 
    935       link = _dbus_list_get_next_link (&d->service->owners, link);
    936     }
    937 
    938   _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
    939 
    940   /* Note that removing then restoring this changes the order in which
    941    * ServiceDeleted messages are sent on destruction of the
    942    * connection.  This should be OK as the only guarantee there is
    943    * that the base service is destroyed last, and we never even
    944    * tentatively remove the base service.
    945    */
    946   bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
    947 
    948   d->hash_entry = NULL;
    949   d->service_link = NULL;
    950   d->owner_link = NULL;
    951 }
    952 
    953 static void
    954 free_ownership_restore_data (void *data)
    955 {
    956   OwnershipRestoreData *d = data;
    957 
    958   if (d->service_link)
    959     _dbus_list_free_link (d->service_link);
    960   if (d->owner_link)
    961     _dbus_list_free_link (d->owner_link);
    962   if (d->hash_entry)
    963     _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
    964                                               d->hash_entry);
    965 
    966   dbus_connection_unref (d->owner->conn);
    967   bus_owner_unref (d->owner);
    968   bus_service_unref (d->service);
    969 
    970   dbus_free (d);
    971 }
    972 
    973 static dbus_bool_t
    974 add_restore_ownership_to_transaction (BusTransaction *transaction,
    975                                       BusService     *service,
    976                                       BusOwner       *owner)
    977 {
    978   OwnershipRestoreData *d;
    979   DBusList *link;
    980 
    981   d = dbus_new (OwnershipRestoreData, 1);
    982   if (d == NULL)
    983     return FALSE;
    984 
    985   d->service = service;
    986   d->owner = owner;
    987   d->service_link = _dbus_list_alloc_link (service);
    988   d->owner_link = _dbus_list_alloc_link (owner);
    989   d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
    990 
    991   bus_service_ref (d->service);
    992   bus_owner_ref (d->owner);
    993   dbus_connection_ref (d->owner->conn);
    994 
    995   d->before_owner = NULL;
    996   link = _dbus_list_get_first_link (&service->owners);
    997   while (link != NULL)
    998     {
    999       if (link->data == owner)
   1000         {
   1001           link = _dbus_list_get_next_link (&service->owners, link);
   1002 
   1003           if (link)
   1004             d->before_owner = link->data;
   1005 
   1006           break;
   1007         }
   1008 
   1009       link = _dbus_list_get_next_link (&service->owners, link);
   1010     }
   1011 
   1012   if (d->service_link == NULL ||
   1013       d->owner_link == NULL ||
   1014       d->hash_entry == NULL ||
   1015       !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
   1016                                         free_ownership_restore_data))
   1017     {
   1018       free_ownership_restore_data (d);
   1019       return FALSE;
   1020     }
   1021 
   1022   return TRUE;
   1023 }
   1024 
   1025 dbus_bool_t
   1026 bus_service_swap_owner (BusService     *service,
   1027                         DBusConnection *connection,
   1028                         BusTransaction *transaction,
   1029                         DBusError      *error)
   1030 {
   1031   DBusList *swap_link;
   1032   BusOwner *primary_owner;
   1033 
   1034   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   1035 
   1036   /* We send out notifications before we do any work we
   1037    * might have to undo if the notification-sending failed
   1038    */
   1039 
   1040   /* Send service lost message */
   1041   primary_owner = bus_service_get_primary_owner (service);
   1042   if (primary_owner == NULL || primary_owner->conn != connection)
   1043     _dbus_assert_not_reached ("Tried to swap a non primary owner");
   1044 
   1045 
   1046   if (!bus_driver_send_service_lost (connection, service->name,
   1047                                      transaction, error))
   1048     return FALSE;
   1049 
   1050   if (service->owners == NULL)
   1051     {
   1052       _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
   1053     }
   1054   else if (_dbus_list_length_is_one (&service->owners))
   1055     {
   1056       _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
   1057     }
   1058   else
   1059     {
   1060       DBusList *link;
   1061       BusOwner *new_owner;
   1062       DBusConnection *new_owner_conn;
   1063       link = _dbus_list_get_first_link (&service->owners);
   1064       _dbus_assert (link != NULL);
   1065       link = _dbus_list_get_next_link (&service->owners, link);
   1066       _dbus_assert (link != NULL);
   1067 
   1068       new_owner = (BusOwner *)link->data;
   1069       new_owner_conn = new_owner->conn;
   1070 
   1071       if (!bus_driver_send_service_owner_changed (service->name,
   1072  						  bus_connection_get_name (connection),
   1073  						  bus_connection_get_name (new_owner_conn),
   1074  						  transaction, error))
   1075         return FALSE;
   1076 
   1077       /* This will be our new owner */
   1078       if (!bus_driver_send_service_acquired (new_owner_conn,
   1079                                              service->name,
   1080                                              transaction,
   1081                                              error))
   1082         return FALSE;
   1083     }
   1084 
   1085   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
   1086     {
   1087       BUS_SET_OOM (error);
   1088       return FALSE;
   1089     }
   1090 
   1091   /* unlink the primary and make it the second link */
   1092   swap_link = _dbus_list_get_first_link (&service->owners);
   1093   _dbus_list_unlink (&service->owners, swap_link);
   1094 
   1095   _dbus_list_insert_after_link (&service->owners,
   1096                                 _dbus_list_get_first_link (&service->owners),
   1097 				swap_link);
   1098 
   1099   return TRUE;
   1100 }
   1101 
   1102 /* this function is self-cancelling if you cancel the transaction */
   1103 dbus_bool_t
   1104 bus_service_remove_owner (BusService     *service,
   1105                           DBusConnection *connection,
   1106                           BusTransaction *transaction,
   1107                           DBusError      *error)
   1108 {
   1109   BusOwner *primary_owner;
   1110 
   1111   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   1112 
   1113   /* We send out notifications before we do any work we
   1114    * might have to undo if the notification-sending failed
   1115    */
   1116 
   1117   /* Send service lost message */
   1118   primary_owner = bus_service_get_primary_owner (service);
   1119   if (primary_owner != NULL && primary_owner->conn == connection)
   1120     {
   1121       if (!bus_driver_send_service_lost (connection, service->name,
   1122                                          transaction, error))
   1123         return FALSE;
   1124     }
   1125   else
   1126     {
   1127       /* if we are not the primary owner then just remove us from the queue */
   1128       DBusList *link;
   1129       BusOwner *temp_owner;
   1130 
   1131       link = _bus_service_find_owner_link (service, connection);
   1132       _dbus_list_unlink (&service->owners, link);
   1133       temp_owner = (BusOwner *)link->data;
   1134       bus_owner_unref (temp_owner);
   1135       _dbus_list_free_link (link);
   1136 
   1137       return TRUE;
   1138     }
   1139 
   1140   if (service->owners == NULL)
   1141     {
   1142       _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
   1143     }
   1144   else if (_dbus_list_length_is_one (&service->owners))
   1145     {
   1146       if (!bus_driver_send_service_owner_changed (service->name,
   1147  						  bus_connection_get_name (connection),
   1148  						  NULL,
   1149  						  transaction, error))
   1150         return FALSE;
   1151     }
   1152   else
   1153     {
   1154       DBusList *link;
   1155       BusOwner *new_owner;
   1156       DBusConnection *new_owner_conn;
   1157       link = _dbus_list_get_first_link (&service->owners);
   1158       _dbus_assert (link != NULL);
   1159       link = _dbus_list_get_next_link (&service->owners, link);
   1160       _dbus_assert (link != NULL);
   1161 
   1162       new_owner = (BusOwner *)link->data;
   1163       new_owner_conn = new_owner->conn;
   1164 
   1165       if (!bus_driver_send_service_owner_changed (service->name,
   1166  						  bus_connection_get_name (connection),
   1167  						  bus_connection_get_name (new_owner_conn),
   1168  						  transaction, error))
   1169         return FALSE;
   1170 
   1171       /* This will be our new owner */
   1172       if (!bus_driver_send_service_acquired (new_owner_conn,
   1173                                              service->name,
   1174                                              transaction,
   1175                                              error))
   1176         return FALSE;
   1177     }
   1178 
   1179   if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
   1180     {
   1181       BUS_SET_OOM (error);
   1182       return FALSE;
   1183     }
   1184 
   1185   bus_service_unlink_owner (service, primary_owner);
   1186 
   1187   if (service->owners == NULL)
   1188     bus_service_unlink (service);
   1189 
   1190   return TRUE;
   1191 }
   1192 
   1193 BusService *
   1194 bus_service_ref (BusService *service)
   1195 {
   1196   _dbus_assert (service->refcount > 0);
   1197 
   1198   service->refcount += 1;
   1199 
   1200   return service;
   1201 }
   1202 
   1203 void
   1204 bus_service_unref (BusService *service)
   1205 {
   1206   _dbus_assert (service->refcount > 0);
   1207 
   1208   service->refcount -= 1;
   1209 
   1210   if (service->refcount == 0)
   1211     {
   1212       _dbus_assert (service->owners == NULL);
   1213 
   1214       dbus_free (service->name);
   1215       _dbus_mem_pool_dealloc (service->registry->service_pool, service);
   1216     }
   1217 }
   1218 
   1219 DBusConnection *
   1220 bus_service_get_primary_owners_connection (BusService *service)
   1221 {
   1222   BusOwner *owner;
   1223 
   1224   owner = bus_service_get_primary_owner (service);
   1225 
   1226   if (owner != NULL)
   1227     return owner->conn;
   1228   else
   1229     return NULL;
   1230 }
   1231 
   1232 BusOwner*
   1233 bus_service_get_primary_owner (BusService *service)
   1234 {
   1235   return _dbus_list_get_first (&service->owners);
   1236 }
   1237 
   1238 const char*
   1239 bus_service_get_name (BusService *service)
   1240 {
   1241   return service->name;
   1242 }
   1243 
   1244 dbus_bool_t
   1245 bus_service_get_allow_replacement (BusService *service)
   1246 {
   1247   BusOwner *owner;
   1248   DBusList *link;
   1249 
   1250   _dbus_assert (service->owners != NULL);
   1251 
   1252   link = _dbus_list_get_first_link (&service->owners);
   1253   owner = (BusOwner *) link->data;
   1254 
   1255   return owner->allow_replacement;
   1256 }
   1257 
   1258 dbus_bool_t
   1259 bus_service_has_owner (BusService     *service,
   1260 		       DBusConnection *connection)
   1261 {
   1262   DBusList *link;
   1263 
   1264   link = _bus_service_find_owner_link (service, connection);
   1265 
   1266   if (link == NULL)
   1267     return FALSE;
   1268   else
   1269     return TRUE;
   1270 }
   1271 
   1272 dbus_bool_t
   1273 bus_service_list_queued_owners (BusService *service,
   1274                                 DBusList  **return_list,
   1275                                 DBusError  *error)
   1276 {
   1277   DBusList *link;
   1278 
   1279   _dbus_assert (*return_list == NULL);
   1280 
   1281   link = _dbus_list_get_first_link (&service->owners);
   1282   _dbus_assert (link != NULL);
   1283 
   1284   while (link != NULL)
   1285     {
   1286       BusOwner *owner;
   1287       const char *uname;
   1288 
   1289       owner = (BusOwner *) link->data;
   1290       uname = bus_connection_get_name (owner->conn);
   1291 
   1292       if (!_dbus_list_append (return_list, (char *)uname))
   1293         goto oom;
   1294 
   1295       link = _dbus_list_get_next_link (&service->owners, link);
   1296     }
   1297 
   1298   return TRUE;
   1299 
   1300  oom:
   1301   _dbus_list_clear (return_list);
   1302   BUS_SET_OOM (error);
   1303   return FALSE;
   1304 }
   1305