4f37bc2ab6d8c136064b53a91b804635528d358d
[platform/upstream/dbus.git] / bus / kdbus-d.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* kdbus-d.c  kdbus related daemon functions
3  *
4  * Copyright (C) 2013  Samsung Electronics
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version and under the terms of the GNU
12  * Lesser General Public License as published by the
13  * Free Software Foundation; either version 2.1 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  *
25  */
26
27 #include <dbus/dbus-connection-internal.h>
28 #include "kdbus-d.h"
29 #include <dbus/kdbus.h>
30 #include <dbus/dbus-bus.h>
31 #include "dispatch.h"
32 #include <dbus/kdbus-common.h>
33 #include <dbus/dbus-transport.h>
34 #include <dbus/dbus-transport-kdbus.h>
35 #include "connection.h"
36 #include "activation.h"
37 #include "services.h"
38
39 #include <utils.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <errno.h>
45
46 /*
47  * Converts string with unique name into __u64 id number. If the name is not unique, sets error.
48  */
49 __u64 sender_name_to_id(const char* name, DBusError* error)
50 {
51         __u64 sender_id = 0;
52
53         if(!strncmp(name, ":1.", 3)) /*if name is unique name it must be converted to unique id*/
54                 sender_id = strtoull(&name[3], NULL, 10);
55         else
56                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Could not convert sender of the message into kdbus unique id");
57
58         return sender_id;
59 }
60
61 /*
62  * Creates kdbus bus of given type.
63  */
64 char* make_kdbus_bus(DBusBusType type, DBusError *error)
65 {
66     struct {
67         struct kdbus_cmd_bus_make head;
68         uint64_t n_size;
69         uint64_t n_type;
70         char name[64];
71     } __attribute__ ((__aligned__(8))) bus_make;
72
73     int fdc, ret;
74     char *bus;
75
76     _dbus_verbose("Opening /dev/kdbus/control\n");
77     fdc = open("/dev/kdbus/control", O_RDWR|O_CLOEXEC);
78     if (fdc < 0)
79     {
80         _dbus_verbose("--- error %d (%m)\n", fdc);
81         dbus_set_error(error, DBUS_ERROR_FAILED, "Opening /dev/kdbus/control failed: %d (%m)", fdc);
82         return NULL;
83     }
84
85     memset(&bus_make, 0, sizeof(bus_make));
86     bus_make.head.bloom_size = 64;
87     bus_make.head.flags = KDBUS_MAKE_ACCESS_WORLD;
88
89     if(type == DBUS_BUS_SYSTEM)
90         snprintf(bus_make.name, sizeof(bus_make.name), "%u-kdbus-%s", getuid(), "system");
91     else if(type == DBUS_BUS_SESSION)
92         snprintf(bus_make.name, sizeof(bus_make.name), "%u-kdbus", getuid());
93     else
94         snprintf(bus_make.name, sizeof(bus_make.name), "%u-kdbus-%u", getuid(), getpid());
95
96     bus_make.n_type = KDBUS_MAKE_NAME;
97     bus_make.n_size = KDBUS_PART_HEADER_SIZE + strlen(bus_make.name) + 1;
98     bus_make.head.size = sizeof(struct kdbus_cmd_bus_make) + bus_make.n_size;
99
100     _dbus_verbose("Creating bus '%s'\n", bus_make.name);
101     ret = ioctl(fdc, KDBUS_CMD_BUS_MAKE, &bus_make);
102     if (ret)
103     {
104         _dbus_verbose("--- error %d (%m)\n", ret);
105         dbus_set_error(error, DBUS_ERROR_FAILED, "Creating bus '%s' failed: %d (%m)", bus_make.name, fdc);
106         return NULL;
107     }
108
109     if (asprintf(&bus, "kdbus:path=/dev/kdbus/%s/bus", bus_make.name) < 0)
110     {
111         BUS_SET_OOM (error);
112         return NULL;
113     }
114
115     _dbus_verbose("Return value '%s'\n", bus);
116         return bus;
117 }
118
119 /*
120  * Minimal server init needed by context to go further.
121  */
122 DBusServer* empty_server_init(char* address)
123 {
124         return dbus_server_init_mini(address);
125 }
126
127 /*
128  * Connects daemon to bus created by him and adds matches for "system" broadcasts.
129  * Do not requests org.freedesktop.DBus name, because it's to early
130  * (some structures of BusContext are not ready yet).
131  */
132 DBusConnection* daemon_as_client(DBusBusType type, char* address, DBusError *error)
133 {
134         DBusConnection* connection;
135
136         dbus_bus_set_bus_connection_address(type, address);
137
138         connection = dbus_bus_get_private(type, error);  /*todo possibly could be optimised by using lower functions*/
139         if(connection == NULL)
140                 return NULL;
141
142         if(!add_match_kdbus (dbus_connection_get_transport(connection), 1, "member='IdRemoved'"))
143     {
144           dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for id:1, %s", _dbus_strerror_from_errno ());
145           goto failed;
146     }
147     if(!add_match_kdbus (dbus_connection_get_transport(connection), 1, "member='NameChanged'"))
148     {
149           dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for id:1, %s", _dbus_strerror_from_errno ());
150           goto failed;
151     }
152     if(!add_match_kdbus (dbus_connection_get_transport(connection), 1, "member='NameLost'"))
153     {
154           dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for id:1, %s", _dbus_strerror_from_errno ());
155           goto failed;
156     }
157     if(!add_match_kdbus (dbus_connection_get_transport(connection), 1, "member='NameAcquired'"))
158     {
159           dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for id:1, %s", _dbus_strerror_from_errno ());
160           goto failed;
161     }
162
163         if(dbus_error_is_set(error))
164         {
165 failed:
166                 _dbus_connection_close_possibly_shared (connection);
167                 dbus_connection_unref (connection);
168                 connection = NULL;
169         }
170         else
171                 _dbus_verbose ("Daemon connected as kdbus client.\n");
172
173         return connection;
174 }
175
176 /*
177  * Asks bus for org.freedesktop.DBus well-known name.
178  */
179 dbus_bool_t register_daemon_name(DBusConnection* connection)
180 {
181     DBusString daemon_name;
182     dbus_bool_t retval = FALSE;
183     BusTransaction *transaction;
184
185     _dbus_string_init_const(&daemon_name, DBUS_SERVICE_DBUS);
186     if(!register_kdbus_policy(DBUS_SERVICE_DBUS, dbus_connection_get_transport(connection), geteuid()))
187       return FALSE;
188
189     if(kdbus_request_name(connection, &daemon_name, 0, 0) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
190        return FALSE;
191
192     transaction = bus_transaction_new (bus_connection_get_context(connection));
193     if (transaction == NULL)
194     {
195         kdbus_release_name(connection, &daemon_name, 0);
196         goto out;
197     }
198
199     if(!bus_registry_ensure (bus_connection_get_registry (connection), &daemon_name, connection, 0, transaction, NULL))
200     {
201         kdbus_release_name(connection, &daemon_name, 0);
202         goto out;
203     }
204
205     retval = TRUE;
206
207 out:
208         bus_transaction_cancel_and_free(transaction);
209     return retval;
210 }
211
212 dbus_uint32_t kdbus_request_name(DBusConnection* connection, const DBusString *service_name, dbus_uint32_t flags, __u64 sender_id)
213 {
214         int fd;
215
216         _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
217
218         return request_kdbus_name(fd, _dbus_string_get_const_data(service_name), flags, sender_id);
219 }
220
221 dbus_uint32_t kdbus_release_name(DBusConnection* connection, const DBusString *service_name, __u64 sender_id)
222 {
223         int fd;
224
225         _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
226
227         return release_kdbus_name(fd, _dbus_string_get_const_data(service_name), sender_id);
228 }
229
230 /*
231  * Asks kdbus for well-known names registered on the bus
232  */
233 dbus_bool_t kdbus_list_services (DBusConnection* connection, char ***listp, int *array_len)
234 {
235         int fd;
236         struct kdbus_cmd_names* pCmd;
237         __u64 cmd_size;
238         dbus_bool_t ret_val = FALSE;
239         char** list;
240         int list_len = 0;
241         int i = 0;
242         int j;
243
244         cmd_size = sizeof(struct kdbus_cmd_names) + KDBUS_ITEM_SIZE(1);
245         pCmd = malloc(cmd_size);
246         if(pCmd == NULL)
247                 goto out;
248         pCmd->size = cmd_size;
249
250         _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
251
252 again:
253         cmd_size = 0;
254         if(ioctl(fd, KDBUS_CMD_NAME_LIST, pCmd))
255         {
256                 if(errno == EINTR)
257                         goto again;
258                 if(errno == ENOBUFS)                    //buffer to small to put all names into it
259                         cmd_size = pCmd->size;          //here kernel tells how much memory it needs
260                 else
261                 {
262                         _dbus_verbose("kdbus error asking for name list: err %d (%m)\n",errno);
263                         goto out;
264                 }
265         }
266         if(cmd_size)  //kernel needs more memory
267         {
268                 pCmd = realloc(pCmd, cmd_size);  //prepare memory
269                 if(pCmd == NULL)
270                         return FALSE;
271                 goto again;                                             //and try again
272         }
273         else
274         {
275                 struct kdbus_cmd_name* pCmd_name;
276
277                 for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
278                         list_len++;
279
280                 list = malloc(sizeof(char*) * (list_len + 1));
281                 if(list == NULL)
282                         goto out;
283
284                 for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
285                 {
286                         list[i] = strdup(pCmd_name->name);
287                         if(list[i] == NULL)
288                         {
289                                 for(j=0; j<i; j++)
290                                         free(list[j]);
291                                 free(list);
292                                 goto out;
293                         }
294                         _dbus_verbose ("Name %d: %s\n", i, list[i]);
295                         ++i;
296                 }
297                 list[i] = NULL;
298         }
299
300         *array_len = list_len;
301         *listp = list;
302         ret_val = TRUE;
303
304 out:
305         if(pCmd)
306                 free(pCmd);
307         return ret_val;
308 }
309
310 /*
311  *  Register match rule in kdbus on behalf of sender of the message
312  */
313 dbus_bool_t kdbus_add_match_rule (DBusConnection* connection, DBusMessage* message, const char* text, DBusError* error)
314 {
315         __u64 sender_id;
316
317         sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
318         if(dbus_error_is_set(error))
319                 return FALSE;
320
321         if(!add_match_kdbus (dbus_connection_get_transport(connection), sender_id, text))
322         {
323               dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match for id:%d, %s",
324                               sender_id, _dbus_strerror_from_errno ());
325               return FALSE;
326         }
327
328         return TRUE;
329 }
330
331 /*
332  *  Removes match rule in kdbus on behalf of sender of the message
333  */
334 dbus_bool_t kdbus_remove_match (DBusConnection* connection, DBusMessage* message, DBusError* error)
335 {
336         __u64 sender_id;
337
338         sender_id = sender_name_to_id(dbus_message_get_sender(message), error);
339         if(dbus_error_is_set(error))
340                 return FALSE;
341
342         if(!remove_match_kdbus (dbus_connection_get_transport(connection), sender_id))
343         {
344               dbus_set_error (error, _dbus_error_from_errno (errno), "Could not remove match rules for id:%d", sender_id);
345               return FALSE;
346         }
347
348         return TRUE;
349 }
350
351 int kdbus_get_name_owner(DBusConnection* connection, const char* name, char* owner)
352 {
353   int ret;
354   struct nameInfo info;
355
356   ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
357   if(ret == 0) //unique id of the name
358   {
359     sprintf(owner, ":1.%llu", (unsigned long long int)info.uniqueId);
360     _dbus_verbose("Unique name discovered:%s\n", owner);
361   }
362   else if(ret != -ENOENT)
363     _dbus_verbose("kdbus error sending name query: err %d (%m)\n", errno);
364
365   return ret;
366 }
367
368 /*
369  *  Asks kdbus for uid of the owner of the name given in the message
370  */
371 dbus_bool_t kdbus_get_unix_user(DBusConnection* connection, const char* name, unsigned long* uid, DBusError* error)
372 {
373   struct nameInfo info;
374   int inter_ret;
375   dbus_bool_t ret = FALSE;
376
377   inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
378   if(inter_ret == 0) //name found
379   {
380     _dbus_verbose("User id:%llu\n", (unsigned long long) info.userId);
381     *uid = info.userId;
382     return TRUE;
383   }
384   else if(inter_ret == -ENOENT)  //name has no owner
385     {
386       _dbus_verbose ("Name %s has no owner.\n", name);
387       dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get UID of name '%s': no such name", name);
388     }
389
390   else
391   {
392     _dbus_verbose("kdbus error determining UID: err %d (%m)\n", errno);
393     dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine UID for '%s'", name);
394   }
395
396   return ret;
397 }
398
399 /*
400  *  Asks kdbus for pid of the owner of the name given in the message
401  */
402 dbus_bool_t kdbus_get_connection_unix_process_id(DBusConnection* connection, const char* name, unsigned long* pid, DBusError* error)
403 {
404         struct nameInfo info;
405         int inter_ret;
406         dbus_bool_t ret = FALSE;
407
408         inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
409         if(inter_ret == 0) //name found
410         {
411                 _dbus_verbose("Process id:%llu\n", (unsigned long long) info.processId);
412                 *pid = info.processId;
413                 return TRUE;
414         }
415         else if(inter_ret == -ENOENT)  //name has no owner
416                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get PID of name '%s': no such name", name);
417         else
418         {
419                 _dbus_verbose("kdbus error determining PID: err %d (%m)\n", errno);
420                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine PID for '%s'", name);
421         }
422
423         return ret;
424 }
425
426 /*
427  *  Asks kdbus for selinux_security_context of the owner of the name given in the message
428  */
429 dbus_bool_t kdbus_get_connection_unix_selinux_security_context(DBusConnection* connection, DBusMessage* message, DBusMessage* reply, DBusError* error)
430 {
431         char* name = NULL;
432         struct nameInfo info;
433         int inter_ret;
434         dbus_bool_t ret = FALSE;
435
436         dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
437         inter_ret = kdbus_NameQuery(name, dbus_connection_get_transport(connection), &info);
438         if(inter_ret == -ENOENT)  //name has no owner
439                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get security context of name '%s': no such name", name);
440         else if(inter_ret < 0)
441         {
442                 _dbus_verbose("kdbus error determining security context: err %d (%m)\n", errno);
443                 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not determine security context for '%s'", name);
444         }
445         else
446         {
447                 if (!dbus_message_append_args (reply, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &info.sec_label, info.sec_label_len, DBUS_TYPE_INVALID))
448                 {
449                       _DBUS_SET_OOM (error);
450                       return FALSE;
451                 }
452                 ret = TRUE;
453         }
454
455         return ret;
456 }
457
458 /**
459  * Gets the UNIX user ID of the connection from kdbus, if known. Returns #TRUE if
460  * the uid is filled in.  Always returns #FALSE on non-UNIX platforms
461  * for now., though in theory someone could hook Windows to NIS or
462  * something.  Always returns #FALSE prior to authenticating the
463  * connection.
464  *
465  * The UID of is only read by bus daemon from kdbus. You can not
466  * call this function from client side of the connection.
467  *
468  * You can ask the bus to tell you the UID of another connection though
469  * if you like; this is done with dbus_bus_get_unix_user().
470  *
471  * @param connection the connection
472  * @param uid return location for the user ID
473  * @returns #TRUE if uid is filled in with a valid user ID
474  */
475 dbus_bool_t
476 dbus_connection_get_unix_user (DBusConnection *connection,
477                                unsigned long  *uid)
478 {
479   _dbus_return_val_if_fail (connection != NULL, FALSE);
480   _dbus_return_val_if_fail (uid != NULL, FALSE);
481
482   return kdbus_get_unix_user(connection, bus_connection_get_name(connection), uid, NULL);
483 }
484
485 /**
486  * Gets the process ID of the connection if any.
487  * Returns #TRUE if the pid is filled in.
488  *
489  * @param connection the connection
490  * @param pid return location for the process ID
491  * @returns #TRUE if uid is filled in with a valid process ID
492  */
493 dbus_bool_t
494 dbus_connection_get_unix_process_id (DBusConnection *connection,
495              unsigned long  *pid)
496 {
497   _dbus_return_val_if_fail (connection != NULL, FALSE);
498   _dbus_return_val_if_fail (pid != NULL, FALSE);
499
500   return kdbus_get_connection_unix_process_id(connection, bus_connection_get_name(connection), pid, NULL);
501 }
502
503 /*
504  * Create connection structure for given name. It is needed to control starters - activatable services
505  * and for ListQueued method (as long as kdbus is not supporting it). This connections don't have it's own
506  * fd so it is set up on the basis of daemon's transport. Functionality of such connection is limited.
507  */
508 DBusConnection* create_phantom_connection(DBusConnection* connection, const char* name, DBusError* error)
509 {
510     DBusConnection *phantom_connection;
511     DBusString Sname;
512
513     _dbus_string_init_const(&Sname, name);
514
515     phantom_connection = _dbus_connection_new_for_used_transport (dbus_connection_get_transport(connection));
516     if(phantom_connection == NULL)
517         return FALSE;
518     if(!bus_connections_setup_connection(bus_connection_get_connections(connection), phantom_connection))
519     {
520         dbus_connection_unref_phantom(phantom_connection);
521         phantom_connection = NULL;
522         dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired", name);
523         goto out;
524     }
525     if(!bus_connection_complete(phantom_connection, &Sname, error))
526     {
527         bus_connection_disconnected(phantom_connection);
528         phantom_connection = NULL;
529         goto out;
530     }
531
532     _dbus_verbose ("Created phantom connection for %s\n", bus_connection_get_name(phantom_connection));
533
534 out:
535     return phantom_connection;
536 }
537
538 /*
539  * Registers activatable services as kdbus starters.
540  */
541 dbus_bool_t register_kdbus_starters(DBusConnection* connection)
542 {
543     int i,j, len;
544     char **services;
545     dbus_bool_t retval = FALSE;
546     int fd;
547     BusTransaction *transaction;
548     DBusString name;
549     DBusTransport* transport;
550     unsigned long int euid;
551
552     transaction = bus_transaction_new (bus_connection_get_context(connection));
553     if (transaction == NULL)
554         return FALSE;
555
556     if (!bus_activation_list_services (bus_connection_get_activation (connection), &services, &len))
557         return FALSE;
558
559     transport = dbus_connection_get_transport(connection);
560     euid = geteuid();
561
562     if(!_dbus_transport_get_socket_fd (transport, &fd))
563       return FALSE;
564
565     _dbus_string_init(&name);
566
567     for(i=0; i<len; i++)
568     {
569         if(!register_kdbus_policy(services[i], transport, euid))
570           goto out;
571
572         if (request_kdbus_name(fd, services[i], (DBUS_NAME_FLAG_ALLOW_REPLACEMENT | KDBUS_NAME_STARTER) , 0) < 0)
573             goto out;
574
575         if(!_dbus_string_append(&name, services[i]))
576                 goto out;
577         if(!bus_registry_ensure (bus_connection_get_registry (connection), &name, connection,
578                         (DBUS_NAME_FLAG_ALLOW_REPLACEMENT | KDBUS_NAME_STARTER), transaction, NULL))
579                 goto out;
580         if(!_dbus_string_set_length(&name, 0))
581                 goto out;
582     }
583     retval = TRUE;
584
585 out:
586     if(retval == FALSE)
587     {
588         for(j=0; j<i; j++)
589             release_kdbus_name(fd, services[j], 0);
590     }
591     dbus_free_string_array (services);
592     _dbus_string_free(&name);
593     bus_transaction_cancel_and_free(transaction);
594     return retval;
595 }
596
597 /*
598  * Updates kdbus starters (activatable services) after configuration was reloaded.
599  * It releases all previous starters and registers all new.
600  */
601 dbus_bool_t update_kdbus_starters(DBusConnection* connection)
602 {
603     dbus_bool_t retval = FALSE;
604     DBusList **services_old;
605     DBusList *link;
606     BusService *service = NULL;
607     BusTransaction *transaction;
608     int fd;
609
610     transaction = bus_transaction_new (bus_connection_get_context(connection));
611     if (transaction == NULL)
612         return FALSE;
613
614     if(!_dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd))
615         goto out;
616
617     services_old = bus_connection_get_services_owned(connection);
618     link = _dbus_list_get_first_link(services_old);
619     link = _dbus_list_get_next_link (services_old, link); //skip org.freedesktop.DBus which is not starter
620
621     while (link != NULL)
622     {
623         int ret;
624
625         service = (BusService*) link->data;
626         if(service == NULL)
627             goto out;
628
629         ret = release_kdbus_name(fd, bus_service_get_name(service), 0);
630
631         if (ret == DBUS_RELEASE_NAME_REPLY_RELEASED)
632         {
633             if(!bus_service_remove_owner(service, connection, transaction, NULL))
634                 _dbus_verbose ("Unable to remove\n");
635         }
636         else if(ret < 0)
637             goto out;
638
639         link = _dbus_list_get_next_link (services_old, link);
640     }
641
642     if(!register_kdbus_starters(connection))
643     {
644         _dbus_verbose ("Registering kdbus starters for dbus activatable names failed!\n");
645         goto out;
646     }
647     retval = TRUE;
648
649 out:
650         bus_transaction_cancel_and_free(transaction);
651     return retval;
652 }
653
654 /*
655  * Analyzes system broadcasts about id and name changes.
656  * Basing on this it sends NameAcquired and NameLost signals and clear phantom connections.
657  */
658 void handleNameOwnerChanged(DBusMessage *msg, BusTransaction *transaction, DBusConnection *connection)
659 {
660     const char *name, *old, *new;
661
662     if(!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID))
663     {
664         _dbus_verbose ("Couldn't get args of NameOwnerChanged signal: .\n");//, error.message);
665         return;
666     }
667
668     _dbus_verbose ("Got NameOwnerChanged signal:\nName: %s\nOld: %s\nNew: %s\n", name, old, new);
669
670     if(!strncmp(name, ":1.", 3))/*if it starts from :1. it is unique name - this might be IdRemoved info*/
671     {
672         if(!strcmp(name, old))  //yes it is - someone has disconnected
673         {
674             DBusConnection* conn;
675
676             conn = bus_connections_find_conn_by_name(bus_connection_get_connections(connection), name);
677             if(conn)
678                 bus_connection_disconnected(conn);
679         }
680     }
681     else //it is well-known name
682     {
683         if((*old != 0) && (strcmp(old, ":1.1")))
684         {
685             DBusMessage *message;
686
687             if(bus_connections_find_conn_by_name(bus_connection_get_connections(connection), old) == NULL)
688                 goto next;
689
690             _dbus_verbose ("Owner '%s' lost name '%s'. Sending NameLost.\n", old, name);
691
692             message = dbus_message_new_signal (DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameLost");
693             if (message == NULL)
694                 goto next;
695
696             if (!dbus_message_set_destination (message, old) || !dbus_message_append_args (message,
697                                                                  DBUS_TYPE_STRING, &name,
698                                                                  DBUS_TYPE_INVALID))
699             {
700                 dbus_message_unref (message);
701                 goto next;
702             }
703
704             bus_transaction_send_from_driver (transaction, connection, message);
705             dbus_message_unref (message);
706         }
707     next:
708         if((*new != 0) && (strcmp(new, ":1.1")))
709         {
710             DBusMessage *message;
711
712             _dbus_verbose ("Owner '%s' acquired name '%s'. Sending NameAcquired.\n", new, name);
713
714             message = dbus_message_new_signal (DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameAcquired");
715             if (message == NULL)
716                 return;
717
718             if (!dbus_message_set_destination (message, new) || !dbus_message_append_args (message,
719                                                                  DBUS_TYPE_STRING, &name,
720                                                                  DBUS_TYPE_INVALID))
721             {
722                 dbus_message_unref (message);
723                 return;
724             }
725
726             bus_transaction_send_from_driver (transaction, connection, message);
727             dbus_message_unref (message);
728         }
729     }
730 }