1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport-kdbus.c kdbus subclasses of DBusTransport
4 * Copyright (C) 2002, 2003, 2004, 2006 Red Hat Inc
5 * Copyright (C) 2013 Samsung Electronics
7 * Licensed under the Academic Free License version 2.1
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 and under the terms of the GNU
13 * Lesser General Public License as published by the
14 * Free Software Foundation; either version 2.1 of the License, or (at
15 * your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "dbus-transport.h"
29 #include "dbus-transport-kdbus.h"
30 #include "dbus-transport-protected.h"
31 #include "dbus-connection-internal.h"
32 #include "dbus-marshal-gvariant.h"
33 #include "dbus-marshal-validate.h"
34 #include "dbus-asv-util.h"
35 #include <linux/kdbus.h>
36 #include "dbus-watch.h"
37 #include "dbus-errors.h"
39 #include "kdbus-common.h"
40 #include "dbus-protocol-gvariant.h"
41 #include <linux/types.h>
49 #include <sys/syscall.h>
52 #include <dbuspolicy/libdbuspolicy1.h>
53 #include "dbus-marshal-header.h"
54 #include "dbus-protocol-gvariant.h"
56 #include "dbus-sysdeps-unix.h"
58 #include <linux/version.h>
59 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
61 # define __NR_memfd_create 385
62 # elif defined(__aarch64__)
63 # define __NR_memfd_create 279
64 # elif defined(__i386__)
65 # define __NR_memfd_create 356
66 # elif defined(__x86_64__)
67 # define __NR_memfd_create 319
69 # error "Architecture not supported"
72 # include <linux/memfd.h>
75 #ifdef DBUS_ENABLE_VERBOSE_MODE
79 /* FIXME shouldn't it be in fcntl.h header file? copied from systemd's missing.h */
80 #ifndef F_LINUX_SPECIFIC_BASE
81 #define F_LINUX_SPECIFIC_BASE 1024
85 #define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
86 #define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
88 #define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
89 #define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
90 #define F_SEAL_GROW 0x0004 /* prevent file from growing */
91 #define F_SEAL_WRITE 0x0008 /* prevent writes */
95 #define MFD_CLOEXEC 0x0001U
98 #ifndef MFD_ALLOW_SEALING
99 #define MFD_ALLOW_SEALING 0x0002U
102 /* ALIGN8 and KDBUS_FOREACH taken from systemd */
103 #define ALIGN8(l) (((l) + 7) & ~7)
104 #define KDBUS_FOREACH(iter, first, _size) \
105 for (iter = (first); \
106 ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
107 ((uint8_t *)(iter) >= (uint8_t *)(first)); \
108 iter = (void*)(((uint8_t *)iter) + ALIGN8((iter)->size)))
109 #define KDBUS_INFINITE_TIMEOUT_NS 0x3fffffffffffffffLLU
112 * @defgroup DBusTransportKdbus DBusTransport implementations for kdbus
113 * @ingroup DBusInternals
114 * @brief Implementation details of DBusTransport on kdbus
119 /** Default Size of the memory area for received non-memfd messages. */
120 #define RECEIVE_POOL_SIZE_DEFAULT_SIZE (16 * 1024LU * 1024LU)
121 /** Name of environmental variable to define receive pool size*/
122 #define RECEIVE_POOL_SIZE_ENV_VAR_NAME "KDBUS_MEMORY_POOL_SIZE"
123 /** Max size of pool size in megabytes*/
124 #define RECEIVE_POOL_SIZE_MAX_MBYTES 64
125 /** Min size of pool size in kilobytes*/
126 #define RECEIVE_POOL_SIZE_MIN_KBYTES 16
128 /** Over this memfd is used to send (if it is not broadcast). */
129 #define MEMFD_SIZE_THRESHOLD (512 * 1024LU)
131 /** Define max bytes read or written in one iteration.
132 * This is to avoid blocking on reading or writing for too long. It is checked after each message is sent or received,
133 * so if message is bigger than MAX_BYTES_PER_ITERATION it will be handled in one iteration, but sending/writing
134 * will break after that message.
136 #define MAX_BYTES_PER_ITERATION 16384
138 #if (MEMFD_SIZE_THRESHOLD > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE)
139 #error Memfd size threshold higher than max kdbus message payload vector size
142 /** Enables verbosing more information about kdbus message.
143 * Works only if DBUS_VERBOSE=1 is used.
145 #define KDBUS_MSG_DECODE_DEBUG 0
148 * Opaque object representing a transport.
150 typedef struct DBusTransportKdbus DBusTransportKdbus;
153 * Implementation details of DBusTransportKdbus. All members are private.
155 struct DBusTransportKdbus
157 DBusTransport base; /**< Parent instance */
158 kdbus_t *kdbus; /**< kdbus data for low level operations */
159 DBusWatch *read_watch; /**< Watch for readability. */
160 DBusWatch *write_watch; /**< Watch for writability. */
162 int max_bytes_read_per_iteration; /**< To avoid blocking too long. */
163 int max_bytes_written_per_iteration; /**< To avoid blocking too long. */
165 char* my_DBus_unique_name; /**< unique name in DBus string format - :1.x , where x is kdbus id*/
166 char* activator; /**< well known name for activator */
167 Matchmaker *matchmaker; /**< for match rules management */
168 dbus_uint32_t client_serial; /**< serial number for messages synthesized by library*/
175 * Creates unique name string frong unique id.
177 * @param id unique id
178 * @returns allocated string with unique name
180 * Caller has to free allocated string with free.
183 create_unique_name_from_unique_id (unsigned long long id)
186 if (asprintf (&str, ":1.%llu", id) == -1)
192 * Puts locally generated message into received messages queue
193 * @param message message that will be added
194 * @param connection connection to which message will be added
195 * @returns TRUE on success, FALSE on memory allocation error
198 add_message_to_received (DBusMessage *message,
199 DBusConnection *connection)
201 DBusList *message_link;
203 message_link = _dbus_list_alloc_link (message);
204 if (message_link == NULL)
206 dbus_message_unref (message);
210 dbus_message_lock (message);
212 _dbus_connection_queue_synthesized_message_link (connection, message_link);
217 reply_with_error_preset_sender (const char *error_type,
218 const char *template,
220 DBusMessage *message,
223 DBusMessage *errMessage;
224 char* error_msg = "";
228 size_t len = strlen (template) + strlen (object) + 1;
229 error_msg = alloca (len);
230 snprintf (error_msg, len, template, object);
233 error_msg = (char*)object;
235 errMessage = _dbus_generate_local_error_message ( dbus_message_get_serial (message),
239 if (errMessage == NULL)
242 if (sender && !dbus_message_set_sender (errMessage, sender))
244 _dbus_verbose ("oom");
245 dbus_message_unref (errMessage);
253 * Generates local error message as a reply to message given as parameter
254 * and adds generated error message to received messages queue.
255 * @param error_type type of error, preferably DBUS_ERROR_(...)
256 * @param template Template of error description. It can has formatting
257 * characters to print object string into it. Can be NULL.
258 * @param object String to print into error description. Can be NULL.
259 * If object is not NULL while template is NULL, the object string
260 * will be the only error description.
261 * @param message Message for which the error reply is generated.
262 * @returns local error message on success, otherwise NULL
265 reply_with_error (const char *error_type,
266 const char *template,
268 DBusMessage *message)
270 return reply_with_error_preset_sender (error_type, template,
271 object, message, NULL);
275 * Generates reply to the message given as a parameter with one item in the reply body
276 * and adds generated reply message to received messages queue.
277 * @param message The message we are replying to.
278 * @param data_type Type of data sent in the reply.Use DBUS_TYPE_(...)
279 * @param pData Address of data sent in the reply.
280 * @returns generated reply on success, otherwise NULL
283 reply_1_data (DBusMessage *message,
287 DBusMessageIter args;
290 reply = dbus_message_new_method_return (message);
294 if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
297 dbus_message_iter_init_append (reply, &args);
298 if (!dbus_message_iter_append_basic (&args, data_type, pData))
304 dbus_message_unref (reply);
310 reply_fixed_array (DBusMessage *message,
315 DBusMessageIter args, array_iter;
318 reply = dbus_message_new_method_return (message);
322 if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
325 dbus_message_iter_init_append (reply, &args);
327 if (!dbus_message_iter_open_container (&args,
329 DBUS_TYPE_BYTE_AS_STRING,
333 if (!dbus_message_iter_append_fixed_array (&array_iter, element_type, &data, n_elements))
336 if (!dbus_message_iter_close_container (&args, &array_iter))
342 dbus_message_iter_abandon_container (&args, &array_iter);
345 dbus_message_unref (reply);
350 * Retrieves file descriptor to memory pool from kdbus module and stores
351 * it in kdbus_transport->memfd. It is then used to send large message.
352 * Triggered when message payload is over MEMFD_SIZE_THRESHOLD
353 * @param kdbus_transport DBusTransportKdbus transport structure
354 * @returns 0 on success, otherwise -1
357 kdbus_acquire_memfd ( void )
361 /* FIXME add HAVE_MEMFD_CREATE */
362 if ((fd = syscall (__NR_memfd_create, "kdbus", MFD_ALLOW_SEALING | MFD_CLOEXEC )) < 0)
364 _dbus_verbose ("memfd_create failed (%d): %m\n", fd);
367 _dbus_verbose ("%s: memfd=%d\n", __FUNCTION__, fd);
372 bloom_add_pair (kdbus_bloom_data_t *bloom_data,
374 const char *parameter,
383 size = strlen (parameter) + strlen (value) + 1;
387 snprintf (buf, size + 1, "%s:%s", parameter, value);
388 _kdbus_bloom_add_data (kdbus, bloom_data, buf, size);
392 bloom_add_prefixes (kdbus_bloom_data_t *bloom_data,
394 const char *parameter,
401 size = strlen (parameter) + strlen (value) + 1;
405 snprintf (buf, size + 1, "%s:%s", parameter, value);
410 last_sep = strrchr (buf, separator);
411 if (!last_sep || last_sep == buf)
415 _kdbus_bloom_add_data (kdbus, bloom_data, buf, last_sep-buf);
420 setup_bloom_filter_for_message (DBusMessage *msg,
422 struct kdbus_bloom_filter *bloom_filter)
424 kdbus_bloom_data_t *bloom_data;
427 DBusMessageIter args;
430 _dbus_assert (bloom_filter);
432 bloom_data = _kdbus_bloom_filter_get_data (bloom_filter);
434 bloom_add_pair (bloom_data,
437 dbus_message_type_to_string (dbus_message_get_type (msg)));
439 bloom_add_pair (bloom_data, kdbus, "interface", dbus_message_get_interface (msg));
440 bloom_add_pair (bloom_data, kdbus, "member", dbus_message_get_member (msg));
441 str = dbus_message_get_path (msg);
444 bloom_add_pair (bloom_data, kdbus, "path", str);
445 bloom_add_pair (bloom_data, kdbus, "path-slash-prefix", str);
446 bloom_add_prefixes (bloom_data, kdbus, "path-slash-prefix", str, '/');
449 if (!dbus_message_iter_init (msg, &args))
452 for (i = 0; i < 64; i++)
455 char buf[sizeof ("arg")-1 + 2 + sizeof ("-slash-prefix")];
459 type = dbus_message_iter_get_arg_type (&args);
460 if (type != DBUS_TYPE_STRING &&
461 type != DBUS_TYPE_OBJECT_PATH &&
462 type != DBUS_TYPE_SIGNATURE)
465 dbus_message_iter_get_basic (&args, &str);
467 snprintf (buf, sizeof (buf), "arg%d", i);
469 bloom_add_pair (bloom_data, kdbus, buf, str);
471 /* point e to end of string, we will add suffixes */
474 /* we need remaining length of the buffer */
475 len = sizeof (buf) - len;
477 strncpy (e, "-dot-prefix", len);
478 bloom_add_prefixes (bloom_data, kdbus, buf, str, '.');
479 strncpy (e, "-slash-prefix", len);
480 bloom_add_prefixes (bloom_data, kdbus, buf, str, '/');
482 if (!dbus_message_iter_next (&args))
490 * Checks if a string is a unique name or well known name.
492 * @param name a valid D-Bus name
493 * @returns 0 for well-known names, otherwise unique id
496 parse_name (const char *name)
498 dbus_uint64_t unique_id = 0;
500 /* if name is unique name it must be converted to unique id */
501 if (strncmp (name, ":1.", 3) == 0)
504 unique_id = strtoull (&name[3], &endptr, 10);
506 if (unique_id == 0 || *endptr != '\0' || errno == ERANGE)
514 prepare_mfd (int memfd,
520 _dbus_verbose ("sending data via memfd\n");
523 wr = write (memfd, body, body_size);
526 _dbus_verbose ("writing to memfd failed: (%d) %m\n", errno);
533 // seal data - kdbus module needs it
534 if (fcntl (memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL) < 0)
536 _dbus_verbose ("memfd sealing failed: %d (%m)\n", errno);
543 send_message (DBusTransportKdbus *transport,
544 struct kdbus_msg *kdbus_msg,
546 const char *destination,
547 dbus_bool_t is_auto_start,
548 struct kdbus_msg **kdbus_msg_reply,
552 dbus_uint64_t flags = 0;
555 flags |= KDBUS_SEND_SYNC_REPLY;
557 ret = _kdbus_send (transport->kdbus,
563 _dbus_verbose ("kdbus error sending message: err %d (%s)\n", ret, _dbus_strerror (ret) );
567 case ENXIO: /* no such id on the bus */
570 dbus_set_error (error,
571 DBUS_ERROR_SERVICE_UNKNOWN,
572 "The name %s was not provided by any .service files",
575 dbus_set_error (error,
576 DBUS_ERROR_NAME_HAS_NO_OWNER,
577 "Name \"%s\" does not exist",
582 dbus_set_error (error,
583 DBUS_ERROR_SERVICE_UNKNOWN,
584 "No support for activation for name: \"%s\"", destination);
588 dbus_set_error (error,
589 DBUS_ERROR_LIMITS_EXCEEDED,
590 "The memory pool of the receiver is full");
594 dbus_set_error (error,
595 DBUS_ERROR_LIMITS_EXCEEDED,
596 "Too many pending messages on the receiver side");
600 dbus_set_error (error,
601 DBUS_ERROR_LIMITS_EXCEEDED,
602 "The size of the message is excessive");
606 dbus_set_error (error,
607 DBUS_ERROR_LIMITS_EXCEEDED,
608 "The maximum number of pending replies per connection has been reached");
612 dbus_set_error (error,
614 "Timeout was reached");
618 dbus_set_error (error,
619 DBUS_ERROR_ACCESS_DENIED,
620 "Permission denied");
624 dbus_set_error (error,
626 "Something went wrong: %s",
627 _dbus_strerror (ret));
637 kdbus_close_message (DBusTransportKdbus *transport, struct kdbus_msg *msg)
639 struct kdbus_item *item;
641 KDBUS_ITEM_FOREACH (item, msg, items)
643 if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD)
644 close (item->memfd.fd);
647 _kdbus_free_mem (transport->kdbus, msg);
650 #ifdef DBUS_ENABLE_VERBOSE_MODE
652 debug_c_str (const char *msg, const char *str, int len)
655 fprintf (stderr, "%s\n", msg);
656 for (i = 0; i < len; i++)
658 fprintf (stderr, "%02x ", (unsigned char)str[i]);
659 if (i%16==15) fprintf (stderr, "\n");
661 fprintf (stderr, "\n");
665 debug_str (const char *msg, const DBusString *str)
667 debug_c_str (msg, _dbus_string_get_const_data (str), _dbus_string_get_length (str));
673 can_send (DBusTransportKdbus *transport,
674 DBusMessage *message)
677 int ret = DBUSPOLICY_RESULT_ALLOW;
678 if (NULL != transport->policy)
680 dbus_uint32_t reply_serial = dbus_message_get_reply_serial (message);
682 /* If reply_serial is non-zero, then it is a reply - just send it.
683 * Otherwise - check the policy.
685 if (0 == reply_serial)
687 /* If method call or unicast signal, check policy */
688 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
689 (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL &&
690 dbus_message_get_destination (message) != NULL))
691 ret = dbuspolicy1_check_out (transport->policy,
692 dbus_message_get_destination (message),
693 transport->my_DBus_unique_name,
694 dbus_message_get_path (message),
695 dbus_message_get_interface (message),
696 dbus_message_get_member (message),
697 dbus_message_get_type (message),
698 dbus_message_get_error_name (message),
700 !dbus_message_get_no_reply (message));
708 /* function prototypes */
709 static int kdbus_message_size (const struct kdbus_msg *msg,
711 static int kdbus_decode_dbus_message (const struct kdbus_msg *msg,
713 DBusTransportKdbus *kdbus_transport,
718 kdbus_write_msg_internal (DBusTransportKdbus *transport,
719 DBusMessage *message,
720 const char *destination,
721 DBusMessage **sync_reply,
722 dbus_bool_t check_privileges)
724 struct kdbus_msg *msg = NULL;
725 struct kdbus_msg *msg_reply = NULL;
726 struct kdbus_item *item;
727 uint64_t dst_id = KDBUS_DST_ID_BROADCAST;
728 const DBusString *header;
729 const DBusString *body;
730 int64_t ret_size = -1;
731 uint64_t body_size = 0;
732 uint64_t header_size = 0;
736 const char* header_data;
738 const char *destination_name = destination;
740 dbus_uint64_t items_size;
741 dbus_uint64_t flags = 0;
742 dbus_uint64_t timeout_ns_or_cookie_reply = 0;
743 dbus_bool_t check_sync_reply = FALSE;
745 dbus_error_init (&error);
747 if (sync_reply != NULL)
748 check_sync_reply = TRUE;
750 // determine destination and destination id
755 _dbus_string_init_const (&str, destination);
756 if (!_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
758 _dbus_verbose ("error: unique name is not valid: %s\n", destination);
762 dst_id = parse_name (destination);
766 dst_id = KDBUS_DST_ID_NAME; /* OK, this is zero anyway
767 * but leave it in case
768 * the kdbus constant changes
772 _dbus_message_get_network_data (message, &header, &body);
773 header_size = _dbus_string_get_length (header);
774 body_size = _dbus_string_get_length (body);
775 ret_size = header_size + body_size;
777 /* check whether we can and should use memfd */
778 if ((dst_id != KDBUS_DST_ID_BROADCAST) && ((uint64_t)ret_size > MEMFD_SIZE_THRESHOLD))
779 memfd = kdbus_acquire_memfd ();
781 _dbus_message_get_unix_fds (message, &unix_fds, &fds_count);
783 items_size = _kdbus_compute_msg_items_size (transport->kdbus,
790 if (!dbus_message_get_auto_start (message))
791 flags |= KDBUS_MSG_NO_AUTO_START;
793 if (KDBUS_DST_ID_BROADCAST == dst_id) /* signals */
794 flags |= KDBUS_MSG_SIGNAL;
797 if (dbus_message_get_no_reply (message)) /* method replies and errors */
798 timeout_ns_or_cookie_reply = dbus_message_get_reply_serial (message);
799 else /* method calls */
801 long tv_sec, tv_usec;
802 int timeout_ms = _dbus_message_get_timeout_ms(message);
804 _dbus_get_monotonic_time (&tv_sec, &tv_usec);
806 timeout_ns_or_cookie_reply = 1U | ( /* ensure nonzero */
807 (dbus_uint64_t)tv_sec * 1000ULL * 1000ULL * 1000ULL
808 + tv_usec * 1000ULL + (
809 timeout_ms == -1 ? _DBUS_DEFAULT_TIMEOUT_VALUE * 1000000LLU :
810 timeout_ms == DBUS_TIMEOUT_INFINITE ? KDBUS_INFINITE_TIMEOUT_NS :
811 (uint64_t)timeout_ms * 1000000U
815 flags |= KDBUS_MSG_EXPECT_REPLY;
819 msg = _kdbus_new_msg (transport->kdbus,
826 dbus_message_get_serial (message),
827 timeout_ns_or_cookie_reply);
831 /* build message contents */
834 header_data = _dbus_string_get_const_data (header);
836 _dbus_verbose ("sending data by vec\n");
837 item = _kdbus_item_add_payload_vec (item,
839 (uintptr_t)header_data);
842 const char* body_data = _dbus_string_get_const_data (body);
843 size_t body_offsets_size;
844 const char *footer_ptr;
846 /* determine body offsets size */
847 if (ret_size <= 0xFF)
848 body_offsets_size = 1;
849 else if (ret_size <= 0xFFFF)
850 body_offsets_size = 2;
851 else if (ret_size <= 0xFFFFFFFF)
852 body_offsets_size = 4;
854 body_offsets_size = 8;
856 /* check footer size */
857 footer_ptr = body_data + body_size - body_offsets_size -1;
858 while (footer_ptr >= body_data && (*footer_ptr) != 0)
861 if (footer_ptr < body_data)
867 #ifdef DBUS_ENABLE_VERBOSE_MODE
870 debug_str ("Header to send:", header);
871 debug_str ("Body to send:", body);
877 /* prepare memfd for body */
878 if (-1 == prepare_mfd (memfd,
880 (uint64_t)((footer_ptr - body_data) * sizeof(char))))
887 item = _kdbus_item_add_payload_memfd (item,
889 (footer_ptr - body_data) * sizeof(char),
893 item = _kdbus_item_add_payload_vec (item,
894 (body_data + body_size - footer_ptr) * sizeof(char),
895 (uintptr_t)footer_ptr);
899 while (body_size > 0)
901 dbus_uint32_t part_size;
903 if (body_size < KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE)
904 part_size = body_size;
906 part_size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
908 /* we need to adjust part size if footer does not fit as a whole */
909 if (body_size - part_size > 0 && footer_ptr < (body_data + part_size))
910 part_size = footer_ptr - body_data;
912 _dbus_verbose ("attaching body part\n");
913 item = _kdbus_item_add_payload_vec (item,
915 (uintptr_t)body_data);
916 body_data += part_size;
917 body_size -= part_size;
923 item = _kdbus_item_add_fds (item, unix_fds, fds_count);
925 if (NULL != destination)
926 item = _kdbus_item_add_string (item,
929 strlen (destination) + 1);
930 else if (dst_id == KDBUS_DST_ID_BROADCAST)
932 struct kdbus_bloom_filter *filter = NULL;
933 item = _kdbus_item_add_bloom_filter (item,
936 setup_bloom_filter_for_message (message, transport->kdbus, filter);
940 if (check_privileges)
944 check = can_send (transport, message);
946 if (check != DBUSPOLICY_RESULT_ALLOW)
952 case DBUSPOLICY_RESULT_DENY:
953 reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
954 "Cannot send message - message rejected due to XML security policies",
958 case DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE:
959 _dbus_assert (destination_name != NULL);
960 if (dbus_message_get_auto_start (message))
961 reply = reply_with_error (DBUS_ERROR_SERVICE_UNKNOWN, NULL,
962 "Cannot send message - destination not known",
965 reply = reply_with_error (DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist",
970 case DBUSPOLICY_RESULT_KDBUS_ERROR:
971 reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
972 "Cannot send message - message rejected due to internal libdbuspolicy error (kdbus)",
976 case DBUSPOLICY_RESULT_CYNARA_ERROR:
977 reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
978 "Cannot send message - message rejected due to internal libdbuspolicy error (Cynara)",
983 reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
984 "Cannot send message - unknown libdbuspolicy error",
995 if (check_sync_reply)
1001 /* puts locally generated reply into received messages queue */
1002 if (!add_message_to_received (reply, transport->base.connection))
1007 } /* ret != DBUSPOLICY_RESULT_ALLOW */
1008 } /* check_privileges */
1011 if (send_message (transport,
1014 dbus_message_get_destination (message),
1015 dbus_message_get_auto_start (message),
1019 DBusMessage *reply = NULL;
1021 if (dbus_error_is_set (&error))
1023 reply = reply_with_error (error.name,
1027 dbus_error_free(&error);
1036 if (check_sync_reply)
1038 *sync_reply = reply;
1042 /* puts locally generated reply into received messages queue */
1043 if (!add_message_to_received (reply, transport->base.connection))
1050 if (check_sync_reply)
1053 int size, ret, *fds;
1057 /* check message size */
1058 size = kdbus_message_size (msg_reply, &n_fds);
1062 kdbus_close_message (transport, msg_reply);
1066 /* alloc buffer for decoded message */
1067 data = dbus_malloc (sizeof (char) * size);
1071 kdbus_close_message (transport, msg_reply);
1075 /* alloc palce for fds */
1076 fds = dbus_malloc (sizeof (int) * (n_fds + 1));
1080 kdbus_close_message (transport, msg_reply);
1085 /* decode dbus message */
1086 ret = kdbus_decode_dbus_message (msg_reply, data,
1087 transport, fds, &n_fds);
1091 kdbus_close_message (transport, msg_reply);
1096 _dbus_string_init_const_len (&str, data, ret);
1098 /* create DBusMessage from kmsg */
1099 *sync_reply = _dbus_decode_kmsg (&str, msg_reply->src_id, fds, (unsigned int)n_fds);
1100 if (*sync_reply == NULL)
1103 kdbus_close_message (transport, msg_reply);
1110 _kdbus_free_msg (msg);
1118 * Sends DBus message using kdbus.
1119 * Handles broadcasts and unicast messages, and passing of Unix fds.
1120 * Also can locally generate error replies on some error returned by kernel.
1122 * TODO refactor to be more compact - maybe we can send header always as a payload vector
1123 * and only message body as memfd if needed.
1125 * @param transport Transport.
1126 * @param message DBus message to be sent
1127 * @param destination Destination of the message.
1128 * @returns bytes sent or -1 if sending failed
1131 kdbus_write_msg (DBusTransportKdbus *transport,
1132 DBusMessage *message,
1133 const char *destination)
1135 return kdbus_write_msg_internal (transport, message, destination, NULL, TRUE);
1138 static dbus_uint64_t
1139 get_pool_size (void)
1141 dbus_uint64_t receive_pool_size = RECEIVE_POOL_SIZE_DEFAULT_SIZE;
1142 const char *env_pool;
1144 env_pool = _dbus_getenv (RECEIVE_POOL_SIZE_ENV_VAR_NAME);
1147 dbus_uint64_t size = 0;
1148 unsigned int multiply = 1;
1151 page_size = sysconf (_SC_PAGESIZE);
1152 if (page_size == -1)
1158 size = strtoul (env_pool, (char**)&env_pool, 10);
1159 if ((errno == EINVAL) || size == 0)
1165 if (*env_pool == 'k')
1170 else if (*env_pool == 'M')
1172 multiply = 1024 * 1024;
1176 if (*env_pool != '\0')
1182 receive_pool_size = size * multiply;
1184 if ((receive_pool_size > RECEIVE_POOL_SIZE_MAX_MBYTES * 1024 * 1024) ||
1185 (receive_pool_size < RECEIVE_POOL_SIZE_MIN_KBYTES * 1024) ||
1186 ((receive_pool_size & (page_size - 1)) != 0)) //pool size must be aligned to page size
1192 _dbus_warn ("%s value is invalid, default value %luB will be used.\n", RECEIVE_POOL_SIZE_ENV_VAR_NAME,
1193 RECEIVE_POOL_SIZE_DEFAULT_SIZE);
1194 _dbus_warn ("Correct value must be between %ukB and %uMB and must be aligned to page size: %ldB.\n",
1195 RECEIVE_POOL_SIZE_MIN_KBYTES, RECEIVE_POOL_SIZE_MAX_MBYTES, page_size);
1197 receive_pool_size = RECEIVE_POOL_SIZE_DEFAULT_SIZE;
1201 _dbus_verbose ("Receive pool size set to %llu.\n", (unsigned long long)receive_pool_size);
1202 return receive_pool_size;
1205 static dbus_uint64_t
1206 get_attach_flags_recv (DBusTransportKdbus *transport)
1208 dbus_uint64_t attach_flags_recv = 0;
1210 #ifdef LIBDBUSPOLICY
1211 attach_flags_recv = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_NAMES | KDBUS_ATTACH_SECLABEL;
1214 return attach_flags_recv;
1218 * Performs kdbus hello - registration on the kdbus bus
1219 * needed to send and receive messages on the bus,
1220 * and configures transport.
1221 * As a result unique id on he bus is obtained.
1223 * @see KDBUS_HELLO_* flags in <linux/kdbus.h>
1225 * @param transport transport structure
1226 * @param registration_flags aditional flags to modify registration process
1227 * @returns #TRUE on success
1230 bus_register_kdbus (DBusTransportKdbus *transport,
1231 dbus_uint32_t registration_flags,
1235 dbus_uint64_t flags;
1237 #ifdef LIBDBUSPOLICY
1238 void *policy = dbuspolicy1_init_shared (_kdbus_get_path(transport->kdbus),
1239 _kdbus_get_fd(transport->kdbus));
1242 dbus_set_error (error,
1243 DBUS_ERROR_NO_REPLY,
1244 "Did not receive a reply. Possible causes include: couldn't load dbus policy for kdbus transport or the message bus security policy blocked the reply.");
1248 transport->policy = policy;
1251 flags = KDBUS_HELLO_ACCEPT_FD;
1252 if (registration_flags & REGISTER_FLAG_MONITOR)
1253 flags |= KDBUS_HELLO_MONITOR;
1255 ret = _kdbus_hello (transport->kdbus,
1258 get_attach_flags_recv (transport),
1260 transport->activator,
1264 dbus_set_error (error, DBUS_ERROR_FAILED, "Hello failed: %d", -ret);
1265 #ifdef LIBDBUSPOLICY
1266 dbuspolicy1_free (policy);
1271 #ifdef LIBDBUSPOLICY
1272 dbuspolicy1_init_set_pool (transport->policy, _kdbus_get_pool(transport->kdbus));
1275 transport->my_DBus_unique_name = create_unique_name_from_unique_id (_kdbus_get_id (transport->kdbus));
1276 if (NULL == transport->my_DBus_unique_name)
1278 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "Hello post failed: %d", -ret);
1279 #ifdef LIBDBUSPOLICY
1280 dbuspolicy1_free (policy);
1285 _dbus_verbose ("-- Our peer ID is: %llu\n", (unsigned long long)_kdbus_get_id (transport->kdbus));
1291 can_own (DBusTransportKdbus *transport,
1294 dbus_bool_t result = TRUE;
1296 #ifdef LIBDBUSPOLICY
1297 if (NULL != transport->policy)
1298 result = (dbuspolicy1_can_own (transport->policy, name) == 1);
1305 request_DBus_name (DBusTransportKdbus *transport,
1310 DBusString service_name_real;
1311 const DBusString *service_name = &service_name_real;
1313 dbus_uint32_t flags;
1315 if (!dbus_message_get_args (msg, error,
1316 DBUS_TYPE_STRING, &name,
1317 DBUS_TYPE_UINT32, &flags,
1321 _dbus_string_init_const (&service_name_real, name);
1323 if (!_dbus_validate_bus_name (service_name, 0,
1324 _dbus_string_get_length (service_name)))
1326 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1327 "Requested bus name \"%s\" is not valid", name);
1329 _dbus_verbose ("Attempt to acquire invalid service name\n");
1334 if (_dbus_string_get_byte (service_name, 0) == ':')
1336 /* Not allowed; only base services can start with ':' */
1337 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1338 "Cannot acquire a service starting with ':' such as \"%s\"", name);
1340 _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"", name);
1345 if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
1347 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1348 "Connection is not allowed to own the service \"%s\"because "
1349 "it is reserved for D-Bus' use only", DBUS_SERVICE_DBUS);
1353 if (!can_own (transport, name))
1355 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
1356 "Connection \"%s\" is not allowed to own the "
1357 "service \"%s\" due to security policies",
1358 transport->my_DBus_unique_name,
1363 *result = _kdbus_request_name (transport->kdbus, name, flags);
1364 if (*result == -EPERM)
1366 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
1367 "Kdbus doesn't allow %s to own the service \"%s\"",
1368 transport->my_DBus_unique_name, _dbus_string_get_const_data (service_name));
1371 else if (*result < 0)
1373 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be acquired, %d, %m", name, errno);
1381 release_DBus_name (DBusTransportKdbus *transport,
1387 DBusString service_name;
1389 if (!dbus_message_get_args (msg, error,
1390 DBUS_TYPE_STRING, &name,
1394 _dbus_string_init_const (&service_name, name);
1396 if (!_dbus_validate_bus_name (&service_name, 0,
1397 _dbus_string_get_length (&service_name)))
1399 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1400 "Given bus name \"%s\" is not valid",
1401 _dbus_string_get_const_data (&service_name));
1403 _dbus_verbose ("Attempt to release invalid service name\n");
1407 if (_dbus_string_get_byte (&service_name, 0) == ':')
1409 /* Not allowed; the base service name cannot be created or released */
1410 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1411 "Cannot release a service starting with ':' such as \"%s\"",
1412 _dbus_string_get_const_data (&service_name));
1414 _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
1415 _dbus_string_get_const_data (&service_name));
1419 if (_dbus_string_equal_c_str (&service_name, DBUS_SERVICE_DBUS))
1421 /* Not allowed; the base service name cannot be created or released */
1422 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1423 "Cannot release the %s service because it is owned by the bus",
1426 _dbus_verbose ("Attempt to release service name \"%s\"",
1431 *result = _kdbus_release_name (transport->kdbus, name);
1434 dbus_set_error (error, DBUS_ERROR_FAILED , "Name \"%s\" could not be released, %d, %m", name, errno);
1442 strcmp_existing (const char *str1, const char *str2)
1444 if (NULL == str1 || NULL == str2)
1446 return strcmp (str1, str2);
1450 is_bloom_needed (MatchRule *rule)
1455 if (_match_rule_get_message_type (rule) != DBUS_TYPE_INVALID
1456 || _match_rule_get_interface (rule) != NULL
1457 || _match_rule_get_member (rule) != NULL
1458 || _match_rule_get_path (rule) != NULL
1459 || _match_rule_get_path_namespace (rule) != NULL)
1462 rule_int = _match_rule_get_args_len (rule);
1463 for (i = 0; i < rule_int; i++)
1465 if (_match_rule_get_args (rule, i) != NULL)
1473 get_bloom (kdbus_t *kdbus, MatchRule *rule, kdbus_bloom_data_t *bloom_data)
1476 const char *rule_string;
1478 char argument_buf[sizeof ("arg")-1 + 2 + sizeof ("-slash-prefix") +1];
1480 rule_int = _match_rule_get_message_type (rule);
1481 if (rule_int != DBUS_MESSAGE_TYPE_INVALID)
1483 bloom_add_pair (bloom_data, kdbus, "message-type", dbus_message_type_to_string (rule_int));
1484 _dbus_verbose ("Adding type %s \n", dbus_message_type_to_string (rule_int));
1487 rule_string = _match_rule_get_interface (rule);
1488 if (rule_string != NULL)
1490 bloom_add_pair (bloom_data, kdbus, "interface", rule_string);
1491 _dbus_verbose ("Adding interface %s \n", rule_string);
1494 rule_string = _match_rule_get_member (rule);
1495 if (rule_string != NULL)
1497 bloom_add_pair (bloom_data, kdbus, "member", rule_string);
1498 _dbus_verbose ("Adding member %s \n", rule_string);
1501 rule_string = _match_rule_get_path (rule);
1502 if (rule_string != NULL)
1504 bloom_add_pair (bloom_data, kdbus, "path", rule_string);
1505 _dbus_verbose ("Adding path %s \n", rule_string);
1508 rule_string = _match_rule_get_path_namespace (rule);
1509 if (rule_string != NULL)
1511 bloom_add_pair (bloom_data, kdbus, "path-slash-prefix", rule_string);
1512 _dbus_verbose ("Adding path-slash-prefix %s \n", rule_string);
1515 rule_int = _match_rule_get_args_len (rule);
1516 for (i = 0; i < rule_int; i++)
1518 rule_string = _match_rule_get_args (rule, i);
1519 if (rule_string != NULL)
1521 unsigned int rule_arg_lens = _match_rule_get_arg_lens (rule, i);
1522 if (rule_arg_lens & MATCH_ARG_IS_PATH)
1524 snprintf (argument_buf, sizeof (argument_buf), "arg%d-slash-prefix", i);
1525 bloom_add_prefixes (bloom_data, kdbus, argument_buf, rule_string, '/');
1527 else if (rule_arg_lens & MATCH_ARG_NAMESPACE)
1529 snprintf (argument_buf, sizeof (argument_buf), "arg%d-dot-prefix", i);
1530 bloom_add_prefixes (bloom_data, kdbus, argument_buf, rule_string, '.');
1534 snprintf (argument_buf, sizeof (argument_buf), "arg%d", i);
1535 bloom_add_pair (bloom_data, kdbus, argument_buf, rule_string);
1542 * Adds a match rule to match broadcast messages going through the message bus.
1543 * Do no affect messages addressed directly.
1545 * TODO add error reporting
1547 * @param transport transport
1551 add_match_kdbus (DBusTransportKdbus *transport,
1554 struct kdbus_cmd_match *cmd;
1555 struct kdbus_item *item;
1557 uint64_t src_id = KDBUS_MATCH_ID_ANY;
1559 dbus_bool_t need_bloom = FALSE;
1561 const char *rule_sender;
1562 const char *rule_arg0 = NULL;
1565 rule_cookie = match_rule_get_cookie (rule);
1566 rule_sender = _match_rule_get_sender (rule);
1569 * First check if it is org.freedesktop.DBus's NameOwnerChanged or any
1570 * org.freedesktop.DBus combination that includes this,
1571 * because it must be converted to special kdbus rule (kdbus has separate rules
1572 * for kdbus (kernel) generated broadcasts).
1574 if (!strcmp_existing (rule_sender, DBUS_SERVICE_DBUS))
1576 int message_type = _match_rule_get_message_type (rule);
1578 if ((DBUS_MESSAGE_TYPE_INVALID == message_type || DBUS_MESSAGE_TYPE_SIGNAL == message_type)
1579 && !strcmp_existing (_match_rule_get_interface (rule), DBUS_INTERFACE_DBUS)
1580 && !strcmp_existing (_match_rule_get_path (rule), DBUS_PATH_DBUS))
1582 if (_match_rule_get_args_len(rule) == 1)
1584 rule_arg0 = _match_rule_get_args(rule, 0);
1588 _dbus_string_init_const (&str, rule_arg0);
1589 ret = _dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str));
1594 if (!strcmp_existing (_match_rule_get_member (rule), "NameOwnerChanged"))
1596 ret = _kdbus_add_match_name_change (transport->kdbus,
1606 _dbus_verbose ("Failed adding match rule for name removal for daemon, error: %d, %s\n",
1607 ret, _dbus_strerror (ret));
1611 _dbus_verbose ("Added match rule for kernel correctly.\n");
1613 ret = _kdbus_add_match_id_change (transport->kdbus,
1621 _dbus_verbose ("Failed adding match rule for adding id for daemon, error: %d, %s\n",
1622 ret, _dbus_strerror (ret));
1626 else if (strcmp (_match_rule_get_member (rule), "NameAcquired") == 0)
1628 ret = _kdbus_add_match_name_acquired (transport->kdbus,
1633 _kdbus_get_id (transport->kdbus),
1638 _dbus_verbose ("Failed adding match rule for name removal for daemon, error: %d, %s\n",
1639 ret, _dbus_strerror (ret));
1643 else if (strcmp (_match_rule_get_member (rule), "NameLost") == 0)
1645 ret = _kdbus_add_match_name_lost (transport->kdbus,
1648 _kdbus_get_id (transport->kdbus),
1655 _dbus_verbose ("Failed adding match rule for name removal for daemon, error: %d, %s\n",
1656 ret, _dbus_strerror (ret));
1661 /* Sender=DBUS_SERVICE_DBUS matches (as opposed to wildcard sender) need no standard rule. */
1667 * standard rule - registered in general way, for non-kernel broadcasts
1668 * kdbus doesn't use it to check kdbus (kernel) generated broadcasts
1671 need_bloom = is_bloom_needed (rule);
1673 if (rule_sender != NULL)
1676 _dbus_string_init_const (&str, rule_sender);
1678 if (!_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
1681 src_id = parse_name (rule_sender);
1683 /* well-known name */
1684 src_id = KDBUS_MATCH_ID_ANY;
1690 items_size = _kdbus_compute_match_items_size (transport->kdbus,
1695 cmd = _kdbus_new_cmd_match (transport->kdbus,
1704 if (NULL != rule_sender) /* well-known name */
1706 item = _kdbus_item_add_string (item,
1709 strlen (rule_sender) + 1);
1710 _dbus_verbose ("Adding sender %s \n", rule_sender);
1712 else if (KDBUS_MATCH_ID_ANY != src_id) /* unique id */
1714 item = _kdbus_item_add_id (item, src_id);
1715 _dbus_verbose ("Adding src_id %llu \n", (unsigned long long)src_id);
1721 item = _kdbus_item_add_bloom_mask (item, transport->kdbus, &bloom);
1722 get_bloom (transport->kdbus, rule, bloom);
1725 ret = _kdbus_add_match (transport->kdbus, cmd);
1727 _kdbus_free_cmd_match (cmd);
1732 _dbus_verbose ("Failed adding match bus rule cookie %llu,\nerror: %d, %s\n",
1733 rule_cookie, ret, _dbus_strerror (ret));
1737 _dbus_verbose ("Added match bus rule %llu\n", rule_cookie);
1741 static DBusMessage *
1742 capture_org_freedesktop_DBus_Hello (DBusTransportKdbus *transport,
1743 DBusMessage *message,
1746 DBusMessageIter args;
1747 dbus_uint32_t registration_flags = 0;
1749 dbus_message_iter_init (message, &args);
1750 if (dbus_message_iter_get_arg_type (&args) == DBUS_TYPE_UINT32)
1751 dbus_message_iter_get_basic (&args, ®istration_flags);
1753 if (!bus_register_kdbus (transport, registration_flags, error))
1756 return reply_1_data (message, DBUS_TYPE_STRING, &transport->my_DBus_unique_name);
1759 free (transport->my_DBus_unique_name);
1763 static DBusMessage *
1764 capture_org_freedesktop_DBus_RequestName (DBusTransportKdbus *transport,
1765 DBusMessage *message,
1770 if (!request_DBus_name (transport, message, &result, error))
1773 return reply_1_data (message, DBUS_TYPE_UINT32, &result);
1776 static DBusMessage *
1777 capture_org_freedesktop_DBus_ReleaseName (DBusTransportKdbus *transport,
1778 DBusMessage *message,
1783 if (!release_DBus_name (transport, message, &result, error))
1786 return reply_1_data (message, DBUS_TYPE_UINT32, &result);
1789 static DBusMessage *
1790 capture_org_freedesktop_DBus_AddMatch (DBusTransportKdbus *transport,
1791 DBusMessage *message,
1796 MatchRule *rule = NULL;
1797 DBusConnection *connection = transport->base.connection;
1799 if (!dbus_message_get_args (message, error,
1800 DBUS_TYPE_STRING, &arg,
1804 _dbus_string_init_const (&arg_str, arg);
1806 rule = match_rule_parse (connection, &arg_str, error);
1810 if (!matchmaker_add_rule (transport->matchmaker, rule))
1812 dbus_set_error_const (error, DBUS_ERROR_NO_MEMORY, "No memory to store match rule");
1816 if (!add_match_kdbus (transport, rule))
1818 dbus_set_error (error, _dbus_error_from_errno (errno), "Could not add match rule, %s",
1819 _dbus_strerror_from_errno ());
1823 match_rule_unref (rule);
1824 return dbus_message_new_method_return (message);
1828 match_rule_unref (rule);
1829 _dbus_verbose ("Error during AddMatch in lib: %s, %s\n", error->name, error->message);
1833 static dbus_uint64_t
1834 get_match_cookie_for_remove (Matchmaker *matchmaker, MatchRule *rule_to_remove)
1836 DBusList *rules = matchmaker_get_rules_list (matchmaker, rule_to_remove);
1839 DBusList *link = _dbus_list_get_last_link (&rules);
1840 while (NULL != link)
1842 if (match_rule_equal_lib (link->data, rule_to_remove))
1844 return match_rule_get_cookie (link->data);
1846 link = _dbus_list_get_prev_link (&rules, link);
1852 static DBusMessage *
1853 capture_org_freedesktop_DBus_RemoveMatch (DBusTransportKdbus *transport,
1854 DBusMessage *message,
1859 MatchRule *rule = NULL;
1860 DBusConnection *connection = transport->base.connection;
1861 dbus_uint64_t cookie;
1863 if (!dbus_message_get_args (message, error,
1864 DBUS_TYPE_STRING, &arg,
1868 _dbus_string_init_const (&arg_str, arg);
1870 rule = match_rule_parse (connection, &arg_str, error);
1873 cookie = get_match_cookie_for_remove (transport->matchmaker, rule);
1876 dbus_set_error (error,
1877 DBUS_ERROR_MATCH_RULE_NOT_FOUND,
1878 "The given match rule wasn't found and can't be removed");
1882 int ret = _kdbus_remove_match (transport->kdbus, cookie);
1884 dbus_set_error (error,
1885 _dbus_error_from_errno (ret),
1886 "Could not remove match rule");
1888 if (!dbus_error_is_set (error))
1889 matchmaker_remove_rule_by_value (transport->matchmaker, rule, error);
1892 match_rule_unref (rule);
1895 if (dbus_error_is_set (error))
1897 _dbus_verbose ("Error during RemoveMatch in lib: %s, %s\n",
1903 return dbus_message_new_method_return (message);
1907 get_connection_info_by_name (DBusMessage *message,
1909 struct nameInfo *info,
1910 DBusTransportKdbus *transport,
1912 dbus_bool_t getLabel)
1915 if (!dbus_validate_bus_name (name, error))
1918 if ((ret = _kdbus_connection_info_by_name (transport->kdbus, name, getLabel, info)) != 0)
1920 if (ESRCH == ret || ENXIO == ret)
1921 dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
1922 "Could not get owner of name '%s': no such name", name);
1924 dbus_set_error (error, DBUS_ERROR_FAILED,
1925 "Unable to query name %s, returned %d, errno = %d (%m).",
1929 if (info->flags & KDBUS_HELLO_ACTIVATOR)
1931 dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
1932 "Could not get owner of name '%s'", name);
1933 /* we return ESRCH - this is an indicator that name has an activator */
1939 /* This local function handles common case for org.freedesktop.DBus method handlers:
1940 * 1. gets string argument from incoming message;
1941 * 2. gets connection info for such name.
1942 * Note: if getLabel argument is set to TRUE, the caller must free info.sec_label.
1945 get_connection_info_from_message_argument (DBusMessage *message,
1947 struct nameInfo *info,
1948 DBusTransportKdbus *transport,
1949 dbus_bool_t getLabel)
1953 if (!dbus_message_get_args (message, error,
1954 DBUS_TYPE_STRING, &arg,
1958 return get_connection_info_by_name (message, error, info, transport, arg, getLabel);
1961 static DBusMessage *
1962 capture_org_freedesktop_DBus_GetConnectionCredentials (DBusTransportKdbus *transport,
1963 DBusMessage *message,
1966 DBusMessage *reply = NULL;
1967 DBusMessageIter reply_iter;
1968 DBusMessageIter array_iter;
1969 struct nameInfo info;
1971 if (get_connection_info_from_message_argument (message, error, &info, transport, TRUE) != 0)
1974 reply = _dbus_asv_new_method_return (message, &reply_iter, &array_iter);
1978 /* we can't represent > 32-bit pids; if your system needs them, please
1979 * add ProcessID64 to the spec or something */
1980 if (info.processId <= _DBUS_UINT32_MAX)
1982 if (!_dbus_asv_add_uint32 (&array_iter, "ProcessID", info.processId))
1985 /* we can't represent > 32-bit uids; if your system needs them, please
1986 * add UnixUserID64 to the spec or something */
1987 if (info.userId <= _DBUS_UINT32_MAX)
1989 if (!_dbus_asv_add_uint32 (&array_iter, "UnixUserID", info.userId))
1993 if (info.sec_label != NULL)
1995 dbus_bool_t res = _dbus_asv_add_byte_array (&array_iter,
1996 "LinuxSecurityLabel",
1998 info.sec_label_len);
2000 dbus_free (info.sec_label);
2006 if (!_dbus_asv_close (&reply_iter, &array_iter))
2009 if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
2015 _dbus_asv_abandon (&reply_iter, &array_iter);
2016 dbus_message_unref (reply);
2022 _mac_smack_use (void)
2024 static int cached_use = -1;
2027 cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
2032 static DBusMessage *
2033 capture_org_freedesktop_DBus_GetConnectionSELinuxSecurityContext (DBusTransportKdbus *transport,
2034 DBusMessage *message,
2037 struct nameInfo info;
2039 if (get_connection_info_from_message_argument (message, error, &info, transport, TRUE) != 0)
2042 if (info.sec_label != NULL)
2044 if (_mac_smack_use())
2046 dbus_set_error (error, DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
2047 "Could not determine security context");
2048 dbus_free (info.sec_label);
2054 reply = reply_fixed_array (message, DBUS_TYPE_BYTE,
2056 info.sec_label_len);
2058 dbus_free (info.sec_label);
2064 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, "Operation not supported");
2070 static DBusMessage *
2071 capture_org_freedesktop_DBus_GetConnectionUnixProcessID (DBusTransportKdbus *transport,
2072 DBusMessage *message,
2075 struct nameInfo info;
2076 dbus_uint32_t processId;
2078 if (get_connection_info_from_message_argument (message, error, &info, transport, FALSE) != 0 ||
2079 info.processId > _DBUS_UINT32_MAX)
2082 processId = info.processId;
2084 return reply_1_data (message, DBUS_TYPE_UINT32, &processId);
2087 static DBusMessage *
2088 capture_org_freedesktop_DBus_GetConnectionUnixUser (DBusTransportKdbus *transport,
2089 DBusMessage *message,
2092 struct nameInfo info;
2093 dbus_uint32_t userId;
2095 if (get_connection_info_from_message_argument (message, error, &info, transport, FALSE) != 0 ||
2096 info.userId > _DBUS_UINT32_MAX)
2099 userId = info.userId;
2101 return reply_1_data (message, DBUS_TYPE_UINT32, &userId);
2104 static DBusMessage *
2105 capture_org_freedesktop_DBus_GetId (DBusTransportKdbus *transport,
2106 DBusMessage *message,
2109 dbus_uint64_t bus_id_size = _kdbus_get_bus_id_size ();
2110 char bus_id[bus_id_size*2+1];
2111 char *bus_id_ptr = bus_id;
2112 char *bus_id_original = _kdbus_get_bus_id (transport->kdbus);
2113 dbus_uint64_t i = 0;
2114 for (; i < bus_id_size; i++)
2115 snprintf (bus_id + 2*i, sizeof (bus_id) - 2*i, "%02x", bus_id_original[i]);
2116 return reply_1_data (message, DBUS_TYPE_STRING, &bus_id_ptr);
2119 static DBusMessage *
2120 capture_org_freedesktop_DBus_GetNameOwner (DBusTransportKdbus *transport,
2121 DBusMessage *message,
2125 struct nameInfo info;
2129 if (!dbus_message_get_args (message, error,
2130 DBUS_TYPE_STRING, &arg,
2134 if (strcmp (arg, DBUS_SERVICE_DBUS) == 0)
2136 if (-1 == asprintf (&unique_name, "%s", DBUS_SERVICE_DBUS))
2141 if (get_connection_info_by_name (message, error, &info, transport, arg, FALSE) != 0)
2144 unique_name = create_unique_name_from_unique_id (info.uniqueId);
2145 if (NULL == unique_name)
2149 reply = reply_1_data (message, DBUS_TYPE_STRING, &unique_name);
2156 static DBusMessage *
2157 reply_listNames (DBusTransportKdbus *transport,
2158 DBusMessage *message,
2160 dbus_uint64_t flags)
2162 DBusMessage *reply = NULL;
2163 dbus_uint64_t prev_id = 0;
2165 /* First, get the list from kdbus */
2167 struct kdbus_info *name_list, *name;
2170 DBusMessageIter iter;
2171 DBusMessageIter array_iter;
2173 ret = _kdbus_list (transport->kdbus,
2179 dbus_set_error (error, DBUS_ERROR_FAILED, "Error listing names");
2183 /* Compose the reply on the fly */
2184 reply = dbus_message_new_method_return (message);
2188 dbus_message_iter_init_append (reply, &iter);
2189 if (!dbus_message_iter_open_container (&iter,
2191 DBUS_TYPE_STRING_AS_STRING,
2195 KDBUS_FOREACH (name, name_list, list_size)
2197 struct kdbus_item *item;
2199 if ((flags & KDBUS_LIST_UNIQUE) && name->id != prev_id)
2203 char *unique_name = create_unique_name_from_unique_id (name->id);
2205 if (NULL == unique_name)
2208 res = dbus_message_iter_append_basic (&array_iter,
2217 KDBUS_ITEM_FOREACH (item, name, items)
2219 if (item->type == KDBUS_ITEM_OWNED_NAME)
2221 char *name_ptr = item->name.name;
2223 if (!dbus_validate_bus_name (name_ptr, NULL))
2226 if (flags & KDBUS_LIST_QUEUED)
2227 name_ptr = create_unique_name_from_unique_id (name->id);
2229 if (NULL == name_ptr)
2232 if (!dbus_message_iter_append_basic (&array_iter,
2236 if (flags & KDBUS_LIST_QUEUED)
2241 if (flags & KDBUS_LIST_QUEUED)
2247 if (!dbus_message_iter_close_container (&iter, &array_iter))
2250 if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
2253 _kdbus_free_mem (transport->kdbus, name_list);
2258 dbus_message_iter_abandon_container (&iter, &array_iter);
2261 dbus_message_unref (reply);
2263 _kdbus_free_mem (transport->kdbus, name_list);
2267 static DBusMessage *
2268 capture_org_freedesktop_DBus_ListActivatableNames (DBusTransportKdbus *transport,
2269 DBusMessage *message,
2272 return reply_listNames (transport, message, error, KDBUS_LIST_ACTIVATORS);
2275 static DBusMessage *
2276 capture_org_freedesktop_DBus_ListNames (DBusTransportKdbus *transport,
2277 DBusMessage *message,
2280 return reply_listNames (transport, message, error, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES);
2283 static DBusMessage *
2284 capture_org_freedesktop_DBus_ListQueuedOwners (DBusTransportKdbus *transport,
2285 DBusMessage *message,
2288 struct nameInfo info;
2290 if (get_connection_info_from_message_argument (message, error, &info, transport, FALSE) != 0)
2293 return reply_listNames (transport, message, error, KDBUS_LIST_QUEUED);
2296 static DBusMessage *
2297 capture_org_freedesktop_DBus_NameHasOwner (DBusTransportKdbus *transport,
2298 DBusMessage *message,
2301 struct nameInfo info;
2302 dbus_bool_t result = TRUE;
2304 if (get_connection_info_from_message_argument (message, error, &info, transport, FALSE) != 0)
2306 if (dbus_error_is_set (error) && dbus_error_has_name (error, DBUS_ERROR_NAME_HAS_NO_OWNER))
2309 dbus_error_free (error);
2315 return reply_1_data (message, DBUS_TYPE_BOOLEAN, &result);
2318 static DBusMessage *
2319 capture_org_freedesktop_DBus_ReloadConfig (DBusTransportKdbus *transport,
2320 DBusMessage *message,
2323 DBusMessageIter iter;
2324 DBusMessage *reply = NULL;
2326 dbus_message_iter_init (message, &iter);
2327 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)
2329 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2330 "Call to 'ReloadConfig' has wrong args");
2334 reply = dbus_message_new_method_return (message);
2338 if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
2344 dbus_message_unref (reply);
2348 static DBusMessage *
2349 capture_org_freedesktop_DBus_StartServiceByName (DBusTransportKdbus *transport,
2350 DBusMessage *message,
2353 struct nameInfo info;
2355 dbus_uint32_t flags; /* Spec says: not used, but we check the syntax anyway */
2357 dbus_bool_t dbus_service = FALSE;
2359 if (!dbus_message_get_args (message, error,
2360 DBUS_TYPE_STRING, &name,
2361 DBUS_TYPE_UINT32, &flags,
2365 dbus_service = (strncmp (name, DBUS_SERVICE_DBUS, strlen (DBUS_SERVICE_DBUS) + 1) == 0);
2368 ret = get_connection_info_by_name (message,
2375 if (dbus_service || 0 == ret)
2377 dbus_uint32_t status = DBUS_START_REPLY_ALREADY_RUNNING;
2378 return reply_1_data (message, DBUS_TYPE_UINT32, &status);
2380 else if (-ESRCH == ret) /* there is an activator */
2382 DBusMessage *sub_message;
2384 /* if we are here, then we have error set - free place for possible real error */
2385 dbus_error_free (error);
2387 /* send method call to org.freedesktop.DBus.Peer.Ping */
2388 sub_message = dbus_message_new_method_call (name, "/", DBUS_INTERFACE_PEER, "Ping");
2389 if (sub_message == NULL)
2392 /* The serial number here is set to -1. A message needs a valid serial number.
2393 * We do not have access to connection's serial numbers counter, so we need to make up one.
2394 * -1 is the last valid serial, so we hope that we'll never get there, especially with 64-bit
2397 dbus_message_set_serial (sub_message, -1);
2399 dbus_message_lock (sub_message);
2401 ret = kdbus_write_msg_internal (transport, sub_message, name, NULL, FALSE);
2403 dbus_message_unref (sub_message);
2409 dbus_uint32_t status = DBUS_START_REPLY_SUCCESS;
2410 return reply_1_data (message, DBUS_TYPE_UINT32, &status);
2416 * There was an error set in get_connection_info_by_name()
2417 * We want to have another error return from StartServiceByName.
2419 dbus_error_free (error);
2420 dbus_set_error (error,
2421 DBUS_ERROR_SERVICE_UNKNOWN,
2422 "The name %s was not provided by any .service files",
2429 static DBusMessage *
2430 capture_org_freedesktop_DBus_UpdateActivationEnvironment (DBusTransportKdbus *transport,
2431 DBusMessage *message,
2434 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
2435 "'%s' method not supported", dbus_message_get_member (message));
2439 typedef DBusMessage * (*CaptureHandler)(DBusTransportKdbus *, DBusMessage *, DBusError *);
2440 struct CaptureHandlers {
2441 const char *method_name;
2442 CaptureHandler handler;
2445 #define HANDLER_ELEMENT(x) {#x, capture_org_freedesktop_DBus_##x}
2447 /* This is to cut the code to parts, and keep it organized:
2448 * an array of elements of type, as in example:
2449 * { "RequestName", capture_org_freedesktop_DBus_RequestName }
2450 * That is, a method of name RequestName will be handled by capture_org_freedesktop_DBus_RequestName ().
2452 static struct CaptureHandlers capture_handlers[] =
2454 // "Hello" is handled separately
2455 // HANDLER_ELEMENT (Hello),
2456 HANDLER_ELEMENT (RequestName),
2457 HANDLER_ELEMENT (ReleaseName),
2458 HANDLER_ELEMENT (AddMatch),
2459 HANDLER_ELEMENT (RemoveMatch),
2460 HANDLER_ELEMENT (GetConnectionCredentials),
2461 HANDLER_ELEMENT (GetConnectionSELinuxSecurityContext),
2462 HANDLER_ELEMENT (GetConnectionUnixProcessID),
2463 HANDLER_ELEMENT (GetConnectionUnixUser),
2464 HANDLER_ELEMENT (GetId),
2465 HANDLER_ELEMENT (GetNameOwner),
2466 HANDLER_ELEMENT (ListActivatableNames),
2467 HANDLER_ELEMENT (ListNames),
2468 HANDLER_ELEMENT (ListQueuedOwners),
2469 HANDLER_ELEMENT (NameHasOwner),
2470 HANDLER_ELEMENT (ReloadConfig),
2471 HANDLER_ELEMENT (StartServiceByName),
2472 HANDLER_ELEMENT (UpdateActivationEnvironment)
2476 * Looks over messages sent to org.freedesktop.DBus. Hello message, which performs
2477 * registration on the bus, is captured as it must be locally converted into
2478 * appropriate ioctl. AddMatch and RemoveMatch are captured to store match rules
2479 * locally in case of false positive result of kdbus bloom filters, but after
2480 * being read they are passed to org.freedesktop.DBus to register these rules
2482 * All the rest org.freedesktop.DBus methods are left untouched
2483 * and they are sent to dbus-daemon in the same way as every other messages.
2485 * @param transport Transport
2486 * @param message Message being sent.
2488 1 if message is not captured and should be passed to kdbus
2489 * 0 if message was handled locally and correctly (it includes proper return of error reply),
2490 * -1 message to org.freedesktop.DBus was not handled correctly.
2493 capture_org_freedesktop_DBus (DBusTransportKdbus *transport,
2494 const char *destination,
2495 DBusMessage *message,
2496 DBusMessage **reply)
2499 if (!strcmp (destination, DBUS_SERVICE_DBUS))
2501 const char *interface = dbus_message_get_interface (message);
2502 if (interface && !strcmp (interface, DBUS_INTERFACE_DBUS))
2505 const char *member = dbus_message_get_member (message);
2507 _dbus_assert (member != NULL);
2509 dbus_error_init (&error);
2511 if (!strcmp (member, "Hello"))
2513 *reply = capture_org_freedesktop_DBus_Hello (transport, message, &error);
2518 int handlers_size = sizeof (capture_handlers)/sizeof (capture_handlers[0]);
2520 while (i < handlers_size && strcmp (member, capture_handlers[i].method_name) != 0)
2523 if (i < handlers_size)
2525 *reply = capture_handlers[i].handler (transport, message, &error);
2529 dbus_set_error (&error, DBUS_ERROR_UNKNOWN_METHOD,
2530 "org.freedesktop.DBus does not understand message %s", member);
2534 if (*reply == NULL && dbus_error_is_set (&error))
2536 *reply = reply_with_error ((char*)error.name,
2540 dbus_error_free (&error);
2548 } /* if DBUS_INTERFACE_DBUS */
2549 } /* if DBUS_SERVICE_DBUS */
2554 #ifdef DBUS_ENABLE_VERBOSE_MODE
2555 #define ENUM_NAME_ITEM(x) case x : return #x
2558 enum_MSG (long long id)
2562 ENUM_NAME_ITEM (_KDBUS_ITEM_NULL);
2563 ENUM_NAME_ITEM (KDBUS_ITEM_PAYLOAD_VEC);
2564 ENUM_NAME_ITEM (KDBUS_ITEM_PAYLOAD_OFF);
2565 ENUM_NAME_ITEM (KDBUS_ITEM_PAYLOAD_MEMFD);
2566 ENUM_NAME_ITEM (KDBUS_ITEM_FDS);
2567 ENUM_NAME_ITEM (KDBUS_ITEM_BLOOM_PARAMETER);
2568 ENUM_NAME_ITEM (KDBUS_ITEM_BLOOM_FILTER);
2569 ENUM_NAME_ITEM (KDBUS_ITEM_DST_NAME);
2570 ENUM_NAME_ITEM (KDBUS_ITEM_CREDS);
2571 ENUM_NAME_ITEM (KDBUS_ITEM_PID_COMM);
2572 ENUM_NAME_ITEM (KDBUS_ITEM_TID_COMM);
2573 ENUM_NAME_ITEM (KDBUS_ITEM_EXE);
2574 ENUM_NAME_ITEM (KDBUS_ITEM_CMDLINE);
2575 ENUM_NAME_ITEM (KDBUS_ITEM_CGROUP);
2576 ENUM_NAME_ITEM (KDBUS_ITEM_CAPS);
2577 ENUM_NAME_ITEM (KDBUS_ITEM_SECLABEL);
2578 ENUM_NAME_ITEM (KDBUS_ITEM_AUDIT);
2579 ENUM_NAME_ITEM (KDBUS_ITEM_CONN_DESCRIPTION);
2580 ENUM_NAME_ITEM (KDBUS_ITEM_NAME);
2581 ENUM_NAME_ITEM (KDBUS_ITEM_TIMESTAMP);
2582 ENUM_NAME_ITEM (KDBUS_ITEM_NAME_ADD);
2583 ENUM_NAME_ITEM (KDBUS_ITEM_NAME_REMOVE);
2584 ENUM_NAME_ITEM (KDBUS_ITEM_NAME_CHANGE);
2585 ENUM_NAME_ITEM (KDBUS_ITEM_ID_ADD);
2586 ENUM_NAME_ITEM (KDBUS_ITEM_ID_REMOVE);
2587 ENUM_NAME_ITEM (KDBUS_ITEM_REPLY_TIMEOUT);
2588 ENUM_NAME_ITEM (KDBUS_ITEM_REPLY_DEAD);
2593 #if KDBUS_MSG_DECODE_DEBUG == 1
2595 enum_PAYLOAD (long long id)
2599 ENUM_NAME_ITEM (KDBUS_PAYLOAD_KERNEL);
2600 ENUM_NAME_ITEM (KDBUS_PAYLOAD_DBUS);
2606 msg_id (uint64_t id)
2609 const char* const_ptr;
2616 snprintf (buf, sizeof (buf), "%llu", (unsigned long long)id);
2624 static dbus_uint32_t
2625 get_next_client_serial (DBusTransportKdbus *transport)
2627 dbus_uint32_t serial;
2629 serial = transport->client_serial++;
2631 if (transport->client_serial == 0)
2632 transport->client_serial = 1;
2638 * Calculates length of the kdbus message content (payload).
2640 * @param msg kdbus message
2641 * @return the length of the kdbus message's payload.
2644 kdbus_message_size (const struct kdbus_msg *msg,
2647 const struct kdbus_item *item;
2651 KDBUS_ITEM_FOREACH (item, msg, items)
2653 if (item->size < KDBUS_ITEM_HEADER_SIZE)
2655 _dbus_verbose (" +%s (%llu bytes) invalid data record\n", enum_MSG (item->type), item->size);
2660 case KDBUS_ITEM_PAYLOAD_OFF:
2661 ret_size += item->vec.size;
2663 case KDBUS_ITEM_PAYLOAD_MEMFD:
2664 ret_size += item->memfd.size;
2666 case KDBUS_ITEM_FDS:
2667 *n_fds = (item->size - KDBUS_ITEM_HEADER_SIZE) / sizeof (int);
2678 generate_NameSignal (const char *signal,
2680 DBusTransportKdbus *transport)
2682 DBusMessage *message;
2684 _dbus_verbose ("Generating %s for %s.\n", signal, name);
2686 message = dbus_message_new_signal (DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, signal);
2687 if (message == NULL)
2690 if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID))
2692 if (!dbus_message_set_destination (message, transport->my_DBus_unique_name))
2694 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
2696 dbus_message_set_serial (message, get_next_client_serial (transport));
2698 if (!add_message_to_received (message, transport->base.connection))
2704 dbus_message_unref (message);
2709 * The NameOwnerChanged signals take three parameters with
2710 * unique or well-known names, but only some forms actually
2713 * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
2714 * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
2715 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
2716 * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
2717 * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
2719 * For the latter two the two unique names must be identical.
2722 kdbus_handle_name_owner_changed (__u64 type,
2723 const char *bus_name,
2726 DBusTransportKdbus *transport)
2728 DBusMessage *message = NULL;
2729 DBusMessageIter args;
2731 const char *const_ptr;
2733 if ((message = dbus_message_new_signal (DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) == NULL)
2736 dbus_message_iter_init_append (message, &args);
2738 // for ID_ADD and ID_REMOVE this function takes NULL as bus_name
2739 if (bus_name == NULL)
2741 snprintf (tmp_str, sizeof (tmp_str), ":1.%llu", old != 0 ? old : new);
2742 const_ptr = tmp_str;
2745 const_ptr = bus_name;
2747 if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &const_ptr))
2750 _dbus_verbose ("%s\n", const_ptr);
2753 if ((old==0) && (new==0))
2755 /* kdbus generates its own set of events that can not be passed to
2756 * client without translation. */
2757 const char *src = "org.freedesktop.DBus";
2758 const char *dst = "org.freedesktop.DBus";
2760 if (type == KDBUS_ITEM_NAME_ADD || type == KDBUS_ITEM_ID_ADD)
2762 else if (type == KDBUS_ITEM_NAME_REMOVE || type == KDBUS_ITEM_ID_REMOVE)
2765 if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &src))
2767 if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &dst))
2770 _dbus_verbose ("[NameOwnerChanged:%s, old=%lld, new=%lld\n", __func__, old, new);
2774 // determine and append old_id
2777 snprintf (tmp_str, sizeof (tmp_str), ":1.%llu", old);
2778 const_ptr = tmp_str;
2783 if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &const_ptr))
2786 _dbus_verbose ("%s\n", const_ptr);
2787 // determine and append new_id
2790 snprintf (tmp_str, sizeof (tmp_str), ":1.%llu", new);
2791 const_ptr = tmp_str;
2796 if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &const_ptr))
2799 _dbus_verbose ("%s\n", const_ptr);
2802 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
2804 dbus_message_set_serial (message, get_next_client_serial (transport));
2806 if (!add_message_to_received (message, transport->base.connection))
2812 dbus_message_unref (message);
2818 handle_item_timestamp (const struct kdbus_item *item)
2820 #if KDBUS_MSG_DECODE_DEBUG == 1
2821 _dbus_verbose (" +%s (%llu bytes) realtime=%lluns monotonic=%lluns\n",
2822 enum_MSG (item->type), item->size,
2823 (unsigned long long)item->timestamp.realtime_ns,
2824 (unsigned long long)item->timestamp.monotonic_ns);
2829 handle_unexpected_item (const struct kdbus_item *item)
2831 _dbus_assert_not_reached ("unexpected item from kdbus");
2835 handle_padding (const struct kdbus_msg *msg,
2836 const struct kdbus_item *end_of_items)
2838 #if KDBUS_MSG_DECODE_DEBUG == 1
2839 if ((char *)end_of_items - ((char *)msg + msg->size) >= 8)
2840 _dbus_verbose ("invalid padding at end of message\n");
2844 #ifdef LIBDBUSPOLICY
2846 load_dbus_header (DBusTransportKdbus *transport,
2848 const char *message_data,
2849 dbus_uint32_t message_len)
2851 DBusValidity validity = DBUS_VALID;
2853 dbus_uint32_t fields_array_len_unsigned;
2854 dbus_uint32_t body_len_unsigned;
2857 if (0 == message_len)
2860 _dbus_string_init_const_len (&message, message_data, message_len);
2861 _dbus_gvariant_raw_get_lengths (&message,
2862 &fields_array_len_unsigned,
2866 _dbus_string_init_const_len (&header->data,
2868 fields_array_len_unsigned + FIRST_GVARIANT_FIELD_OFFSET);
2870 header->padding = 0;
2871 header->byte_order = message_data[0];
2872 header->protocol_version = DBUS_PROTOCOL_VERSION_GVARIANT;
2873 for (i = 0; i <= DBUS_HEADER_FIELD_LAST; i++)
2874 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
2876 return _dbus_header_load_gvariant (header, &validity);
2881 can_receive (DBusTransportKdbus *transport,
2882 const struct kdbus_msg *msg,
2883 const char *message_data,
2884 dbus_uint32_t message_len)
2886 dbus_bool_t result = TRUE;
2888 #ifdef LIBDBUSPOLICY
2889 if (transport->policy)
2892 dbus_bool_t got_header = FALSE;
2893 dbus_bool_t got_creds = FALSE;
2894 dbus_bool_t got_seclabel = FALSE;
2896 if (KDBUS_PAYLOAD_DBUS == msg->payload_type)
2898 const struct kdbus_item *item;
2899 uid_t sender_euid = -1;
2900 gid_t sender_egid = -1;
2901 const char *seclabel = NULL;
2906 if (!_dbus_string_init (&names))
2908 _dbus_verbose ("oom:_dbus_string_init");
2912 KDBUS_ITEM_FOREACH(item, msg, items)
2915 case KDBUS_ITEM_CREDS:
2916 sender_euid = (uid_t) item->creds.euid;
2917 sender_egid = (gid_t) item->creds.egid;
2918 got_creds = (sender_euid != (uid_t)-1) && (sender_egid != (gid_t)-1);
2920 case KDBUS_ITEM_SECLABEL:
2921 seclabel = item->str;
2922 got_seclabel = (seclabel != NULL);
2924 case KDBUS_ITEM_OWNED_NAME:
2927 _dbus_string_init_const (&name, item->name.name);
2928 if (_dbus_validate_bus_name (&name, 0, _dbus_string_get_length (&name)))
2930 if (_dbus_string_get_length (&names) != 0)
2932 if (!_dbus_string_append_byte (&names, ' '))
2934 _dbus_string_free (&names);
2939 if (!_dbus_string_copy (&name,
2942 _dbus_string_get_length (&names)))
2944 _dbus_string_free (&names);
2951 break; /* ignore all other items */
2954 if (NULL != message_data && message_len > 0)
2956 if (load_dbus_header (transport, &header, message_data, message_len))
2960 _dbus_header_get_message_type (&header) != DBUS_MESSAGE_TYPE_METHOD_CALL &&
2961 _dbus_header_get_message_type (&header) != DBUS_MESSAGE_TYPE_SIGNAL)
2965 else if (got_header && got_creds && got_seclabel)
2967 const char *destination = NULL;
2968 const char *path = NULL;
2969 const char *interface = NULL;
2970 const char *member = NULL;
2971 const char *error_name = NULL;
2972 dbus_uint64_t reply_cookie = 0;
2973 dbus_bool_t requested_reply = FALSE;
2976 _dbus_header_get_field_basic (&header,
2977 DBUS_HEADER_FIELD_DESTINATION,
2981 destination = transport->my_DBus_unique_name;
2983 _dbus_header_get_field_basic (&header,
2984 DBUS_HEADER_FIELD_PATH,
2988 _dbus_header_get_field_basic (&header,
2989 DBUS_HEADER_FIELD_INTERFACE,
2993 _dbus_header_get_field_basic (&header,
2994 DBUS_HEADER_FIELD_MEMBER,
2998 _dbus_header_get_field_basic (&header,
2999 DBUS_HEADER_FIELD_ERROR_NAME,
3003 _dbus_header_get_field_basic (&header,
3004 DBUS_HEADER_FIELD_REPLY_SERIAL,
3008 requested_reply = !(_dbus_header_get_flag (&header,
3009 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED));
3011 ret = dbuspolicy1_check_in (transport->policy,
3013 _dbus_string_get_length (&names) > 0 ?
3014 _dbus_string_get_const_data (&names) :
3022 _dbus_header_get_message_type (&header),
3026 result = (1 == ret);
3029 _dbus_string_free (&names);
3038 kdbus_decode_dbus_message (const struct kdbus_msg *msg,
3040 DBusTransportKdbus *kdbus_transport,
3044 const struct kdbus_item *item;
3046 char *buffer = data;
3050 KDBUS_ITEM_FOREACH (item, msg, items)
3052 if (item->size < KDBUS_ITEM_HEADER_SIZE)
3054 _dbus_verbose (" +%s (%llu bytes) invalid data record\n", enum_MSG (item->type), item->size);
3061 case KDBUS_ITEM_PAYLOAD_OFF:
3062 memcpy (data, (char *)msg+item->vec.offset, item->vec.size);
3063 data += item->vec.size;
3064 ret_size += item->vec.size;
3066 #ifdef DBUS_ENABLE_VERBOSE_MODE
3069 debug_c_str ("Message part arrived:", (char *)msg+item->vec.offset, item->vec.size);
3073 _dbus_verbose (" +%s (%llu bytes) off=%llu size=%llu\n",
3074 enum_MSG (item->type), item->size,
3075 (unsigned long long)item->vec.offset,
3076 (unsigned long long)item->vec.size);
3079 case KDBUS_ITEM_PAYLOAD_MEMFD:
3084 size = item->memfd.size;
3085 _dbus_verbose ("memfd.size : %llu\n", (unsigned long long)size);
3087 buf = mmap (NULL, size, PROT_READ, MAP_PRIVATE, item->memfd.fd, 0);
3088 if (buf == MAP_FAILED)
3090 _dbus_verbose ("mmap () fd=%i failed:%m", item->memfd.fd);
3094 memcpy (data, buf, size);
3099 close (item->memfd.fd);
3101 _dbus_verbose (" +%s (%llu bytes) off=%llu size=%llu\n",
3102 enum_MSG (item->type), item->size,
3103 (unsigned long long)item->vec.offset,
3104 (unsigned long long)item->vec.size);
3108 case KDBUS_ITEM_FDS:
3112 *n_fds = (item->size - KDBUS_ITEM_HEADER_SIZE) / sizeof (int);
3113 memcpy (fds, item->fds, *n_fds * sizeof (int));
3114 for (i = 0; i < *n_fds; i++)
3115 _dbus_fd_set_close_on_exec (fds[i]);
3119 case KDBUS_ITEM_CREDS:
3120 #if KDBUS_MSG_DECODE_DEBUG == 1
3121 _dbus_verbose (" +%s (%llu bytes) uid=%lld, gid=%lld, pid=%lld, tid=%lld, starttime=%lld\n",
3122 enum_MSG (item->type), item->size,
3123 item->creds.uid, item->creds.gid,
3124 item->creds.pid, item->creds.tid,
3125 item->creds.starttime);
3129 case KDBUS_ITEM_PID_COMM:
3130 case KDBUS_ITEM_TID_COMM:
3131 case KDBUS_ITEM_EXE:
3132 case KDBUS_ITEM_CGROUP:
3133 case KDBUS_ITEM_SECLABEL:
3134 case KDBUS_ITEM_DST_NAME:
3135 #if KDBUS_MSG_DECODE_DEBUG == 1
3136 _dbus_verbose (" +%s (%llu bytes) '%s' (%zu)\n",
3137 enum_MSG (item->type), item->size, item->str, strlen (item->str));
3141 case KDBUS_ITEM_CMDLINE:
3142 case KDBUS_ITEM_NAME:
3143 #if KDBUS_MSG_DECODE_DEBUG == 1
3145 __u64 size = item->size - KDBUS_ITEM_HEADER_SIZE;
3146 const char *str = item->str;
3149 _dbus_verbose (" +%s (%llu bytes) ", enum_MSG (item->type), item->size);
3152 _dbus_verbose ("'%s' ", str);
3153 size -= strlen (str) + 1;
3154 str += strlen (str) + 1;
3158 _dbus_verbose ("(%d string%s)\n", count, (count == 1) ? "" : "s");
3163 case KDBUS_ITEM_AUDIT:
3164 #if KDBUS_MSG_DECODE_DEBUG == 1
3165 _dbus_verbose (" +%s (%llu bytes) loginuid=%llu sessionid=%llu\n",
3166 enum_MSG (item->type), item->size,
3167 (unsigned long long)item->data64[0],
3168 (unsigned long long)item->data64[1]);
3172 case KDBUS_ITEM_CAPS:
3173 #if KDBUS_MSG_DECODE_DEBUG == 1
3176 const uint32_t *cap;
3179 _dbus_verbose (" +%s (%llu bytes) len=%llu bytes)\n",
3180 enum_MSG (item->type), item->size,
3181 (unsigned long long)item->size - KDBUS_ITEM_HEADER_SIZE);
3184 n = (item->size - KDBUS_ITEM_HEADER_SIZE) / 4 / sizeof (uint32_t);
3186 _dbus_verbose (" CapInh=");
3187 for (i = 0; i < n; i++)
3188 _dbus_verbose ("%08x", cap[(0 * n) + (n - i - 1)]);
3190 _dbus_verbose (" CapPrm=");
3191 for (i = 0; i < n; i++)
3192 _dbus_verbose ("%08x", cap[(1 * n) + (n - i - 1)]);
3194 _dbus_verbose (" CapEff=");
3195 for (i = 0; i < n; i++)
3196 _dbus_verbose ("%08x", cap[(2 * n) + (n - i - 1)]);
3198 _dbus_verbose (" CapInh=");
3199 for (i = 0; i < n; i++)
3200 _dbus_verbose ("%08x", cap[(3 * n) + (n - i - 1)]);
3201 _dbus_verbose ("\n");
3206 case KDBUS_ITEM_TIMESTAMP:
3207 handle_item_timestamp (item);
3210 case KDBUS_ITEM_BLOOM_FILTER:
3215 handle_unexpected_item (item);
3220 handle_padding (msg, item);
3222 if (!can_receive (kdbus_transport, msg, buffer, ret_size))
3223 return 0; /* ignore message if not allowed */
3229 kdbus_decode_kernel_message (const struct kdbus_msg *msg,
3230 DBusTransportKdbus *kdbus_transport)
3232 const struct kdbus_item *item;
3235 KDBUS_ITEM_FOREACH (item, msg, items)
3237 if (item->size < KDBUS_ITEM_HEADER_SIZE)
3239 _dbus_verbose (" +%s (%llu bytes) invalid data record\n", enum_MSG (item->type), item->size);
3246 case KDBUS_ITEM_REPLY_TIMEOUT:
3247 case KDBUS_ITEM_REPLY_DEAD:
3248 _dbus_verbose (" +%s (%llu bytes) cookie=%llu\n",
3249 enum_MSG (item->type), item->size, msg->cookie_reply);
3252 case KDBUS_ITEM_NAME_ADD:
3253 case KDBUS_ITEM_NAME_REMOVE:
3254 case KDBUS_ITEM_NAME_CHANGE:
3258 _dbus_verbose (" +%s (%llu bytes) '%s', old id=%lld, new id=%lld, old flags=0x%llx, new flags=0x%llx\n",
3259 enum_MSG (item->type), (unsigned long long) item->size,
3260 item->name_change.name, item->name_change.old_id.id,
3261 item->name_change.new_id.id, item->name_change.old_id.flags,
3262 item->name_change.new_id.flags);
3264 if (item->name_change.new_id.id == _kdbus_get_id (kdbus_transport->kdbus))
3265 ret_size = generate_NameSignal ("NameAcquired", item->name_change.name, kdbus_transport);
3266 else if (item->name_change.old_id.id == _kdbus_get_id (kdbus_transport->kdbus))
3267 ret_size = generate_NameSignal ("NameLost", item->name_change.name, kdbus_transport);
3272 if (item->name_change.new_id.flags & KDBUS_NAME_ACTIVATOR)
3273 local_ret = kdbus_handle_name_owner_changed (item->type,
3274 item->name_change.name,
3275 item->name_change.old_id.id, 0,
3277 else if (item->name_change.old_id.flags & KDBUS_NAME_ACTIVATOR)
3278 local_ret = kdbus_handle_name_owner_changed (item->type,
3279 item->name_change.name, 0,
3280 item->name_change.new_id.id,
3283 local_ret = kdbus_handle_name_owner_changed (item->type,
3284 item->name_change.name,
3285 item->name_change.old_id.id,
3286 item->name_change.new_id.id,
3288 if (local_ret == -1)
3291 ret_size += local_ret;
3295 case KDBUS_ITEM_ID_ADD:
3296 case KDBUS_ITEM_ID_REMOVE:
3297 _dbus_verbose (" +%s (%llu bytes) id=%llu flags=%llu\n",
3298 enum_MSG (item->type), (unsigned long long) item->size,
3299 (unsigned long long) item->id_change.id,
3300 (unsigned long long) item->id_change.flags);
3302 if (item->id_change.flags & KDBUS_HELLO_ACTIVATOR)
3303 ret_size = kdbus_handle_name_owner_changed (item->type, NULL, 0, 0,
3306 ret_size = kdbus_handle_name_owner_changed (item->type, NULL,
3307 item->type == KDBUS_ITEM_ID_ADD ? 0 : item->id_change.id,
3308 item->type == KDBUS_ITEM_ID_ADD ? item->id_change.id : 0,
3315 case KDBUS_ITEM_TIMESTAMP:
3316 handle_item_timestamp (item);
3320 handle_unexpected_item (item);
3325 handle_padding (msg, item);
3332 * Decodes kdbus message in order to extract DBus message and puts it into received data buffer
3333 * and file descriptor's buffer. Also captures kdbus error messages and kdbus kernel broadcasts
3334 * and converts all of them into appropriate DBus messages.
3336 * @param msg kdbus message
3337 * @param data place to copy DBus message to
3338 * @param kdbus_transport transport
3339 * @param fds place to store file descriptors received
3340 * @param n_fds place to store quantity of file descriptors received
3341 * @return number of DBus message's bytes received or -1 on error
3344 kdbus_decode_msg (const struct kdbus_msg *msg,
3346 DBusTransportKdbus *kdbus_transport,
3352 #if KDBUS_MSG_DECODE_DEBUG == 1
3353 _dbus_verbose ("MESSAGE: %s (%llu bytes) flags=0x%llx, %s → %s, cookie=%llu, timeout=%llu\n",
3354 enum_PAYLOAD (msg->payload_type),
3355 (unsigned long long) msg->size,
3356 (unsigned long long) msg->flags,
3357 msg_id (msg->src_id),
3358 msg_id (msg->dst_id),
3359 (unsigned long long) msg->cookie,
3360 (unsigned long long) msg->timeout_ns);
3363 switch (msg->payload_type)
3365 case KDBUS_PAYLOAD_DBUS:
3366 ret_size = kdbus_decode_dbus_message (msg, data, kdbus_transport, fds, n_fds);
3368 case KDBUS_PAYLOAD_KERNEL:
3369 ret_size = kdbus_decode_kernel_message (msg, kdbus_transport);
3372 _dbus_assert_not_reached ("unexpected payload type from kdbus");
3380 * Reads message from kdbus and puts it into DBus buffers
3382 * @param kdbus_transport transport
3383 * @param buffer place to copy received message to
3384 * @param fds place to store file descriptors received with the message
3385 * @param n_fds place to store quantity of file descriptors received
3386 * @return size of received message on success, -1 on error
3389 kdbus_read_message (DBusTransportKdbus *kdbus_transport,
3394 int ret_size, buf_size;
3395 struct kdbus_msg *msg;
3398 dbus_uint64_t flags = 0;
3401 start = _dbus_string_get_length (buffer);
3403 if (kdbus_transport->activator != NULL)
3404 flags |= KDBUS_RECV_PEEK;
3406 ret = _kdbus_recv (kdbus_transport->kdbus, flags, 0, &msg);
3410 _dbus_verbose ("kdbus error receiving message: %d (%s)\n", ret, _dbus_strerror (ret));
3414 buf_size = kdbus_message_size (msg, n_fds);
3417 _dbus_verbose ("kdbus error - too short message: %d (%m)\n", errno);
3421 /* What is the maximum size of the locally generated message?
3422 I just assume 2048 bytes */
3423 buf_size = MAX (buf_size, 2048);
3425 if (!_dbus_string_lengthen (buffer, buf_size))
3430 data = _dbus_string_get_data_len (buffer, start, buf_size);
3432 ret_size = kdbus_decode_msg (msg, data, kdbus_transport, fds, n_fds);
3434 if (ret_size == -1) /* error */
3435 _dbus_string_set_length (buffer, start);
3436 else if (ret_size >= 0 && buf_size != ret_size) /* case of locally generated message */
3437 _dbus_string_set_length (buffer, start + ret_size);
3440 _dbus_message_loader_set_unique_sender_id (kdbus_transport->base.loader, msg->src_id);
3442 if (kdbus_transport->activator != NULL)
3445 ret = _kdbus_free_mem (kdbus_transport->kdbus, msg);
3448 _dbus_verbose ("kdbus error freeing message: %d (%s)\n", ret, _dbus_strerror (ret));
3455 #ifdef ENABLE_KDBUS_SYNC_CALLS
3456 static DBusMessage *
3457 kdbus_send_sync_call (DBusTransportKdbus *transport,
3458 DBusMessage *message)
3460 DBusMessage *reply = NULL;
3462 const char *destination;
3464 dbus_message_lock (message);
3466 destination = dbus_message_get_destination (message);
3471 ret = capture_org_freedesktop_DBus ((DBusTransportKdbus*)transport, destination, message, &reply);
3478 kdbus_write_msg_internal (transport, message, destination, &reply, TRUE);
3486 dbus_error_init (&error);
3488 dbus_set_error (&error, DBUS_ERROR_FAILED,
3489 "Something went wrong");
3491 reply = reply_with_error ((char*)error.name,
3496 dbus_error_free (&error);
3500 _dbus_assert (reply != NULL);
3501 dbus_message_lock (reply);
3508 * Copy-paste from socket transport. Only renames done.
3511 free_watches (DBusTransportKdbus *kdbus_transport)
3513 DBusConnection *connection = kdbus_transport->base.connection;
3514 _dbus_verbose ("start\n");
3516 if (kdbus_transport->read_watch)
3519 _dbus_connection_remove_watch_unlocked (connection,
3520 kdbus_transport->read_watch);
3521 _dbus_watch_invalidate (kdbus_transport->read_watch);
3522 _dbus_watch_unref (kdbus_transport->read_watch);
3523 kdbus_transport->read_watch = NULL;
3526 if (kdbus_transport->write_watch)
3529 _dbus_connection_remove_watch_unlocked (connection,
3530 kdbus_transport->write_watch);
3531 _dbus_watch_invalidate (kdbus_transport->write_watch);
3532 _dbus_watch_unref (kdbus_transport->write_watch);
3533 kdbus_transport->write_watch = NULL;
3536 _dbus_verbose ("end\n");
3540 free_policies (DBusTransportKdbus *transport)
3542 #ifdef LIBDBUSPOLICY
3543 if (NULL != transport->policy)
3544 dbuspolicy1_free (transport->policy);
3549 * Copy-paste from socket transport. Only done needed renames and removed
3550 * lines related to encoded messages.
3553 transport_finalize (DBusTransport *transport)
3555 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus *)transport;
3556 _dbus_verbose ("\n");
3558 free_watches (kdbus_transport);
3560 _dbus_transport_finalize_base (transport);
3562 _dbus_assert (kdbus_transport->read_watch == NULL);
3563 _dbus_assert (kdbus_transport->write_watch == NULL);
3565 free_matchmaker (kdbus_transport->matchmaker);
3567 dbus_free (kdbus_transport->activator);
3569 free_policies ( kdbus_transport );
3571 _kdbus_free (kdbus_transport->kdbus);
3572 free (kdbus_transport->my_DBus_unique_name);
3574 dbus_free (transport);
3578 * Copy-paste from socket transport. Removed code related to authentication,
3579 * socket_transport replaced by kdbus_transport.
3582 check_write_watch (DBusTransportKdbus *kdbus_transport)
3585 DBusTransport *transport = &kdbus_transport->base;
3587 if (transport->connection == NULL)
3590 if (transport->disconnected)
3592 _dbus_assert (kdbus_transport->write_watch == NULL);
3596 _dbus_transport_ref (transport);
3598 needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
3600 _dbus_verbose ("check_write_watch (): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n",
3601 needed, transport->connection, kdbus_transport->write_watch,
3602 _kdbus_get_fd (kdbus_transport->kdbus),
3603 _dbus_connection_has_messages_to_send_unlocked (transport->connection));
3605 _dbus_connection_toggle_watch_unlocked (transport->connection,
3606 kdbus_transport->write_watch,
3609 _dbus_transport_unref (transport);
3613 * Copy-paste from socket transport. Removed code related to authentication,
3614 * socket_transport replaced by kdbus_transport.
3617 check_read_watch (DBusTransportKdbus *kdbus_transport)
3619 dbus_bool_t need_read_watch;
3620 DBusTransport *transport = &kdbus_transport->base;
3622 _dbus_verbose ("fd = %d\n",_kdbus_get_fd (kdbus_transport->kdbus));
3624 if (transport->connection == NULL)
3627 if (transport->disconnected)
3629 _dbus_assert (kdbus_transport->read_watch == NULL);
3633 _dbus_transport_ref (transport);
3636 (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
3637 (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds);
3639 _dbus_verbose (" setting read watch enabled = %d\n", need_read_watch);
3641 _dbus_connection_toggle_watch_unlocked (transport->connection,
3642 kdbus_transport->read_watch,
3645 _dbus_transport_unref (transport);
3649 * Copy-paste from socket transport.
3652 do_io_error (DBusTransport *transport)
3654 _dbus_transport_ref (transport);
3655 _dbus_transport_disconnect (transport);
3656 _dbus_transport_unref (transport);
3660 * Based on do_writing from socket transport.
3661 * Removed authentication code and code related to encoded messages
3662 * and adapted to kdbus transport.
3663 * In socket transport returns false on out-of-memory. Here this won't happen,
3664 * so it always returns TRUE.
3667 do_writing (DBusTransport *transport)
3669 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus*) transport;
3671 dbus_bool_t oom = FALSE;
3673 if (transport->disconnected)
3675 _dbus_verbose ("Not connected, not writing anything\n");
3679 _dbus_verbose ("do_writing (), have_messages = %d, fd = %d\n",
3680 _dbus_connection_has_messages_to_send_unlocked (transport->connection),
3681 _kdbus_get_fd (kdbus_transport->kdbus));
3683 while (!transport->disconnected && _dbus_connection_has_messages_to_send_unlocked (transport->connection))
3686 DBusMessage *message;
3688 const DBusString *header;
3689 const DBusString *body;
3690 const char* pDestination;
3692 if (total > kdbus_transport->max_bytes_written_per_iteration)
3694 _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
3695 total, kdbus_transport->max_bytes_written_per_iteration);
3700 message = _dbus_connection_get_message_to_send (transport->connection);
3701 _dbus_assert (message != NULL);
3702 pDestination = dbus_message_get_destination (message);
3708 ret = capture_org_freedesktop_DBus ((DBusTransportKdbus*)transport, pDestination, message, &reply);
3709 if (ret < 0) //error
3714 else if (ret == 0) //message captured and handled correctly
3716 /* puts locally generated reply into received messages queue */
3717 if (!add_message_to_received (reply, kdbus_transport->base.connection))
3723 _dbus_message_get_network_data (message, &header, &body);
3724 bytes_written = _dbus_string_get_length (header) + _dbus_string_get_length (body);
3727 //else send as regular message
3730 bytes_written = kdbus_write_msg (kdbus_transport, message, pDestination);
3733 if (bytes_written < 0)
3735 if (errno == ENOMEM)
3741 /* EINTR already handled for us */
3743 /* For some discussion of why we also ignore EPIPE here, see
3744 * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
3747 if (_dbus_get_is_errno_eagain_or_ewouldblock (errno) || _dbus_get_is_errno_epipe (errno))
3751 _dbus_verbose ("Error writing to remote app: %s\n", _dbus_strerror_from_errno ());
3752 do_io_error (transport);
3758 #if defined (DBUS_ENABLE_VERBOSE_MODE) || !defined (DBUS_DISABLE_ASSERT)
3759 int total_bytes_to_write;
3761 _dbus_message_get_network_data (message, &header, &body);
3762 total_bytes_to_write = _dbus_string_get_length (header)
3763 + _dbus_string_get_length (body);
3764 _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
3765 total_bytes_to_write);
3767 _dbus_assert (bytes_written == total_bytes_to_write);
3769 total += bytes_written;
3771 _dbus_connection_message_sent_unlocked (transport->connection,
3784 * Based on do_reading from socket transport.
3785 * Removed authentication code and code related to encoded messages
3786 * and adapted to kdbus transport.
3787 * returns false on out-of-memory
3790 do_reading (DBusTransport *transport)
3792 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus*) transport;
3795 dbus_bool_t oom = FALSE;
3799 _dbus_verbose ("fd = %d\n", _kdbus_get_fd (kdbus_transport->kdbus));
3803 /* See if we've exceeded max messages and need to disable reading */
3804 if (kdbus_transport->activator == NULL)
3805 check_read_watch (kdbus_transport);
3807 if (total > kdbus_transport->max_bytes_read_per_iteration)
3809 _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
3810 total, kdbus_transport->max_bytes_read_per_iteration);
3814 _dbus_assert (kdbus_transport->read_watch != NULL ||
3815 transport->disconnected);
3817 if (transport->disconnected)
3820 if (!dbus_watch_get_enabled (kdbus_transport->read_watch))
3823 if (!_dbus_message_loader_get_unix_fds (transport->loader, &fds, (unsigned int *)&n_fds))
3825 _dbus_verbose ("Out of memory reading file descriptors\n");
3829 _dbus_message_loader_get_buffer (transport->loader, &buffer, NULL, NULL);
3831 bytes_read = kdbus_read_message (kdbus_transport, buffer, fds, &n_fds);
3833 if (bytes_read >= 0 && n_fds > 0)
3834 _dbus_verbose ("Read %i unix fds\n", n_fds);
3836 _dbus_message_loader_return_buffer (transport->loader,
3838 _dbus_message_loader_return_unix_fds (transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
3842 /* EINTR already handled for us */
3844 if (_dbus_get_is_errno_enomem (errno))
3846 _dbus_verbose ("Out of memory in read()/do_reading()\n");
3850 else if (_dbus_get_is_errno_eagain_or_ewouldblock (errno))
3854 _dbus_verbose ("Error reading from remote app: %s\n",
3855 _dbus_strerror_from_errno ());
3856 do_io_error (transport);
3860 else if (bytes_read > 0)
3862 _dbus_verbose (" read %d bytes\n", bytes_read);
3864 total += bytes_read;
3866 if (!_dbus_transport_queue_messages (transport))
3869 _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
3873 /* Try reading more data until we get EAGAIN and return, or
3874 * exceed max bytes per iteration. If in blocking mode of
3875 * course we'll block instead of returning.
3879 /* 0 == bytes_read is for kernel and ignored messages */
3888 * Copy-paste from socket transport, with socket replaced by kdbus.
3891 unix_error_with_read_to_come (DBusTransport *itransport,
3895 DBusTransportKdbus *transport = (DBusTransportKdbus *) itransport;
3897 if (!((flags & DBUS_WATCH_HANGUP) || (flags & DBUS_WATCH_ERROR)))
3900 /* If we have a read watch enabled ...
3901 we -might have data incoming ... => handle the HANGUP there */
3902 if (watch != transport->read_watch && _dbus_watch_get_enabled (transport->read_watch))
3909 * Copy-paste from socket transport. Removed authentication related code
3910 * and renamed socket_transport to kdbus_transport.
3913 kdbus_handle_watch (DBusTransport *transport,
3917 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus*) transport;
3919 _dbus_assert (watch == kdbus_transport->read_watch ||
3920 watch == kdbus_transport->write_watch);
3921 _dbus_assert (watch != NULL);
3923 /* If we hit an error here on a write watch, don't disconnect the transport yet because data can
3924 * still be in the buffer and do_reading may need several iteration to read
3925 * it all (because of its max_bytes_read_per_iteration limit).
3927 if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags))
3929 _dbus_verbose ("Hang up or error on watch\n");
3930 _dbus_transport_disconnect (transport);
3934 if (watch == kdbus_transport->read_watch &&
3935 (flags & DBUS_WATCH_READABLE))
3937 _dbus_verbose ("handling read watch %p flags = %x\n",
3940 if (!do_reading (transport))
3942 _dbus_verbose ("no memory to read\n");
3946 else if (watch == kdbus_transport->write_watch &&
3947 (flags & DBUS_WATCH_WRITABLE))
3949 _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
3950 _dbus_connection_has_messages_to_send_unlocked (transport->connection));
3952 if (!do_writing (transport))
3954 _dbus_verbose ("no memory to write\n");
3958 /* See if we still need the write watch */
3959 check_write_watch (kdbus_transport);
3966 * Copy-paste from socket transport, but socket_transport renamed to kdbus_transport
3967 * and _dbus_close_socket replaced with close ().
3970 kdbus_disconnect (DBusTransport *transport)
3972 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus*) transport;
3974 _dbus_verbose ("\n");
3976 free_watches (kdbus_transport);
3978 _kdbus_close (kdbus_transport->kdbus);
3982 * Copy-paste from socket transport. Renamed socket_transport to
3983 * kdbus_transport and added setting authenticated to TRUE, because
3984 * we do not perform authentication in kdbus, so we have mark is as already done
3985 * to make everything work.
3988 kdbus_connection_set (DBusTransport *transport)
3990 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus*) transport;
3992 _dbus_watch_set_handler (kdbus_transport->write_watch,
3993 _dbus_connection_handle_watch,
3994 transport->connection, NULL);
3996 _dbus_watch_set_handler (kdbus_transport->read_watch,
3997 _dbus_connection_handle_watch,
3998 transport->connection, NULL);
4000 if (!_dbus_connection_add_watch_unlocked (transport->connection,
4001 kdbus_transport->write_watch))
4004 if (!_dbus_connection_add_watch_unlocked (transport->connection,
4005 kdbus_transport->read_watch))
4007 _dbus_connection_remove_watch_unlocked (transport->connection,
4008 kdbus_transport->write_watch);
4012 check_read_watch (kdbus_transport);
4013 check_write_watch (kdbus_transport);
4019 * Copy-paste from socket_transport.
4020 * Socket_transport renamed to kdbus_transport
4022 * Original dbus copy-pasted @todo comment below.
4023 * @todo We need to have a way to wake up the select sleep if
4024 * a new iteration request comes in with a flag (read/write) that
4025 * we're not currently serving. Otherwise a call that just reads
4026 * could block a write call forever (if there are no incoming
4030 kdbus_do_iteration (DBusTransport *transport,
4032 int timeout_milliseconds)
4034 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus*) transport;
4039 _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
4040 flags & DBUS_ITERATION_DO_READING ? "read" : "",
4041 flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
4042 timeout_milliseconds,
4043 kdbus_transport->read_watch,
4044 kdbus_transport->write_watch,
4045 _kdbus_get_fd (kdbus_transport->kdbus));
4047 poll_fd.fd = _kdbus_get_fd (kdbus_transport->kdbus);
4052 * This fix is for reply_with_error function.
4053 * When timeout is set to -1 in client application,
4054 * error messages are inserted directly to incoming queue and
4055 * application hangs on dbus_poll.
4057 * This causes a busy loop in _dbus_connection_block_pending_call()
4058 * There is no case of waiting for the locally-generated error reply
4060 if (_dbus_connection_get_n_incoming (transport->connection) > 0)
4062 timeout_milliseconds = 0;
4066 /* This is kind of a hack; if we have stuff to write, then try
4067 * to avoid the poll. This is probably about a 5% speedup on an
4068 * echo client/server.
4070 * If both reading and writing were requested, we want to avoid this
4071 * since it could have funky effects:
4072 * - both ends spinning waiting for the other one to read
4073 * data so they can finish writing
4074 * - prioritizing all writing ahead of reading
4076 if ((flags & DBUS_ITERATION_DO_WRITING) &&
4077 !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
4078 !transport->disconnected &&
4079 _dbus_connection_has_messages_to_send_unlocked (transport->connection))
4081 do_writing (transport);
4083 if (transport->disconnected ||
4084 !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
4088 /* If we get here, we decided to do the poll() after all */
4089 _dbus_assert (kdbus_transport->read_watch);
4090 if (flags & DBUS_ITERATION_DO_READING)
4091 poll_fd.events |= _DBUS_POLLIN;
4093 _dbus_assert (kdbus_transport->write_watch);
4094 if (flags & DBUS_ITERATION_DO_WRITING)
4095 poll_fd.events |= _DBUS_POLLOUT;
4099 if ( (flags & DBUS_ITERATION_BLOCK) && !(flags & DBUS_ITERATION_DO_WRITING))
4100 poll_timeout = timeout_milliseconds;
4104 /* For blocking selects we drop the connection lock here
4105 * to avoid blocking out connection access during a potentially
4106 * indefinite blocking call. The io path is still protected
4107 * by the io_path_cond condvar, so we won't reenter this.
4109 if (flags & DBUS_ITERATION_BLOCK)
4111 _dbus_verbose ("unlock pre poll\n");
4112 _dbus_connection_unlock (transport->connection);
4116 poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
4118 if (poll_res < 0 && _dbus_get_is_errno_eintr (errno))
4121 if (flags & DBUS_ITERATION_BLOCK)
4123 _dbus_verbose ("lock post poll\n");
4124 _dbus_connection_lock (transport->connection);
4130 poll_fd.revents = 0; /* some concern that posix does not guarantee this;
4131 * valgrind flags it as an error. though it probably
4132 * is guaranteed on linux at least.
4135 if (poll_fd.revents & _DBUS_POLLERR)
4136 do_io_error (transport);
4139 dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
4141 _dbus_verbose ("in iteration, need_read=%d\n",
4144 if (need_read && (flags & DBUS_ITERATION_DO_READING))
4145 do_reading (transport);
4146 /* We always be able to write to kdbus */
4147 if (flags & DBUS_ITERATION_DO_WRITING)
4148 do_writing (transport);
4152 _dbus_verbose ("Error from _dbus_poll(): %s\n", _dbus_strerror_from_errno ());
4156 /* We need to install the write watch only if we did not
4157 * successfully write everything. Note we need to be careful that we
4158 * don't call check_write_watch *before* do_writing, since it's
4159 * inefficient to add the write watch, and we can avoid it most of
4160 * the time since we can write immediately.
4162 * However, we MUST always call check_write_watch(); DBusConnection code
4163 * relies on the fact that running an iteration will notice that
4164 * messages are pending.
4166 check_write_watch (kdbus_transport);
4168 _dbus_verbose (" ... leaving do_iteration()\n");
4172 * Copy-paste from socket transport.
4175 kdbus_live_messages_changed (DBusTransport *transport)
4177 /* See if we should look for incoming messages again */
4178 check_read_watch ((DBusTransportKdbus *)transport);
4182 * Gets file descriptor of the kdbus bus.
4183 * @param transport transport
4184 * @param fd_p place to write fd to
4185 * @returns always TRUE
4188 kdbus_get_kdbus_fd (DBusTransport *transport,
4191 DBusTransportKdbus *kdbus_transport = (DBusTransportKdbus*) transport;
4193 fd_p->fd = _kdbus_get_fd (kdbus_transport->kdbus);
4198 static const DBusTransportVTable kdbus_vtable = {
4202 kdbus_connection_set,
4204 kdbus_live_messages_changed,
4208 typedef unsigned long (*ConnectionInfoExtractField) (struct nameInfo *);
4210 static inline unsigned long
4211 _extract_name_info_userId (struct nameInfo *nameInfo)
4213 return nameInfo->userId;
4216 static inline unsigned long
4217 _extract_name_info_processId (struct nameInfo *nameInfo)
4219 return nameInfo->processId;
4223 _dbus_transport_kdbus_get_connection_info_ulong_field (DBusTransportKdbus *transport,
4224 ConnectionInfoExtractField function,
4227 struct nameInfo conn_info;
4230 ret = _kdbus_connection_info_by_id (transport->kdbus,
4231 _kdbus_get_id (transport->kdbus),
4237 *val = function (&conn_info);
4242 _dbus_transport_kdbus_get_unix_user (DBusTransport *transport,
4245 return _dbus_transport_kdbus_get_connection_info_ulong_field ((DBusTransportKdbus *)transport,
4246 _extract_name_info_userId,
4251 _dbus_transport_kdbus_get_unix_process_id (DBusTransport *transport,
4254 return _dbus_transport_kdbus_get_connection_info_ulong_field ((DBusTransportKdbus *)transport,
4255 _extract_name_info_processId,
4260 * Copy-paste from dbus_transport_socket with needed changes.
4262 * Creates a new transport for the given kdbus file descriptor and address.
4263 * The file descriptor must be nonblocking.
4265 * @param fd the file descriptor.
4266 * @param address the transport's address
4267 * @returns the new transport, or #NULL if no memory.
4269 static DBusTransportKdbus *
4270 new_kdbus_transport (kdbus_t *kdbus,
4271 const DBusString *address,
4272 const char *activator)
4274 DBusTransportKdbus *kdbus_transport;
4276 kdbus_transport = dbus_new0 (DBusTransportKdbus, 1);
4277 if (kdbus_transport == NULL)
4280 kdbus_transport->kdbus = kdbus;
4282 kdbus_transport->write_watch = _dbus_watch_new (_kdbus_get_fd (kdbus),
4283 DBUS_WATCH_WRITABLE,
4286 if (kdbus_transport->write_watch == NULL)
4289 kdbus_transport->read_watch = _dbus_watch_new (_kdbus_get_fd (kdbus),
4290 DBUS_WATCH_READABLE,
4293 if (kdbus_transport->read_watch == NULL)
4296 if (!_dbus_transport_init_base_authenticated (&kdbus_transport->base,
4301 _dbus_transport_set_get_unix_user_function (&kdbus_transport->base,
4302 _dbus_transport_kdbus_get_unix_user);
4303 _dbus_transport_set_get_unix_process_id_function (&kdbus_transport->base,
4304 _dbus_transport_kdbus_get_unix_process_id);
4305 #ifdef ENABLE_KDBUS_SYNC_CALLS
4306 _dbus_transport_set_send_sync_call_function (&kdbus_transport->base,
4307 (DBusTransportSendSyncCallFunction) kdbus_send_sync_call);
4309 _dbus_transport_set_assure_protocol_function (&kdbus_transport->base,
4310 _dbus_message_assure_gvariant,
4311 DBUS_PROTOCOL_VERSION_GVARIANT);
4313 /* These values should probably be tunable or something. */
4314 kdbus_transport->max_bytes_read_per_iteration = MAX_BYTES_PER_ITERATION;
4315 kdbus_transport->max_bytes_written_per_iteration = MAX_BYTES_PER_ITERATION;
4317 if (activator!=NULL)
4319 kdbus_transport->activator = _dbus_strdup (activator);
4320 if (kdbus_transport->activator == NULL)
4324 kdbus_transport->matchmaker = matchmaker_new ();
4326 kdbus_transport->client_serial = 1;
4328 return kdbus_transport;
4331 _dbus_watch_invalidate (kdbus_transport->read_watch);
4332 _dbus_watch_unref (kdbus_transport->read_watch);
4334 _dbus_watch_invalidate (kdbus_transport->write_watch);
4335 _dbus_watch_unref (kdbus_transport->write_watch);
4337 dbus_free (kdbus_transport);
4342 * Connects to kdbus, creates and sets-up transport.
4344 * @param path the path to the bus.
4345 * @param error address where an error can be returned.
4346 * @returns a new transport, or #NULL on failure.
4348 static DBusTransport*
4349 _dbus_transport_new_for_kdbus (const char *path,
4350 const char *activator,
4354 DBusTransportKdbus *transport;
4358 #ifdef DBUS_ENABLE_VERBOSE_MODE
4359 const char *dbgenv = _dbus_getenv ("G_DBUS_DEBUG");
4362 if (!strcmp (dbgenv, "message"))
4364 else if (!strcmp (dbgenv, "all"))
4369 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4371 if (!_dbus_string_init (&address))
4373 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4377 if ((!_dbus_string_append (&address, DBUS_ADDRESS_KDBUS "path=")) || (!_dbus_string_append (&address, path)))
4379 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4383 kdbus = _kdbus_new (path);
4386 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4390 ret = _kdbus_open (kdbus);
4393 dbus_set_error (error,
4394 _dbus_error_from_errno (-ret),
4395 "Failed to open file descriptor: %s: %s",
4397 _dbus_strerror (-ret));
4398 goto failed_0_with_kdbus;
4401 _dbus_verbose ("Successfully connected to kdbus bus %s\n", path);
4403 transport = new_kdbus_transport (kdbus, &address, activator);
4404 if (transport == NULL)
4406 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
4410 _dbus_string_free (&address);
4412 return (DBusTransport*)transport;
4415 _kdbus_close (kdbus);
4416 failed_0_with_kdbus:
4417 _kdbus_free (kdbus);
4419 _dbus_string_free (&address);
4425 * Opens kdbus transport if method from address entry is kdbus
4427 * @param entry the address entry to open
4428 * @param transport_p return location for the opened transport
4429 * @param error place to store error
4430 * @returns result of the attempt as a DBusTransportOpenResult enum
4432 DBusTransportOpenResult
4433 _dbus_transport_open_kdbus (DBusAddressEntry *entry,
4434 DBusTransport **transport_p,
4439 method = dbus_address_entry_get_method (entry);
4440 _dbus_assert (method != NULL);
4442 if (strcmp (method, "kernel") == 0)
4444 const char *path = dbus_address_entry_get_value (entry, "path");
4445 const char *activator = dbus_address_entry_get_value (entry, "activator");
4449 _dbus_set_bad_address (error, "kdbus", "path", NULL);
4450 return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
4453 *transport_p = _dbus_transport_new_for_kdbus (path, activator, error);
4455 if (*transport_p == NULL)
4457 _DBUS_ASSERT_ERROR_IS_SET (error);
4458 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
4462 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4463 return DBUS_TRANSPORT_OPEN_OK;
4468 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4469 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;