1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2013 Samsung Electronics
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Michal Eljasiewicz <m.eljasiewic@samsung.com>
21 * Author: Lukasz Skalski <l.skalski@samsung.com>
26 #include "glib-unix.h"
34 #include <sys/ioctl.h>
38 #ifdef HAVE_SYS_FILIO_H
39 # include <sys/filio.h>
46 #include <glib/gstdio.h>
47 #include <glib/glib-private.h>
49 #include <gio/gunixfdlist.h>
52 #include "gunixfdmessage.h"
54 #define KDBUS_MSG_MAX_SIZE 8192
55 #define KDBUS_TIMEOUT_NS 2000000000LU
56 #define KDBUS_POOL_SIZE (16 * 1024LU * 1024LU)
57 #define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
58 #define KDBUS_ALIGN8_PTR(p) ((void*) (uintptr_t)(p))
60 #define KDBUS_ITEM_HEADER_SIZE G_STRUCT_OFFSET(struct kdbus_item, data)
61 #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
63 #define KDBUS_ITEM_NEXT(item) \
64 (typeof(item))(((guint8 *)item) + KDBUS_ALIGN8((item)->size))
65 #define KDBUS_ITEM_FOREACH(item, head, first) \
66 for (item = (head)->first; \
67 (guint8 *)(item) < (guint8 *)(head) + (head)->size; \
68 item = KDBUS_ITEM_NEXT(item))
69 #define KDBUS_FOREACH(iter, first, _size) \
70 for (iter = (first); \
71 ((guint8 *)(iter) < (guint8 *)(first) + (_size)) && \
72 ((guint8 *)(iter) >= (guint8 *)(first)); \
73 iter = (void*)(((guint8 *)iter) + KDBUS_ALIGN8((iter)->size)))
75 #define g_alloca0(x) memset(g_alloca(x), '\0', (x))
77 struct dbus_fixed_header {
86 #define DBUS_FIXED_HEADER_TYPE ((const GVariantType *) "(yyyyut)")
87 #define DBUS_EXTENDED_HEADER_TYPE ((const GVariantType *) "a{tv}")
88 #define DBUS_MESSAGE_TYPE ((const GVariantType *) "((yyyyut)a{tv}v)")
91 * Macros for SipHash algorithm
94 #define ROTL(x,b) (guint64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
96 #define U32TO8_LE(p, v) \
97 (p)[0] = (guint8)((v) ); (p)[1] = (guint8)((v) >> 8); \
98 (p)[2] = (guint8)((v) >> 16); (p)[3] = (guint8)((v) >> 24);
100 #define U64TO8_LE(p, v) \
101 U32TO8_LE((p), (guint32)((v) )); \
102 U32TO8_LE((p) + 4, (guint32)((v) >> 32));
104 #define U8TO64_LE(p) \
105 (((guint64)((p)[0]) ) | \
106 ((guint64)((p)[1]) << 8) | \
107 ((guint64)((p)[2]) << 16) | \
108 ((guint64)((p)[3]) << 24) | \
109 ((guint64)((p)[4]) << 32) | \
110 ((guint64)((p)[5]) << 40) | \
111 ((guint64)((p)[6]) << 48) | \
112 ((guint64)((p)[7]) << 56))
116 v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
117 v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \
118 v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \
119 v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
126 G_BUS_CREDS_UNIQUE_NAME = 3,
127 G_BUS_CREDS_SELINUX_CONTEXT = 4
128 } GBusCredentialsFlags;
130 typedef GObjectClass GKDBusWorkerClass;
134 GObject parent_instance;
138 GMainContext *context;
147 guint64 attach_flags_send;
148 guint64 attach_flags_recv;
160 GDBusCapabilityFlags capabilities;
161 GDBusWorkerMessageReceivedCallback message_received_callback;
162 GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback;
163 GDBusWorkerDisconnectedCallback disconnected_callback;
167 static gssize _g_kdbus_receive (GKDBusWorker *kdbus,
168 GCancellable *cancellable,
171 G_DEFINE_TYPE (GKDBusWorker, g_kdbus_worker, G_TYPE_OBJECT)
173 /* Hash keys for bloom filters*/
174 const guint8 hash_keys[8][16] =
176 {0xb9,0x66,0x0b,0xf0,0x46,0x70,0x47,0xc1,0x88,0x75,0xc4,0x9c,0x54,0xb9,0xbd,0x15},
177 {0xaa,0xa1,0x54,0xa2,0xe0,0x71,0x4b,0x39,0xbf,0xe1,0xdd,0x2e,0x9f,0xc5,0x4a,0x3b},
178 {0x63,0xfd,0xae,0xbe,0xcd,0x82,0x48,0x12,0xa1,0x6e,0x41,0x26,0xcb,0xfa,0xa0,0xc8},
179 {0x23,0xbe,0x45,0x29,0x32,0xd2,0x46,0x2d,0x82,0x03,0x52,0x28,0xfe,0x37,0x17,0xf5},
180 {0x56,0x3b,0xbf,0xee,0x5a,0x4f,0x43,0x39,0xaf,0xaa,0x94,0x08,0xdf,0xf0,0xfc,0x10},
181 {0x31,0x80,0xc8,0x73,0xc7,0xea,0x46,0xd3,0xaa,0x25,0x75,0x0f,0x9e,0x4c,0x09,0x29},
182 {0x7d,0xf7,0x18,0x4b,0x7b,0xa4,0x44,0xd5,0x85,0x3c,0x06,0xe0,0x65,0x53,0x96,0x6d},
183 {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35}
188 MATCH_ELEMENT_SENDER,
189 MATCH_ELEMENT_INTERFACE,
190 MATCH_ELEMENT_MEMBER,
192 MATCH_ELEMENT_PATH_NAMESPACE,
193 MATCH_ELEMENT_DESTINATION,
194 MATCH_ELEMENT_ARG0NAMESPACE,
195 MATCH_ELEMENT_EAVESDROP,
197 MATCH_ELEMENT_ARGNPATH,
200 /* MatchElement struct */
210 MatchElement *elements;
219 _g_siphash24 (guint8 out[8],
224 /* "somepseudorandomlygeneratedbytes" */
225 guint64 v0 = 0x736f6d6570736575ULL;
226 guint64 v1 = 0x646f72616e646f6dULL;
227 guint64 v2 = 0x6c7967656e657261ULL;
228 guint64 v3 = 0x7465646279746573ULL;
230 guint64 k0 = U8TO64_LE (k);
231 guint64 k1 = U8TO64_LE (k + 8);
233 const guint8 *in = _in;
234 const guint8 *end = in + inlen - (inlen % sizeof(guint64));
235 const int left = inlen & 7;
236 b = ((guint64) inlen) << 56;
242 for (; in != end; in += 8)
253 case 7: b |= ((guint64) in[6]) << 48;
254 case 6: b |= ((guint64) in[5]) << 40;
255 case 5: b |= ((guint64) in[4]) << 32;
256 case 4: b |= ((guint64) in[3]) << 24;
257 case 3: b |= ((guint64) in[2]) << 16;
258 case 2: b |= ((guint64) in[1]) << 8;
259 case 1: b |= ((guint64) in[0]); break;
273 b = v0 ^ v1 ^ v2 ^ v3;
283 is_key (const char *key_start, const char *key_end, char *value)
285 gsize len = strlen (value);
287 if (len != key_end - key_start)
290 return strncmp (key_start, value, len) == 0;
299 parse_key (MatchElement *element, const char *key_start, const char *key_end)
303 if (is_key (key_start, key_end, "type"))
305 element->type = MATCH_ELEMENT_TYPE;
307 else if (is_key (key_start, key_end, "sender"))
309 element->type = MATCH_ELEMENT_SENDER;
311 else if (is_key (key_start, key_end, "interface"))
313 element->type = MATCH_ELEMENT_INTERFACE;
315 else if (is_key (key_start, key_end, "member"))
317 element->type = MATCH_ELEMENT_MEMBER;
319 else if (is_key (key_start, key_end, "path"))
321 element->type = MATCH_ELEMENT_PATH;
323 else if (is_key (key_start, key_end, "path_namespace"))
325 element->type = MATCH_ELEMENT_PATH_NAMESPACE;
327 else if (is_key (key_start, key_end, "destination"))
329 element->type = MATCH_ELEMENT_DESTINATION;
331 else if (is_key (key_start, key_end, "arg0namespace"))
333 element->type = MATCH_ELEMENT_ARG0NAMESPACE;
335 else if (is_key (key_start, key_end, "eavesdrop"))
337 element->type = MATCH_ELEMENT_EAVESDROP;
339 else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
341 const char *digits = key_start + 3;
342 const char *end_digits = digits;
344 while (end_digits < key_end && g_ascii_isdigit (*end_digits))
347 if (end_digits == key_end) /* argN */
349 element->type = MATCH_ELEMENT_ARGN;
350 element->arg = atoi (digits);
352 else if (is_key (end_digits, key_end, "path")) /* argNpath */
354 element->type = MATCH_ELEMENT_ARGNPATH;
355 element->arg = atoi (digits);
372 parse_value (MatchElement *element, const char *s)
377 value = g_string_new ("");
400 g_string_append_c (value, *s);
404 else if (quote_char == '\\')
406 /* \ only counts as an escape if escaping a quote mark */
408 g_string_append_c (value, '\\');
410 g_string_append_c (value, *s);
413 else /* quote_char == ' */
418 g_string_append_c (value, *s);
423 if (quote_char == '\\')
424 g_string_append_c (value, '\\');
425 else if (quote_char == '\'')
427 g_string_free (value, TRUE);
431 element->value = g_string_free (value, FALSE);
441 match_new (const char *str)
446 const char *key_start;
448 MatchElement element;
451 elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
457 memset (&element, 0, sizeof (element));
459 /* Skip initial whitespace */
460 while (*p && g_ascii_isspace (*p))
465 /* Read non-whitespace non-equals chars */
466 while (*p && *p != '=' && !g_ascii_isspace (*p))
471 /* Skip any whitespace after key */
472 while (*p && g_ascii_isspace (*p))
475 if (key_start == key_end)
476 continue; /* Allow trailing whitespace */
482 if (!parse_key (&element, key_start, key_end))
485 p = parse_value (&element, p);
489 g_array_append_val (elements, element);
492 match = g_new0 (Match, 1);
493 match->n_elements = elements->len;
494 match->elements = (MatchElement *)g_array_free (elements, FALSE);
499 for (i = 0; i < elements->len; i++)
500 g_free (g_array_index (elements, MatchElement, i).value);
501 g_array_free (elements, TRUE);
511 match_free (Match *match)
514 for (i = 0; i < match->n_elements; i++)
515 g_free (match->elements[i].value);
516 g_free (match->elements);
526 g_kdbus_worker_finalize (GObject *object)
528 GKDBusWorker *kdbus = G_KDBUS_WORKER (object);
530 if (kdbus->kdbus_buffer != NULL)
531 munmap (kdbus->kdbus_buffer, KDBUS_POOL_SIZE);
533 kdbus->kdbus_buffer = NULL;
535 if (kdbus->fd != -1 && !kdbus->closed)
536 _g_kdbus_close (kdbus);
538 G_OBJECT_CLASS (g_kdbus_worker_parent_class)->finalize (object);
542 g_kdbus_worker_class_init (GKDBusWorkerClass *class)
544 class->finalize = g_kdbus_worker_finalize;
548 g_kdbus_worker_init (GKDBusWorker *kdbus)
552 kdbus->unique_id = -1;
553 kdbus->unique_name = NULL;
555 kdbus->kdbus_buffer = NULL;
557 kdbus->flags = KDBUS_HELLO_ACCEPT_FD;
558 kdbus->attach_flags_send = _KDBUS_ATTACH_ALL;
559 kdbus->attach_flags_recv = _KDBUS_ATTACH_ALL;
563 kdbus_ready (gint fd,
564 GIOCondition condition,
567 GKDBusWorker *kdbus = user_data;
568 GError *error = NULL;
570 _g_kdbus_receive (kdbus, NULL, &error);
571 g_assert_no_error (error);
573 return G_SOURCE_CONTINUE;
577 _g_kdbus_open (GKDBusWorker *worker,
578 const gchar *address,
581 g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
583 worker->fd = open(address, O_RDWR|O_NOCTTY|O_CLOEXEC);
586 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Can't open kdbus endpoint"));
590 worker->closed = FALSE;
601 g_kdbus_free_data (GKDBusWorker *kdbus,
604 struct kdbus_cmd_free cmd = {
611 ret = ioctl (kdbus->fd, KDBUS_CMD_FREE, &cmd);
620 * g_kdbus_translate_nameowner_flags:
624 g_kdbus_translate_nameowner_flags (GBusNameOwnerFlags flags,
625 guint64 *kdbus_flags)
631 if (flags & G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT)
632 new_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
634 if (flags & G_BUS_NAME_OWNER_FLAGS_REPLACE)
635 new_flags |= KDBUS_NAME_REPLACE_EXISTING;
637 if (!(flags & G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE))
638 new_flags |= KDBUS_NAME_QUEUE;
640 *kdbus_flags = new_flags;
649 _g_kdbus_close (GKDBusWorker *kdbus)
651 g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
656 g_source_destroy (kdbus->source);
659 g_main_context_unref (kdbus->context);
660 kdbus->context = NULL;
665 kdbus->closed = TRUE;
669 * _g_kdbus_is_closed:
673 _g_kdbus_is_closed (GKDBusWorker *kdbus)
675 g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
677 return kdbus->closed;
686 _g_kdbus_Hello (GKDBusWorker *worker,
689 struct kdbus_cmd_hello *cmd;
690 struct kdbus_bloom_parameter *bloom;
691 struct kdbus_item *item, *items;
694 size_t size, conn_name_size;
696 conn_name = "gdbus-kdbus";
697 conn_name_size = strlen (conn_name);
699 size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_hello, items)) +
700 KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1);
702 cmd = g_alloca0 (size);
703 cmd->flags = worker->flags;
704 cmd->attach_flags_send = worker->attach_flags_send;
705 cmd->attach_flags_recv = worker->attach_flags_recv;
707 cmd->pool_size = KDBUS_POOL_SIZE;
710 item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1;
711 item->type = KDBUS_ITEM_CONN_DESCRIPTION;
712 memcpy (item->str, conn_name, conn_name_size+1);
713 item = KDBUS_ITEM_NEXT (item);
715 if (ioctl(worker->fd, KDBUS_CMD_HELLO, cmd))
717 g_set_error (error, G_IO_ERROR,
718 g_io_error_from_errno (errno),
719 _("Failed to send HELLO: %s"),
724 worker->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, worker->fd, 0);
725 if (worker->kdbus_buffer == MAP_FAILED)
727 g_set_error (error, G_IO_ERROR,
728 g_io_error_from_errno (errno),
734 if (cmd->bus_flags > 0xFFFFFFFFULL)
736 g_set_error_literal (error,
739 _("Incompatible HELLO flags"));
743 memcpy (worker->bus_id, cmd->id128, 16);
745 worker->unique_id = cmd->id;
746 asprintf(&worker->unique_name, ":1.%llu", (unsigned long long) cmd->id);
748 /* read bloom filters parameters */
750 items = (void*)(worker->kdbus_buffer + cmd->offset);
751 KDBUS_FOREACH(item, items, cmd->items_size)
755 case KDBUS_ITEM_BLOOM_PARAMETER:
756 bloom = &item->bloom_parameter;
763 worker->bloom_size = (gsize) bloom->size;
764 worker->bloom_n_hash = (guint) bloom->n_hash;
768 g_set_error_literal (error,
771 _("Can't read bloom filter parameters"));
776 return g_variant_new ("(s)", worker->unique_name);
781 * _g_kdbus_RequestName:
785 _g_kdbus_RequestName (GKDBusWorker *worker,
787 GBusNameOwnerFlags flags,
791 struct kdbus_cmd *cmd;
796 status = G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER;
798 if (!g_dbus_is_name (name))
802 G_DBUS_ERROR_INVALID_ARGS,
803 "Given bus name \"%s\" is not valid", name);
811 G_DBUS_ERROR_INVALID_ARGS,
812 "Cannot acquire a service starting with ':' such as \"%s\"", name);
816 g_kdbus_translate_nameowner_flags (flags, &kdbus_flags);
818 len = strlen(name) + 1;
819 size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
820 cmd = g_alloca0 (size);
822 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
823 cmd->items[0].type = KDBUS_ITEM_NAME;
824 cmd->flags = kdbus_flags;
825 memcpy (cmd->items[0].str, name, len);
827 ret = ioctl(worker->fd, KDBUS_CMD_NAME_ACQUIRE, cmd);
831 status = G_BUS_REQUEST_NAME_FLAGS_EXISTS;
832 else if (errno == EALREADY)
833 status = G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER;
836 g_set_error (error, G_IO_ERROR,
837 g_io_error_from_errno (errno),
838 _("Error while acquiring name: %s"),
844 if (cmd->return_flags & KDBUS_NAME_IN_QUEUE)
845 status = G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE;
847 result = g_variant_new ("(u)", status);
854 * _g_kdbus_ReleaseName:
858 _g_kdbus_ReleaseName (GKDBusWorker *worker,
863 struct kdbus_cmd *cmd;
867 status = G_BUS_RELEASE_NAME_FLAGS_RELEASED;
869 if (!g_dbus_is_name (name))
873 G_DBUS_ERROR_INVALID_ARGS,
874 "Given bus name \"%s\" is not valid", name);
882 G_DBUS_ERROR_INVALID_ARGS,
883 "Cannot release a service starting with ':' such as \"%s\"", name);
887 len = strlen(name) + 1;
888 size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
889 cmd = g_alloca0 (size);
891 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
892 cmd->items[0].type = KDBUS_ITEM_NAME;
893 memcpy (cmd->items[0].str, name, len);
895 ret = ioctl(worker->fd, KDBUS_CMD_NAME_RELEASE, cmd);
899 status = G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT;
900 else if (errno == EADDRINUSE)
901 status = G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER;
904 g_set_error (error, G_IO_ERROR,
905 g_io_error_from_errno (errno),
906 _("Error while releasing name: %s"),
912 result = g_variant_new ("(u)", status);
923 _g_kdbus_GetBusId (GKDBusWorker *worker,
930 result_str = g_string_new (NULL);
932 for (cnt=0; cnt<16; cnt++)
933 g_string_append_printf (result_str, "%02x", worker->bus_id[cnt]);
935 result = g_variant_new ("(s)", result_str->str);
936 g_string_free (result_str, TRUE);
943 * _g_kdbus_GetListNames:
947 _g_kdbus_GetListNames (GKDBusWorker *worker,
948 guint list_name_type,
952 GVariantBuilder *builder;
953 struct kdbus_info *name_list, *name;
954 struct kdbus_cmd_list cmd = {
964 cmd.flags = KDBUS_LIST_ACTIVATORS; /* ListActivatableNames */
966 cmd.flags = KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES; /* ListNames */
968 ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
974 _("Error listing names"));
978 name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
979 builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
981 KDBUS_FOREACH(name, name_list, cmd.list_size)
983 struct kdbus_item *item;
984 const gchar *item_name = "";
986 if ((cmd.flags & KDBUS_LIST_UNIQUE) && name->id != prev_id)
988 GString *unique_name;
990 unique_name = g_string_new (NULL);
991 g_string_printf (unique_name, ":1.%llu", name->id);
992 g_variant_builder_add (builder, "s", unique_name->str);
993 g_string_free (unique_name,TRUE);
997 KDBUS_ITEM_FOREACH(item, name, items)
998 if (item->type == KDBUS_ITEM_OWNED_NAME)
999 item_name = item->name.name;
1001 if (g_dbus_is_name (item_name))
1002 g_variant_builder_add (builder, "s", item_name);
1005 result = g_variant_new ("(as)", builder);
1006 g_variant_builder_unref (builder);
1008 g_kdbus_free_data (worker, cmd.offset);
1014 * _g_kdbus_NameHasOwner_internal:
1018 g_kdbus_NameHasOwner_internal (GKDBusWorker *worker,
1022 struct kdbus_cmd_info *cmd;
1026 if (g_dbus_is_unique_name(name))
1028 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
1029 cmd = g_alloca0 (size);
1030 cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1034 len = strlen(name) + 1;
1035 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
1036 cmd = g_alloca0 (size);
1037 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1038 cmd->items[0].type = KDBUS_ITEM_NAME;
1039 memcpy (cmd->items[0].str, name, len);
1043 ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
1044 g_kdbus_free_data (worker, cmd->offset);
1054 * _g_kdbus_GetListQueuedOwners:
1058 _g_kdbus_GetListQueuedOwners (GKDBusWorker *worker,
1063 GVariantBuilder *builder;
1064 GString *unique_name;
1067 struct kdbus_info *name_list, *kname;
1068 struct kdbus_cmd_list cmd = {
1069 .size = sizeof(cmd),
1070 .flags = KDBUS_LIST_QUEUED
1073 if (!g_dbus_is_name (name))
1077 G_DBUS_ERROR_INVALID_ARGS,
1078 "Given bus name \"%s\" is not valid", name);
1082 if (!g_kdbus_NameHasOwner_internal (worker, name, error))
1086 G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1087 "Could not get owner of name '%s': no such name", name);
1091 ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
1096 G_DBUS_ERROR_FAILED,
1097 _("Error listing names"));
1101 name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
1103 unique_name = g_string_new (NULL);
1104 builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
1105 KDBUS_FOREACH(kname, name_list, cmd.list_size)
1107 struct kdbus_item *item;
1108 const char *item_name = "";
1110 KDBUS_ITEM_FOREACH(item, kname, items)
1111 if (item->type == KDBUS_ITEM_NAME)
1112 item_name = item->str;
1114 if (strcmp(item_name, name))
1117 g_string_printf (unique_name, ":1.%llu", kname->id);
1118 g_variant_builder_add (builder, "s", item_name);
1121 result = g_variant_new ("(as)", builder);
1122 g_variant_builder_unref (builder);
1123 g_string_free (unique_name,TRUE);
1125 g_kdbus_free_data (worker, cmd.offset);
1131 * g_kdbus_GetConnInfo_internal:
1135 g_kdbus_GetConnInfo_internal (GKDBusWorker *worker,
1142 struct kdbus_cmd_info *cmd;
1143 struct kdbus_info *conn_info;
1144 struct kdbus_item *item;
1150 if (!g_dbus_is_name (name))
1154 G_DBUS_ERROR_INVALID_ARGS,
1155 "Given bus name \"%s\" is not valid", name);
1159 if (!g_kdbus_NameHasOwner_internal (worker, name, error))
1163 G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1164 "Could not get owner of name '%s': no such name", name);
1168 if (g_dbus_is_unique_name(name))
1170 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
1171 cmd = g_alloca0 (size);
1172 cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1176 len = strlen(name) + 1;
1177 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
1178 cmd = g_alloca0 (size);
1179 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1180 cmd->items[0].type = KDBUS_ITEM_NAME;
1181 memcpy (cmd->items[0].str, name, len);
1184 cmd->attach_flags = _KDBUS_ATTACH_ALL;
1187 ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
1192 G_DBUS_ERROR_FAILED,
1193 _("Could not get connection info"));
1197 conn_info = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd->offset);
1200 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
1204 if (flag == G_BUS_CREDS_UNIQUE_NAME)
1206 GString *unique_name;
1208 unique_name = g_string_new (NULL);
1209 g_string_printf (unique_name, ":1.%llu", (unsigned long long) conn_info->id);
1210 result = g_variant_new ("(s)", unique_name->str);
1211 g_string_free (unique_name,TRUE);
1215 KDBUS_ITEM_FOREACH(item, conn_info, items)
1219 case KDBUS_ITEM_PIDS:
1221 if (flag == G_BUS_CREDS_PID)
1223 guint pid = item->pids.pid;
1224 result = g_variant_new ("(u)", pid);
1228 case KDBUS_ITEM_CREDS:
1230 if (flag == G_BUS_CREDS_UID)
1232 guint uid = item->creds.uid;
1233 result = g_variant_new ("(u)", uid);
1237 case KDBUS_ITEM_SECLABEL:
1238 case KDBUS_ITEM_PID_COMM:
1239 case KDBUS_ITEM_TID_COMM:
1240 case KDBUS_ITEM_EXE:
1241 case KDBUS_ITEM_CMDLINE:
1242 case KDBUS_ITEM_CGROUP:
1243 case KDBUS_ITEM_CAPS:
1244 case KDBUS_ITEM_AUDIT:
1245 case KDBUS_ITEM_CONN_DESCRIPTION:
1246 case KDBUS_ITEM_AUXGROUPS:
1247 case KDBUS_ITEM_OWNED_NAME:
1253 g_kdbus_free_data (worker, cmd->offset);
1259 * _g_kdbus_GetNameOwner:
1263 _g_kdbus_GetNameOwner (GKDBusWorker *worker,
1267 return g_kdbus_GetConnInfo_internal (worker,
1269 G_BUS_CREDS_UNIQUE_NAME,
1275 * _g_kdbus_GetConnectionUnixProcessID:
1279 _g_kdbus_GetConnectionUnixProcessID (GKDBusWorker *worker,
1283 return g_kdbus_GetConnInfo_internal (worker,
1291 * _g_kdbus_GetConnectionUnixUser:
1295 _g_kdbus_GetConnectionUnixUser (GKDBusWorker *worker,
1299 return g_kdbus_GetConnInfo_internal (worker,
1307 * g_kdbus_bloom_add_data:
1308 * Based on bus-bloom.c from systemd
1309 * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1312 g_kdbus_bloom_add_data (GKDBusWorker *worker,
1313 guint64 bloom_data [],
1319 guint bytes_num = 0;
1321 guint hash_index = 0;
1326 bit_num = worker->bloom_size * 8;
1329 bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8;
1331 for (cnt_1 = 0; cnt_1 < (worker->bloom_n_hash); cnt_1++)
1333 for (cnt_2 = 0, hash_index = 0; cnt_2 < bytes_num; cnt_2++)
1337 _g_siphash24(hash, data, n, hash_keys[hash_index++]);
1341 p = (p << 8ULL) | (guint64) hash[8 - c];
1346 bloom_data[p >> 6] |= 1ULL << (p & 63);
1352 * g_kdbus_bloom_add_pair:
1356 g_kdbus_bloom_add_pair (GKDBusWorker *worker,
1357 guint64 bloom_data [],
1358 const gchar *parameter,
1364 size = strlen(parameter) + strlen(value) + 1;
1368 strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1369 g_kdbus_bloom_add_data(worker, bloom_data, buf, size);
1374 * g_kdbus_bloom_add_prefixes:
1378 g_kdbus_bloom_add_prefixes (GKDBusWorker *worker,
1379 guint64 bloom_data [],
1380 const gchar *parameter,
1387 size = strlen(parameter) + strlen(value) + 1;
1391 strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1396 last_sep = strrchr(buf, separator);
1397 if (!last_sep || last_sep == buf)
1401 g_kdbus_bloom_add_data(worker, bloom_data, buf, last_sep-buf);
1407 * _g_kdbus_AddMatch:
1411 _g_kdbus_AddMatch (GKDBusWorker *worker,
1412 const gchar *match_rule,
1416 MatchElement *element;
1417 const gchar *sender_name;
1418 gsize sender_len, size;
1419 struct kdbus_cmd_match *cmd;
1420 struct kdbus_item *item;
1426 if (match_rule[0] == '-')
1429 match = match_new (match_rule);
1437 src_id = KDBUS_MATCH_ID_ANY;
1439 bloom = g_alloca0 (worker->bloom_size);
1440 size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_match, items));
1441 match = match_new (match_rule);
1443 for (cnt = 0; cnt < match->n_elements; cnt++)
1445 element = &match->elements[cnt];
1446 switch (element->type)
1448 case MATCH_ELEMENT_SENDER:
1449 if (g_dbus_is_unique_name(element->value))
1451 src_id = g_ascii_strtoull ((element->value)+3, NULL, 10);
1452 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id));
1454 else if (g_dbus_is_name (element->value))
1456 sender_name = element->value;
1457 sender_len = strlen(element->value) + 1;
1458 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len);
1462 g_critical ("Error while adding a match");
1468 case MATCH_ELEMENT_TYPE:
1469 g_kdbus_bloom_add_pair (worker, bloom, "message-type", element->value);
1472 case MATCH_ELEMENT_INTERFACE:
1473 g_kdbus_bloom_add_pair (worker, bloom, "interface", element->value);
1476 case MATCH_ELEMENT_MEMBER:
1477 g_kdbus_bloom_add_pair (worker, bloom, "member", element->value);
1480 case MATCH_ELEMENT_PATH:
1481 g_kdbus_bloom_add_pair (worker, bloom, "path", element->value);
1484 case MATCH_ELEMENT_PATH_NAMESPACE:
1485 if (g_strcmp0 (element->value, "/"))
1486 g_kdbus_bloom_add_pair (worker, bloom, "path-slash-prefix", element->value);
1489 case MATCH_ELEMENT_ARGN:
1490 asprintf (&type, "arg%u", element->arg);
1491 g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1495 case MATCH_ELEMENT_ARGNPATH:
1496 asprintf (&type, "arg%u-slash-prefix", element->arg);
1497 g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1501 case MATCH_ELEMENT_ARG0NAMESPACE:
1502 g_kdbus_bloom_add_pair (worker, bloom, "arg0-dot-prefix", element->value);
1505 case MATCH_ELEMENT_DESTINATION:
1506 case MATCH_ELEMENT_EAVESDROP:
1511 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, data64) + worker->bloom_size);
1512 cmd = g_alloca0 (size);
1514 cmd->cookie = cookie;
1517 item->size = G_STRUCT_OFFSET(struct kdbus_item, data64) + worker->bloom_size;
1518 item->type = KDBUS_ITEM_BLOOM_MASK;
1519 memcpy(item->data64, bloom, worker->bloom_size);
1520 item = KDBUS_ITEM_NEXT(item);
1522 if (src_id != KDBUS_MATCH_ID_ANY)
1524 item->size = G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id);
1525 item->type = KDBUS_ITEM_ID;
1527 item = KDBUS_ITEM_NEXT(item);
1532 item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len;
1533 item->type = KDBUS_ITEM_NAME;
1534 memcpy (item->str, sender_name, sender_len);
1537 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1539 g_critical ("Error while adding a match: %d", (int) errno);
1546 * _g_kdbus_RemoveMatch:
1550 _g_kdbus_RemoveMatch (GKDBusWorker *worker,
1553 struct kdbus_cmd_match cmd = {
1554 .size = sizeof(cmd),
1559 g_print ("Unsubscribe match entry with cookie - %d\n", (int)cookie);
1560 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_REMOVE, &cmd);
1562 g_warning ("Error while removing a match: %d\n", errno);
1567 * _g_kdbus_subscribe_name_owner_changed_internal:
1571 _g_kdbus_subscribe_name_owner_changed_internal (GKDBusWorker *worker,
1573 const gchar *old_name,
1574 const gchar *new_name,
1577 struct kdbus_item *item;
1578 struct kdbus_cmd_match *cmd;
1582 guint64 new_id = KDBUS_MATCH_ID_ANY;
1585 len = strlen(name) + 1;
1589 size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1590 G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1591 G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1593 cmd = g_alloca0 (size);
1595 cmd->cookie = cookie;
1598 if (old_name == NULL)
1600 old_id = KDBUS_MATCH_ID_ANY;
1604 if (g_dbus_is_unique_name(old_name))
1605 old_id = strtoull (old_name + 3, NULL, 10);
1610 if (new_name == NULL)
1612 new_id = KDBUS_MATCH_ID_ANY;
1616 if (g_dbus_is_unique_name(new_name))
1617 new_id = strtoull (new_name + 3, NULL, 10);
1622 cmd = g_alloca0 (size);
1624 cmd->cookie = cookie;
1627 /* KDBUS_ITEM_NAME_CHANGE */
1628 item->type = KDBUS_ITEM_NAME_CHANGE;
1629 item->name_change.old_id.id = old_id;
1630 item->name_change.new_id.id = new_id;
1633 memcpy(item->name_change.name, name, len);
1635 item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1636 G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1637 item = KDBUS_ITEM_NEXT(item);
1639 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1641 g_warning ("ERROR - %d\n", (int) errno);
1646 * _g_kdbus_subscribe_name_acquired:
1650 _g_kdbus_subscribe_name_acquired (GKDBusWorker *worker,
1654 struct kdbus_item *item;
1655 struct kdbus_cmd_match *cmd;
1659 g_print ("Subscribe 'NameAcquired': name - %s ; cookie - %d\n", name, (int)cookie);
1661 len = strlen(name) + 1;
1665 size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1666 G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1667 G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1669 cmd = g_alloca0 (size);
1671 cmd->cookie = cookie;
1674 /* KDBUS_ITEM_NAME_ADD */
1675 item->type = KDBUS_ITEM_NAME_ADD;
1676 item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
1677 item->name_change.new_id.id = worker->unique_id;
1680 memcpy(item->name_change.name, name, len);
1682 item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1683 G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1684 item = KDBUS_ITEM_NEXT(item);
1686 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1688 g_warning ("ERROR - %d\n", (int) errno);
1690 _g_kdbus_subscribe_name_owner_changed_internal (worker, name, NULL, worker->unique_name, cookie);
1695 * _g_kdbus_subscribe_name_lost:
1699 _g_kdbus_subscribe_name_lost (GKDBusWorker *worker,
1703 struct kdbus_item *item;
1704 struct kdbus_cmd_match *cmd;
1708 g_print ("Subscribe 'NameLost': name - %s ; cookie - %d\n", name, (int)cookie);
1710 len = strlen(name) + 1;
1714 size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1715 G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1716 G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1718 cmd = g_alloca0 (size);
1720 cmd->cookie = cookie;
1723 /* KDBUS_ITEM_NAME_REMOVE */
1724 item->type = KDBUS_ITEM_NAME_REMOVE;
1725 item->name_change.old_id.id = worker->unique_id;
1726 item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
1729 memcpy(item->name_change.name, name, len);
1731 item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1732 G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1733 item = KDBUS_ITEM_NEXT(item);
1735 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd);
1737 g_warning ("ERROR - %d\n", (int) errno);
1739 _g_kdbus_subscribe_name_owner_changed_internal (worker, name, worker->unique_name, NULL, cookie);
1748 _g_kdbus_subscribe_name_owner_changed (GKDBusWorker *worker,
1752 g_print ("NameOwnerChanged subscription\n");
1757 * g_kdbus_setup_bloom:
1758 * Based on bus-bloom.c from systemd
1759 * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1762 g_kdbus_setup_bloom (GKDBusWorker *worker,
1763 GDBusMessage *dbus_msg,
1764 struct kdbus_bloom_filter *bloom_filter)
1768 const gchar *message_type;
1769 const gchar *interface;
1770 const gchar *member;
1775 body = g_dbus_message_get_body (dbus_msg);
1776 message_type = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, g_dbus_message_get_message_type (dbus_msg));
1777 interface = g_dbus_message_get_interface (dbus_msg);
1778 member = g_dbus_message_get_member (dbus_msg);
1779 path = g_dbus_message_get_path (dbus_msg);
1781 bloom_data = bloom_filter->data;
1782 memset (bloom_data, 0, worker->bloom_size);
1783 bloom_filter->generation = 0;
1785 g_kdbus_bloom_add_pair(worker, bloom_data, "message-type", message_type);
1788 g_kdbus_bloom_add_pair(worker, bloom_data, "interface", interface);
1791 g_kdbus_bloom_add_pair(worker, bloom_data, "member", member);
1795 g_kdbus_bloom_add_pair(worker, bloom_data, "path", path);
1796 g_kdbus_bloom_add_pair(worker, bloom_data, "path-slash-prefix", path);
1797 g_kdbus_bloom_add_prefixes(worker, bloom_data, "path-slash-prefix", path, '/');
1802 const GVariantType *body_type;
1803 const GVariantType *arg_type;
1806 body_type = g_variant_get_type (body);
1808 for (arg_type = g_variant_type_first (body_type), cnt = 0;
1810 arg_type = g_variant_type_next (arg_type), cnt++)
1812 gchar type_char = g_variant_type_peek_string (arg_type)[0];
1813 gchar buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1818 if (type_char != 's' && type_char != 'o')
1819 /* XXX: kdbus docs say "stop after first non-string" but I
1820 * think they're wrong (vs. dbus-1 compat)...
1824 child = g_variant_get_child_value (body, cnt);
1825 str = g_variant_get_string (child, NULL);
1827 e = stpcpy(buf, "arg");
1829 *(e++) = '0' + (char) cnt;
1832 *(e++) = '0' + (char) (cnt / 10);
1833 *(e++) = '0' + (char) (cnt % 10);
1836 /* We add this one for both strings and object paths */
1837 strcpy(e, "-slash-prefix");
1838 g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '/');
1840 /* But the others are only for strings */
1841 if (type_char == 's')
1843 strcpy(e, "-dot-prefix");
1844 g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '.');
1847 g_kdbus_bloom_add_pair(worker, bloom_data, buf, str);
1850 g_variant_unref (child);
1861 g_kdbus_translate_id_change (GKDBusWorker *worker,
1862 struct kdbus_item *item)
1864 g_error ("TODO: translate_id_change\n");
1873 g_kdbus_translate_name_change (GKDBusWorker *worker,
1874 struct kdbus_item *item)
1876 GDBusMessage *signal_message;
1878 signal_message = NULL;
1881 if ((item->type == KDBUS_ITEM_NAME_ADD) ||
1882 (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.new_id.id == worker->unique_id)))
1884 signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
1885 "org.freedesktop.DBus",
1888 g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
1889 g_dbus_message_set_body (signal_message,
1890 g_variant_new ("(s)", item->name_change.name));
1892 (* worker->message_received_callback) (signal_message, worker->user_data);
1893 g_object_unref (signal_message);
1897 if ((item->type == KDBUS_ITEM_NAME_REMOVE) ||
1898 (item->type == KDBUS_ITEM_NAME_CHANGE && ((guint64)item->name_change.old_id.id == worker->unique_id)))
1900 GDBusMessage *signal_message;
1902 signal_message = g_dbus_message_new_signal ("/org/freedesktop/DBus",
1903 "org.freedesktop.DBus",
1906 g_dbus_message_set_sender (signal_message, "org.freedesktop.DBus");
1907 g_dbus_message_set_body (signal_message,
1908 g_variant_new ("(s)", item->name_change.name));
1910 (* worker->message_received_callback) (signal_message, worker->user_data);
1911 g_object_unref (signal_message);
1914 /* NameOwnerChanged */
1924 g_kdbus_translate_kernel_reply (GKDBusWorker *worker,
1925 struct kdbus_item *item)
1927 g_error ("TODO: translate_kernel_reply\n");
1932 * g_kdbus_decode_kernel_msg:
1936 g_kdbus_decode_kernel_msg (GKDBusWorker *worker,
1937 struct kdbus_msg *msg)
1939 struct kdbus_item *item = NULL;
1941 KDBUS_ITEM_FOREACH(item, msg, items)
1945 case KDBUS_ITEM_ID_ADD:
1946 case KDBUS_ITEM_ID_REMOVE:
1947 g_kdbus_translate_id_change (worker, item);
1950 case KDBUS_ITEM_NAME_ADD:
1951 case KDBUS_ITEM_NAME_REMOVE:
1952 case KDBUS_ITEM_NAME_CHANGE:
1953 g_kdbus_translate_name_change (worker, item);
1956 case KDBUS_ITEM_REPLY_TIMEOUT:
1957 case KDBUS_ITEM_REPLY_DEAD:
1958 g_kdbus_translate_kernel_reply (worker, item);
1961 case KDBUS_ITEM_TIMESTAMP:
1965 g_warning ("Unknown field in kernel message - %lld", item->type);
1972 * g_kdbus_decode_dbus_msg:
1975 static GDBusMessage *
1976 g_kdbus_decode_dbus_msg (GKDBusWorker *worker,
1977 struct kdbus_msg *msg)
1979 GDBusMessage *message;
1980 struct kdbus_item *item;
1981 gssize data_size = 0;
1982 GArray *body_vectors;
1988 GVariantIter *fields_iter;
1989 guint8 endianness, type, flags, version;
1995 message = g_dbus_message_new ();
1997 body_vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
1999 tmp = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) msg->src_id);
2000 g_dbus_message_set_sender (message, tmp);
2006 KDBUS_ITEM_FOREACH(item, msg, items)
2008 if (item->size <= KDBUS_ITEM_HEADER_SIZE)
2009 g_error("[KDBUS] %llu bytes - invalid data record\n", item->size);
2011 data_size = item->size - KDBUS_ITEM_HEADER_SIZE;
2015 /* KDBUS_ITEM_DST_NAME */
2016 case KDBUS_ITEM_DST_NAME:
2017 /* Classic D-Bus doesn't make this known to the receiver, so
2018 * we don't do it here either (for compatibility with the
2023 /* KDBUS_ITEM_PALOAD_OFF */
2024 case KDBUS_ITEM_PAYLOAD_OFF:
2026 GVariantVector vector;
2029 /* We want to make sure the bytes are aligned the same as
2030 * they would be if they appeared in a contiguously
2031 * allocated chunk of aligned memory.
2033 * We decide what the alignment 'should' be by consulting
2034 * body_size, which has been tracking the total size of the
2035 * message up to this point.
2037 * We then play around with the pointer by removing as many
2038 * bytes as required to get it to the proper alignment (and
2039 * copy extra bytes accordingly). This means that we will
2040 * grab some extra data in the 'bytes', but it won't be
2041 * shared with GVariant (which means there is no chance of
2042 * it being accidentally retransmitted).
2044 * The kernel does the same thing, so make sure we get the
2045 * expected result. Because of the kernel doing the same,
2046 * the result is that we will always be rounding-down to a
2047 * multiple of 8 for the pointer, which means that the
2048 * pointer will always be valid, assuming the original
2051 * We could fix this with a new GBytes constructor that took
2052 * 'flavour' as a parameter, but it's not worth it...
2054 flavour = body_size & 7;
2055 g_assert ((item->vec.offset & 7) == flavour);
2057 vector.gbytes = g_bytes_new (((guchar *) msg) + item->vec.offset - flavour, item->vec.size + flavour);
2058 vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL);
2059 vector.data.pointer += flavour;
2060 vector.size = item->vec.size;
2062 g_array_append_val (body_vectors, vector);
2063 body_size += vector.size;
2067 /* KDBUS_ITEM_PAYLOAD_MEMFD */
2068 case KDBUS_ITEM_PAYLOAD_MEMFD:
2070 GVariantVector vector;
2074 vector.gbytes = g_bytes_new_take_zero_copy_fd (item->memfd.fd);
2075 data = g_bytes_get_data (vector.gbytes, &size);
2077 g_assert (item->memfd.start + item->memfd.size <= size);
2079 vector.data.pointer = data + item->memfd.start;
2080 vector.size = item->memfd.size;
2082 g_array_append_val (body_vectors, vector);
2083 body_size += vector.size;
2087 /* KDBUS_ITEM_FDS */
2088 case KDBUS_ITEM_FDS:
2090 GUnixFDList *fd_list;
2092 fd_list = g_unix_fd_list_new_from_array (item->fds, data_size / sizeof (int));
2093 g_dbus_message_set_unix_fd_list (message, fd_list);
2094 g_object_unref (fd_list);
2098 /* All of the following items, like CMDLINE,
2099 CGROUP, etc. need some GDBUS API extensions and
2100 should be implemented in the future */
2101 case KDBUS_ITEM_TIMESTAMP:
2103 /* g_print ("time: seq %llu mon %llu real %llu\n",
2104 item->timestamp.seqnum, item->timestamp.monotonic_ns, item->timestamp.realtime_ns); */
2106 //g_dbus_message_set_timestamp (message, item->timestamp.monotonic_ns / 1000);
2107 //g_dbus_message_set_serial (message, item->timestamp.seqnum);
2111 case KDBUS_ITEM_CREDS:
2113 /* g_print ("creds: u%llu eu %llu su%llu fsu%llu g%llu eg%llu sg%llu fsg%llu\n",
2114 item->creds.uid, item->creds.euid, item->creds.suid, item->creds.fsuid,
2115 item->creds.gid, item->creds.egid, item->creds.sgid, item->creds.fsgid); */
2119 case KDBUS_ITEM_PIDS:
2120 case KDBUS_ITEM_PID_COMM:
2121 case KDBUS_ITEM_TID_COMM:
2122 case KDBUS_ITEM_EXE:
2123 case KDBUS_ITEM_CMDLINE:
2124 case KDBUS_ITEM_CGROUP:
2125 case KDBUS_ITEM_AUDIT:
2126 case KDBUS_ITEM_CAPS:
2127 case KDBUS_ITEM_SECLABEL:
2128 case KDBUS_ITEM_CONN_DESCRIPTION:
2129 case KDBUS_ITEM_AUXGROUPS:
2130 case KDBUS_ITEM_OWNED_NAME:
2131 case KDBUS_ITEM_NAME:
2132 //g_print ("unhandled %04x\n", (int) item->type);
2136 g_error ("[KDBUS] DBUS_PAYLOAD: Unknown filed - %lld", item->type);
2141 body = GLIB_PRIVATE_CALL(g_variant_from_vectors) (G_VARIANT_TYPE ("((yyyyuta{tv})v)"),
2142 (GVariantVector *) body_vectors->data,
2143 body_vectors->len, body_size, FALSE);
2146 for (i = 0; i < body_vectors->len; i++)
2147 g_bytes_unref (g_array_index (body_vectors, GVariantVector, i).gbytes);
2149 g_array_free (body_vectors, TRUE);
2151 parts[0] = g_variant_get_child_value (body, 0);
2152 parts[1] = g_variant_get_child_value (body, 1);
2153 g_variant_unref (body);
2155 g_variant_get (parts[0], "(yyyyuta{tv})", &endianness, &type, &flags, &version, NULL, &serial, &fields_iter);
2156 g_variant_unref (parts[0]);
2158 while (g_variant_iter_loop (fields_iter, "{tv}", &key, &value))
2159 g_dbus_message_set_header (message, key, value);
2161 g_dbus_message_set_flags (message, flags);
2162 g_dbus_message_set_serial (message, serial);
2163 g_dbus_message_set_message_type (message, type);
2165 //if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE) != NULL)
2167 body = g_variant_get_variant (parts[1]);
2168 g_dbus_message_set_body (message, body);
2169 g_variant_unref (body);
2171 g_variant_unref (parts[1]);
2173 //g_print ("Received:\n%s\n", g_dbus_message_print (message, 2));
2175 (* worker->message_received_callback) (message, worker->user_data);
2177 g_object_unref (message);
2188 _g_kdbus_receive (GKDBusWorker *kdbus,
2189 GCancellable *cancellable,
2192 struct kdbus_cmd_recv recv;
2193 struct kdbus_msg *msg;
2195 memset (&recv, 0, sizeof recv);
2196 recv.size = sizeof (recv);
2198 if (g_cancellable_set_error_if_cancelled (cancellable, error))
2202 if (ioctl(kdbus->fd, KDBUS_CMD_RECV, &recv) < 0)
2207 if (errno == EAGAIN)
2210 g_warning ("in holding pattern over %d %d\n", kdbus->fd, errno);
2214 g_set_error (error, G_IO_ERROR,
2215 g_io_error_from_errno (errno),
2216 _("Error while receiving message: %s"),
2217 g_strerror (errno));
2221 msg = (struct kdbus_msg *)((guint8 *)kdbus->kdbus_buffer + recv.msg.offset);
2223 if (msg->payload_type == KDBUS_PAYLOAD_DBUS)
2224 g_kdbus_decode_dbus_msg (kdbus, msg);
2225 else if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
2226 g_kdbus_decode_kernel_msg (kdbus, msg);
2231 G_DBUS_ERROR_FAILED,
2232 _("Received unknown payload type"));
2236 g_kdbus_free_data (kdbus, recv.msg.offset);
2242 g_kdbus_msg_append_item (struct kdbus_msg *msg,
2247 struct kdbus_item *item;
2250 item_size = size + G_STRUCT_OFFSET(struct kdbus_item, data);
2252 if (msg->size + item_size > KDBUS_MSG_MAX_SIZE)
2256 msg->size += (-msg->size) & 7;
2257 item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2259 item->size = item_size;
2260 memcpy (item->data, data, size);
2262 msg->size += item_size;
2268 g_kdbus_msg_append_payload_vec (struct kdbus_msg *msg,
2272 struct kdbus_vec vec = {
2274 .address = (gsize) data
2277 return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_VEC, &vec, sizeof vec);
2281 g_kdbus_msg_append_payload_memfd (struct kdbus_msg *msg,
2286 struct kdbus_memfd mfd = {
2292 return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd);
2295 static struct kdbus_bloom_filter *
2296 g_kdbus_msg_append_bloom (struct kdbus_msg *msg,
2299 struct kdbus_item *bloom_item;
2300 gsize bloom_item_size;
2302 bloom_item_size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
2303 G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
2305 if (msg->size + bloom_item_size > KDBUS_MSG_MAX_SIZE)
2309 msg->size += (-msg->size) & 7;
2310 bloom_item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2312 /* set size and type */
2313 bloom_item->size = bloom_item_size;
2314 bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
2316 msg->size += bloom_item->size;
2317 return &bloom_item->bloom_filter;
2321 #include "dbusheader.h"
2323 void dump_header (gconstpointer data, gsize size) ;
2325 dump_header (gconstpointer data,
2328 GDBusMessageHeaderFieldsIterator iter;
2329 GDBusMessageHeader header;
2331 header = g_dbus_message_header_new (data, size);
2332 g_print ("header e/%c t/%u f/x%x v/%u s/%"G_GUINT64_FORMAT"\n",
2333 g_dbus_message_header_get_endian (header),
2334 g_dbus_message_header_get_type (header),
2335 g_dbus_message_header_get_flags (header),
2336 g_dbus_message_header_get_version (header),
2337 g_dbus_message_header_get_serial (header));
2339 iter = g_dbus_message_header_iterate_fields (header);
2341 while (g_dbus_message_header_fields_iterator_next (&iter))
2343 const gchar *string;
2347 key = g_dbus_message_header_fields_iterator_get_key (iter);
2351 case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2352 if (g_dbus_message_header_fields_iterator_get_value_as_object_path (iter, &string))
2353 g_print (" path: %s\n", string);
2355 g_print (" path: <<invalid string>>\n");
2358 case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2359 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2360 g_print (" interface: %s\n", string);
2362 g_print (" interface: <<invalid string>>\n");
2365 case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2366 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2367 g_print (" member: %s\n", string);
2369 g_print (" member: <<invalid string>>\n");
2372 case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2373 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2374 g_print (" error: %s\n", string);
2376 g_print (" error: <<invalid string>>\n");
2379 case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2380 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2381 g_print (" serial: %s\n", string);
2383 g_print (" serial: <<invalid string>>\n");
2386 case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2387 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2388 g_print (" destination: %s\n", string);
2390 g_print (" destination: <<invalid string>>\n");
2393 case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2394 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2395 g_print (" sender: %s\n", string);
2397 g_print (" sender: <<invalid string>>\n");
2401 g_print ("unknown field code %"G_GUINT64_FORMAT"\n", key);
2402 g_assert_not_reached ();
2413 * Returns: size of data sent or -1 when error
2416 _g_kdbus_send (GKDBusWorker *kdbus,
2417 GDBusMessage *message,
2420 struct kdbus_msg *msg = alloca (KDBUS_MSG_MAX_SIZE);
2421 GVariantVectors body_vectors;
2422 struct kdbus_cmd_send send;
2423 const gchar *dst_name;
2425 g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), -1);
2427 /* fill in as we go... */
2428 memset (msg, 0, sizeof (struct kdbus_msg));
2429 msg->size = sizeof (struct kdbus_msg);
2430 msg->payload_type = KDBUS_PAYLOAD_DBUS;
2431 msg->src_id = kdbus->unique_id;
2432 msg->cookie = g_dbus_message_get_serial(message);
2434 /* Message destination */
2436 dst_name = g_dbus_message_get_destination (message);
2438 if (dst_name != NULL)
2440 if (g_dbus_is_unique_name (dst_name))
2442 if (dst_name[1] != '1' || dst_name[2] != '.')
2444 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
2445 "Invalid unique D-Bus name '%s'", dst_name);
2449 /* We already know that it passes the checks for unique
2450 * names, so no need to perform error checking on strtoull.
2452 msg->dst_id = strtoull (dst_name + 3, NULL, 10);
2457 g_kdbus_msg_append_item (msg, KDBUS_ITEM_DST_NAME, dst_name, strlen (dst_name) + 1);
2458 msg->dst_id = KDBUS_DST_ID_NAME;
2462 msg->dst_id = KDBUS_DST_ID_BROADCAST;
2465 /* File descriptors */
2467 GUnixFDList *fd_list;
2469 fd_list = g_dbus_message_get_unix_fd_list (message);
2471 if (fd_list != NULL)
2476 fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
2479 g_kdbus_msg_append_item (msg, KDBUS_ITEM_FDS, fds, sizeof (gint) * n_fds);
2485 struct dbus_fixed_header fh;
2486 GHashTableIter header_iter;
2487 GVariantBuilder builder;
2488 gpointer key, value;
2492 fh.endian = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? 'l': 'B';
2493 fh.type = g_dbus_message_get_message_type (message);
2494 fh.flags = g_dbus_message_get_flags (message);
2497 fh.serial = g_dbus_message_get_serial (message);
2498 parts[0] = g_variant_new_from_data (DBUS_FIXED_HEADER_TYPE, &fh, sizeof fh, TRUE, NULL, NULL);
2500 g_dbus_message_init_header_iter (message, &header_iter);
2501 g_variant_builder_init (&builder, DBUS_EXTENDED_HEADER_TYPE);
2503 /* We set the sender field to the correct value for ourselves */
2504 g_variant_builder_add (&builder, "{tv}",
2505 (guint64) G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
2506 g_variant_new_printf (":1.%"G_GUINT64_FORMAT, kdbus->unique_id));
2508 while (g_hash_table_iter_next (&header_iter, &key, &value))
2510 guint64 key_int = (gsize) key;
2514 /* These are the normal header fields that get passed
2517 case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2518 case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2519 case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2520 case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2521 case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2522 case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2523 g_variant_builder_add (&builder, "{tv}", key_int, value);
2524 /* This is a little bit gross.
2526 * We must send the header part of the message in a single
2527 * vector as per kdbus rules, but the GVariant serialiser
2528 * code will split any item >= 128 bytes into its own
2529 * vector to save the copy.
2531 * No header field should be that big anyway... right?
2533 g_assert_cmpint (g_variant_get_size (value), <, 128);
2536 /* We send this one unconditionally, but set it ourselves */
2537 case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2540 /* We don't send these at all in GVariant format */
2541 case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
2542 case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
2546 g_assert_not_reached ();
2549 parts[1] = g_variant_builder_end (&builder);
2551 body = g_dbus_message_get_body (message);
2553 body = g_variant_new ("()");
2554 parts[2] = g_variant_new_variant (body);
2556 body = g_variant_ref_sink (g_variant_new_tuple (parts, G_N_ELEMENTS (parts)));
2557 GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, &body_vectors);
2559 /* Sanity check to make sure the header is really contiguous:
2561 * - we must have at least one vector in the output
2562 * - the first vector must completely contain at least the header
2564 g_assert_cmpint (body_vectors.vectors->len, >, 0);
2565 g_assert_cmpint (g_array_index (body_vectors.vectors, GVariantVector, 0).size, >=,
2566 g_variant_get_size (parts[0]) + g_variant_get_size (parts[1]));
2568 g_variant_unref (body);
2574 for (i = 0; i < body_vectors.vectors->len; i++)
2576 GVariantVector vector = g_array_index (body_vectors.vectors, GVariantVector, i);
2582 fd = g_bytes_get_zero_copy_fd (vector.gbytes);
2586 const guchar *bytes_data;
2589 bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
2591 if (bytes_data <= vector.data.pointer && vector.data.pointer + vector.size <= bytes_data + bytes_size)
2593 if (!g_kdbus_msg_append_payload_memfd (msg, fd, vector.data.pointer - bytes_data, vector.size))
2598 if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2604 if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2609 if (!g_kdbus_msg_append_payload_vec (msg, body_vectors.extra_bytes->data + vector.data.offset, vector.size))
2617 msg->flags = ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
2618 ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0);
2620 if ((msg->flags) & KDBUS_MSG_EXPECT_REPLY)
2621 msg->timeout_ns = 1000LU * g_get_monotonic_time() + KDBUS_TIMEOUT_NS;
2623 msg->cookie_reply = g_dbus_message_get_reply_serial(message);
2625 if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_SIGNAL)
2626 msg->flags |= KDBUS_MSG_SIGNAL;
2629 * append bloom filter item for broadcast signals
2631 if (msg->dst_id == KDBUS_DST_ID_BROADCAST)
2633 struct kdbus_bloom_filter *bloom_filter;
2635 bloom_filter = g_kdbus_msg_append_bloom (msg, kdbus->bloom_size);
2636 if (bloom_filter == NULL)
2638 g_kdbus_setup_bloom (kdbus, message, bloom_filter);
2641 send.size = sizeof (send);
2643 send.msg_address = (gsize) msg;
2648 if (ioctl(kdbus->fd, KDBUS_CMD_SEND, &send))
2650 if (errno == ENXIO || errno == ESRCH)
2652 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
2653 "Destination '%s' not known", dst_name);
2655 else if (errno == EADDRNOTAVAIL)
2657 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN,
2658 "No support for activation for name: %s", dst_name);
2660 else if (errno == EXFULL)
2662 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
2663 "The memory pool of the receiver is full");
2665 else if (errno == ENOBUFS)
2667 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_LIMITS_EXCEEDED,
2668 "Too many pending messages on the receiver side");
2672 g_error ("WTF? %d\n", errno);
2673 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
2674 "%s", strerror(errno));
2682 /* We end up here if:
2683 * - too many kdbus_items
2684 * - too large kdbus_msg size
2685 * - too much vector data
2687 * We need to compact the message before sending it.
2689 g_assert_not_reached ();
2693 g_kdbus_worker_new (const gchar *address,
2696 GKDBusWorker *worker;
2698 worker = g_object_new (G_TYPE_KDBUS_WORKER, NULL);
2699 if (!_g_kdbus_open (worker, address, error))
2701 g_object_unref (worker);
2709 g_kdbus_worker_associate (GKDBusWorker *worker,
2710 GDBusCapabilityFlags capabilities,
2711 GDBusWorkerMessageReceivedCallback message_received_callback,
2712 GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback,
2713 GDBusWorkerDisconnectedCallback disconnected_callback,
2716 worker->capabilities = capabilities;
2717 worker->message_received_callback = message_received_callback;
2718 worker->message_about_to_be_sent_callback = message_about_to_be_sent_callback;
2719 worker->disconnected_callback = disconnected_callback;
2720 worker->user_data = user_data;
2724 g_kdbus_worker_unfreeze (GKDBusWorker *worker)
2728 if (worker->source != NULL)
2731 worker->context = g_main_context_ref_thread_default ();
2732 worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN);
2734 g_source_set_callback (worker->source, (GSourceFunc) kdbus_ready, worker, NULL);
2735 name = g_strdup_printf ("kdbus worker");
2736 g_source_set_name (worker->source, name);
2739 g_source_attach (worker->source, worker->context);
2743 g_kdbus_worker_send_message (GKDBusWorker *worker,
2744 GDBusMessage *message,
2747 return _g_kdbus_send (worker, message, error);
2751 g_kdbus_worker_stop (GKDBusWorker *worker)
2756 g_kdbus_worker_flush_sync (GKDBusWorker *worker)
2761 g_kdbus_worker_close (GKDBusWorker *worker,
2762 GCancellable *cancellable,
2763 GSimpleAsyncResult *result)