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_TIMEOUT_NS 2000000000LU
55 #define KDBUS_POOL_SIZE (16 * 1024LU * 1024LU)
56 #define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
57 #define KDBUS_ALIGN8_PTR(p) ((void*) (uintptr_t)(p))
59 #define KDBUS_ITEM_HEADER_SIZE G_STRUCT_OFFSET(struct kdbus_item, data)
60 #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
62 #define KDBUS_ITEM_NEXT(item) \
63 (typeof(item))(((guint8 *)item) + KDBUS_ALIGN8((item)->size))
64 #define KDBUS_ITEM_FOREACH(item, head, first) \
65 for (item = (head)->first; \
66 (guint8 *)(item) < (guint8 *)(head) + (head)->size; \
67 item = KDBUS_ITEM_NEXT(item))
68 #define KDBUS_FOREACH(iter, first, _size) \
69 for (iter = (first); \
70 ((guint8 *)(iter) < (guint8 *)(first) + (_size)) && \
71 ((guint8 *)(iter) >= (guint8 *)(first)); \
72 iter = (void*)(((guint8 *)iter) + KDBUS_ALIGN8((iter)->size)))
74 #define g_alloca0(x) memset(g_alloca(x), '\0', (x))
76 struct dbus_fixed_header {
85 #define DBUS_FIXED_HEADER_TYPE ((const GVariantType *) "(yyyyut)")
86 #define DBUS_EXTENDED_HEADER_TYPE ((const GVariantType *) "a{tv}")
87 #define DBUS_MESSAGE_TYPE ((const GVariantType *) "((yyyyut)a{tv}v)")
89 #define KDBUS_MSG_MAX_SIZE 8192
95 G_BUS_CREDS_UNIQUE_NAME = 3,
96 G_BUS_CREDS_SELINUX_CONTEXT = 4
97 } GBusCredentialsFlags;
99 typedef GObjectClass GKDBusWorkerClass;
103 GObject parent_instance;
107 GMainContext *context;
116 guint64 attach_flags_send;
117 guint64 attach_flags_recv;
129 GDBusCapabilityFlags capabilities;
130 GDBusWorkerMessageReceivedCallback message_received_callback;
131 GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback;
132 GDBusWorkerDisconnectedCallback disconnected_callback;
136 static gssize _g_kdbus_receive (GKDBusWorker *kdbus,
137 GCancellable *cancellable,
140 G_DEFINE_TYPE (GKDBusWorker, g_kdbus_worker, G_TYPE_OBJECT)
142 /* Hash keys for bloom filters*/
143 const guint8 hash_keys[8][16] =
145 {0xb9,0x66,0x0b,0xf0,0x46,0x70,0x47,0xc1,0x88,0x75,0xc4,0x9c,0x54,0xb9,0xbd,0x15},
146 {0xaa,0xa1,0x54,0xa2,0xe0,0x71,0x4b,0x39,0xbf,0xe1,0xdd,0x2e,0x9f,0xc5,0x4a,0x3b},
147 {0x63,0xfd,0xae,0xbe,0xcd,0x82,0x48,0x12,0xa1,0x6e,0x41,0x26,0xcb,0xfa,0xa0,0xc8},
148 {0x23,0xbe,0x45,0x29,0x32,0xd2,0x46,0x2d,0x82,0x03,0x52,0x28,0xfe,0x37,0x17,0xf5},
149 {0x56,0x3b,0xbf,0xee,0x5a,0x4f,0x43,0x39,0xaf,0xaa,0x94,0x08,0xdf,0xf0,0xfc,0x10},
150 {0x31,0x80,0xc8,0x73,0xc7,0xea,0x46,0xd3,0xaa,0x25,0x75,0x0f,0x9e,0x4c,0x09,0x29},
151 {0x7d,0xf7,0x18,0x4b,0x7b,0xa4,0x44,0xd5,0x85,0x3c,0x06,0xe0,0x65,0x53,0x96,0x6d},
152 {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35}
157 MATCH_ELEMENT_SENDER,
158 MATCH_ELEMENT_INTERFACE,
159 MATCH_ELEMENT_MEMBER,
161 MATCH_ELEMENT_PATH_NAMESPACE,
162 MATCH_ELEMENT_DESTINATION,
163 MATCH_ELEMENT_ARG0NAMESPACE,
164 MATCH_ELEMENT_EAVESDROP,
166 MATCH_ELEMENT_ARGNPATH,
169 /* MatchElement struct */
179 MatchElement *elements;
188 is_key (const char *key_start, const char *key_end, char *value)
190 gsize len = strlen (value);
192 if (len != key_end - key_start)
195 return strncmp (key_start, value, len) == 0;
204 parse_key (MatchElement *element, const char *key_start, const char *key_end)
208 if (is_key (key_start, key_end, "type"))
210 element->type = MATCH_ELEMENT_TYPE;
212 else if (is_key (key_start, key_end, "sender"))
214 element->type = MATCH_ELEMENT_SENDER;
216 else if (is_key (key_start, key_end, "interface"))
218 element->type = MATCH_ELEMENT_INTERFACE;
220 else if (is_key (key_start, key_end, "member"))
222 element->type = MATCH_ELEMENT_MEMBER;
224 else if (is_key (key_start, key_end, "path"))
226 element->type = MATCH_ELEMENT_PATH;
228 else if (is_key (key_start, key_end, "path_namespace"))
230 element->type = MATCH_ELEMENT_PATH_NAMESPACE;
232 else if (is_key (key_start, key_end, "destination"))
234 element->type = MATCH_ELEMENT_DESTINATION;
236 else if (is_key (key_start, key_end, "arg0namespace"))
238 element->type = MATCH_ELEMENT_ARG0NAMESPACE;
240 else if (is_key (key_start, key_end, "eavesdrop"))
242 element->type = MATCH_ELEMENT_EAVESDROP;
244 else if (key_end - key_start > 3 && is_key (key_start, key_start + 3, "arg"))
246 const char *digits = key_start + 3;
247 const char *end_digits = digits;
249 while (end_digits < key_end && g_ascii_isdigit (*end_digits))
252 if (end_digits == key_end) /* argN */
254 element->type = MATCH_ELEMENT_ARGN;
255 element->arg = atoi (digits);
257 else if (is_key (end_digits, key_end, "path")) /* argNpath */
259 element->type = MATCH_ELEMENT_ARGNPATH;
260 element->arg = atoi (digits);
277 parse_value (MatchElement *element, const char *s)
282 value = g_string_new ("");
305 g_string_append_c (value, *s);
309 else if (quote_char == '\\')
311 /* \ only counts as an escape if escaping a quote mark */
313 g_string_append_c (value, '\\');
315 g_string_append_c (value, *s);
318 else /* quote_char == ' */
323 g_string_append_c (value, *s);
328 if (quote_char == '\\')
329 g_string_append_c (value, '\\');
330 else if (quote_char == '\'')
332 g_string_free (value, TRUE);
336 element->value = g_string_free (value, FALSE);
346 match_new (const char *str)
351 const char *key_start;
353 MatchElement element;
356 elements = g_array_new (TRUE, TRUE, sizeof (MatchElement));
362 memset (&element, 0, sizeof (element));
364 /* Skip initial whitespace */
365 while (*p && g_ascii_isspace (*p))
370 /* Read non-whitespace non-equals chars */
371 while (*p && *p != '=' && !g_ascii_isspace (*p))
376 /* Skip any whitespace after key */
377 while (*p && g_ascii_isspace (*p))
380 if (key_start == key_end)
381 continue; /* Allow trailing whitespace */
387 if (!parse_key (&element, key_start, key_end))
390 p = parse_value (&element, p);
394 g_array_append_val (elements, element);
397 match = g_new0 (Match, 1);
398 match->n_elements = elements->len;
399 match->elements = (MatchElement *)g_array_free (elements, FALSE);
404 for (i = 0; i < elements->len; i++)
405 g_free (g_array_index (elements, MatchElement, i).value);
406 g_array_free (elements, TRUE);
416 match_free (Match *match)
419 for (i = 0; i < match->n_elements; i++)
420 g_free (match->elements[i].value);
421 g_free (match->elements);
431 g_kdbus_worker_finalize (GObject *object)
433 GKDBusWorker *kdbus = G_KDBUS_WORKER (object);
435 if (kdbus->kdbus_buffer != NULL)
436 munmap (kdbus->kdbus_buffer, KDBUS_POOL_SIZE);
438 kdbus->kdbus_buffer = NULL;
440 if (kdbus->fd != -1 && !kdbus->closed)
441 _g_kdbus_close (kdbus);
443 G_OBJECT_CLASS (g_kdbus_worker_parent_class)->finalize (object);
447 g_kdbus_worker_class_init (GKDBusWorkerClass *class)
449 class->finalize = g_kdbus_worker_finalize;
453 g_kdbus_worker_init (GKDBusWorker *kdbus)
457 kdbus->unique_id = -1;
458 kdbus->unique_name = NULL;
460 kdbus->kdbus_buffer = NULL;
462 kdbus->flags = 0; /* KDBUS_HELLO_ACCEPT_FD */
463 kdbus->attach_flags_send = _KDBUS_ATTACH_ALL;
464 kdbus->attach_flags_recv = _KDBUS_ATTACH_ALL;
468 kdbus_ready (gint fd,
469 GIOCondition condition,
472 GKDBusWorker *kdbus = user_data;
473 GError *error = NULL;
475 _g_kdbus_receive (kdbus, NULL, &error);
476 g_assert_no_error (error);
478 return G_SOURCE_CONTINUE;
482 _g_kdbus_open (GKDBusWorker *worker,
483 const gchar *address,
486 g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
488 worker->fd = open(address, O_RDWR|O_NOCTTY|O_CLOEXEC);
491 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Can't open kdbus endpoint"));
495 worker->closed = FALSE;
506 g_kdbus_free_data (GKDBusWorker *kdbus,
509 struct kdbus_cmd_free cmd = {};
512 cmd.size = sizeof(cmd);
516 ret = ioctl (kdbus->fd, KDBUS_CMD_FREE, &cmd);
525 * g_kdbus_translate_nameowner_flags:
529 g_kdbus_translate_nameowner_flags (GBusNameOwnerFlags flags,
530 guint64 *kdbus_flags)
536 if (flags & G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT)
537 new_flags |= KDBUS_NAME_ALLOW_REPLACEMENT;
539 if (flags & G_BUS_NAME_OWNER_FLAGS_REPLACE)
540 new_flags |= KDBUS_NAME_REPLACE_EXISTING;
542 if (!(flags & G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE))
543 new_flags |= KDBUS_NAME_QUEUE;
545 *kdbus_flags = new_flags;
554 _g_kdbus_close (GKDBusWorker *kdbus)
556 g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
561 g_source_destroy (kdbus->source);
564 g_main_context_unref (kdbus->context);
565 kdbus->context = NULL;
570 kdbus->closed = TRUE;
574 * _g_kdbus_is_closed:
578 _g_kdbus_is_closed (GKDBusWorker *kdbus)
580 g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), FALSE);
582 return kdbus->closed;
591 _g_kdbus_Hello (GKDBusWorker *worker,
594 struct kdbus_cmd_hello *hello;
595 struct kdbus_item *item;
598 size_t size, conn_name_size;
600 conn_name = "gdbus-kdbus";
601 conn_name_size = strlen (conn_name);
603 size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_hello, items)) +
604 KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1);
606 hello = g_alloca0 (size);
607 hello->flags = worker->flags;
608 hello->attach_flags_send = worker->attach_flags_send;
609 hello->attach_flags_recv = worker->attach_flags_recv;
611 hello->pool_size = KDBUS_POOL_SIZE;
614 item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + conn_name_size + 1;
615 item->type = KDBUS_ITEM_CONN_DESCRIPTION;
616 memcpy (item->str, conn_name, conn_name_size+1);
617 item = KDBUS_ITEM_NEXT (item);
619 if (ioctl(worker->fd, KDBUS_CMD_HELLO, hello))
621 g_set_error (error, G_IO_ERROR,
622 g_io_error_from_errno (errno),
623 _("Failed to send HELLO: %s"),
628 worker->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, worker->fd, 0);
629 if (worker->kdbus_buffer == MAP_FAILED)
631 g_set_error (error, G_IO_ERROR,
632 g_io_error_from_errno (errno),
638 if (hello->bus_flags > 0xFFFFFFFFULL)
640 g_set_error_literal (error,
643 _("Incompatible HELLO flags"));
647 memcpy (worker->bus_id, hello->id128, 16);
649 worker->unique_id = hello->id;
650 asprintf(&worker->unique_name, ":1.%llu", (unsigned long long) hello->id);
652 /* read bloom filters parameters */
653 //worker->bloom_size = (gsize) hello->bloom.size;
654 //worker->bloom_n_hash = (guint) hello->bloom.n_hash;
656 return g_variant_new ("(s)", worker->unique_name);
661 * _g_kdbus_RequestName:
665 _g_kdbus_RequestName (GKDBusWorker *worker,
667 GBusNameOwnerFlags flags,
671 struct kdbus_cmd *kdbus_name;
676 status = G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER;
678 if (!g_dbus_is_name (name))
682 G_DBUS_ERROR_INVALID_ARGS,
683 "Given bus name \"%s\" is not valid", name);
691 G_DBUS_ERROR_INVALID_ARGS,
692 "Cannot acquire a service starting with ':' such as \"%s\"", name);
696 g_kdbus_translate_nameowner_flags (flags, &kdbus_flags);
698 len = strlen(name) + 1;
699 size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
700 kdbus_name = g_alloca0 (size);
701 kdbus_name->size = size;
702 kdbus_name->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
703 kdbus_name->items[0].type = KDBUS_ITEM_NAME;
704 kdbus_name->flags = kdbus_flags;
705 memcpy (kdbus_name->items[0].str, name, len);
707 ret = ioctl(worker->fd, KDBUS_CMD_NAME_ACQUIRE, kdbus_name);
711 status = G_BUS_REQUEST_NAME_FLAGS_EXISTS;
712 else if (errno == EALREADY)
713 status = G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER;
716 g_set_error (error, G_IO_ERROR,
717 g_io_error_from_errno (errno),
718 _("Error while acquiring name: %s"),
724 if (kdbus_name->flags & KDBUS_NAME_IN_QUEUE)
725 status = G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE;
727 result = g_variant_new ("(u)", status);
734 * _g_kdbus_ReleaseName:
738 _g_kdbus_ReleaseName (GKDBusWorker *worker,
743 struct kdbus_cmd *kdbus_name;
747 status = G_BUS_RELEASE_NAME_FLAGS_RELEASED;
749 if (!g_dbus_is_name (name))
753 G_DBUS_ERROR_INVALID_ARGS,
754 "Given bus name \"%s\" is not valid", name);
762 G_DBUS_ERROR_INVALID_ARGS,
763 "Cannot release a service starting with ':' such as \"%s\"", name);
767 len = strlen(name) + 1;
768 size = G_STRUCT_OFFSET (struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(len);
769 kdbus_name = g_alloca0 (size);
770 kdbus_name->size = size;
771 kdbus_name->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
772 kdbus_name->items[0].type = KDBUS_ITEM_NAME;
773 memcpy (kdbus_name->items[0].str, name, len);
775 ret = ioctl(worker->fd, KDBUS_CMD_NAME_RELEASE, kdbus_name);
779 status = G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT;
780 else if (errno == EADDRINUSE)
781 status = G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER;
784 g_set_error (error, G_IO_ERROR,
785 g_io_error_from_errno (errno),
786 _("Error while releasing name: %s"),
792 result = g_variant_new ("(u)", status);
803 _g_kdbus_GetBusId (GKDBusWorker *worker,
810 result_str = g_string_new (NULL);
812 for (cnt=0; cnt<16; cnt++)
813 g_string_append_printf (result_str, "%02x", worker->bus_id[cnt]);
815 result = g_variant_new ("(s)", result_str->str);
816 g_string_free (result_str, TRUE);
823 * _g_kdbus_GetListNames:
827 _g_kdbus_GetListNames (GKDBusWorker *worker,
828 guint list_name_type,
832 GVariantBuilder *builder;
834 struct kdbus_cmd_list cmd = {};
835 struct kdbus_info *name_list, *name;
843 cmd.flags = KDBUS_LIST_ACTIVATORS; /* ListActivatableNames */
845 cmd.flags = KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES; /* ListNames */
847 cmd.size = sizeof(cmd);
848 ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
854 _("Error listing names"));
858 name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
859 builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
861 KDBUS_FOREACH(name, name_list, cmd.list_size)
863 struct kdbus_item *item;
864 const gchar *item_name = "";
866 if ((cmd.flags & KDBUS_LIST_UNIQUE) && name->id != prev_id)
868 GString *unique_name;
870 unique_name = g_string_new (NULL);
871 g_string_printf (unique_name, ":1.%llu", name->id);
872 g_variant_builder_add (builder, "s", unique_name->str);
873 g_string_free (unique_name,TRUE);
877 KDBUS_ITEM_FOREACH(item, name, items)
878 if (item->type == KDBUS_ITEM_OWNED_NAME)
879 item_name = item->name.name;
881 if (g_dbus_is_name (item_name))
882 g_variant_builder_add (builder, "s", item_name);
885 result = g_variant_new ("(as)", builder);
886 g_variant_builder_unref (builder);
888 g_kdbus_free_data (worker, cmd.offset);
894 * _g_kdbus_NameHasOwner_internal:
898 g_kdbus_NameHasOwner_internal (GKDBusWorker *worker,
902 struct kdbus_cmd_info *cmd;
906 if (g_dbus_is_unique_name(name))
908 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
909 cmd = g_alloca0 (size);
910 cmd->id = g_ascii_strtoull (name+3, NULL, 10);
914 len = strlen(name) + 1;
915 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
916 cmd = g_alloca0 (size);
917 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
918 cmd->items[0].type = KDBUS_ITEM_NAME;
919 memcpy (cmd->items[0].str, name, len);
923 ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
924 g_kdbus_free_data (worker, cmd->offset);
934 * _g_kdbus_GetListQueuedOwners:
938 _g_kdbus_GetListQueuedOwners (GKDBusWorker *worker,
943 GVariantBuilder *builder;
944 GString *unique_name;
947 struct kdbus_cmd_list cmd = {};
948 struct kdbus_info *name_list, *kname;
950 if (!g_dbus_is_name (name))
954 G_DBUS_ERROR_INVALID_ARGS,
955 "Given bus name \"%s\" is not valid", name);
959 if (!g_kdbus_NameHasOwner_internal (worker, name, error))
963 G_DBUS_ERROR_NAME_HAS_NO_OWNER,
964 "Could not get owner of name '%s': no such name", name);
968 cmd.flags = KDBUS_LIST_QUEUED;
969 cmd.size = sizeof(cmd);
970 ret = ioctl(worker->fd, KDBUS_CMD_LIST, &cmd);
976 _("Error listing names"));
980 name_list = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd.offset);
982 unique_name = g_string_new (NULL);
983 builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
984 KDBUS_FOREACH(kname, name_list, cmd.list_size)
986 struct kdbus_item *item;
987 const char *item_name = "";
989 KDBUS_ITEM_FOREACH(item, kname, items)
990 if (item->type == KDBUS_ITEM_NAME)
991 item_name = item->str;
993 if (strcmp(item_name, name))
996 g_string_printf (unique_name, ":1.%llu", kname->id);
997 g_variant_builder_add (builder, "s", item_name);
1000 result = g_variant_new ("(as)", builder);
1001 g_variant_builder_unref (builder);
1002 g_string_free (unique_name,TRUE);
1004 g_kdbus_free_data (worker, cmd.offset);
1010 * g_kdbus_GetConnInfo_internal:
1014 g_kdbus_GetConnInfo_internal (GKDBusWorker *worker,
1021 struct kdbus_cmd_info *cmd;
1022 struct kdbus_info *conn_info;
1023 struct kdbus_item *item;
1029 if (!g_dbus_is_name (name))
1033 G_DBUS_ERROR_INVALID_ARGS,
1034 "Given bus name \"%s\" is not valid", name);
1038 if (!g_kdbus_NameHasOwner_internal (worker, name, error))
1042 G_DBUS_ERROR_NAME_HAS_NO_OWNER,
1043 "Could not get owner of name '%s': no such name", name);
1047 if (g_dbus_is_unique_name(name))
1049 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items);
1050 cmd = g_alloca0 (size);
1051 cmd->id = g_ascii_strtoull (name+3, NULL, 10);
1055 len = strlen(name) + 1;
1056 size = G_STRUCT_OFFSET (struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(len);
1057 cmd = g_alloca0 (size);
1058 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + len;
1059 cmd->items[0].type = KDBUS_ITEM_NAME;
1060 memcpy (cmd->items[0].str, name, len);
1063 cmd->flags = _KDBUS_ATTACH_ALL;
1066 ret = ioctl(worker->fd, KDBUS_CMD_CONN_INFO, cmd);
1071 G_DBUS_ERROR_FAILED,
1072 _("Could not get connection info"));
1076 conn_info = (struct kdbus_info *) ((guint8 *) worker->kdbus_buffer + cmd->offset);
1079 if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
1083 if (flag == G_BUS_CREDS_UNIQUE_NAME)
1085 GString *unique_name;
1087 unique_name = g_string_new (NULL);
1088 g_string_printf (unique_name, ":1.%llu", (unsigned long long) conn_info->id);
1089 result = g_variant_new ("(s)", unique_name->str);
1090 g_string_free (unique_name,TRUE);
1094 KDBUS_ITEM_FOREACH(item, conn_info, items)
1098 case KDBUS_ITEM_PIDS:
1100 if (flag == G_BUS_CREDS_PID)
1102 guint pid = item->pids.pid;
1103 result = g_variant_new ("(u)", pid);
1107 case KDBUS_ITEM_CREDS:
1109 if (flag == G_BUS_CREDS_UID)
1111 guint uid = item->creds.uid;
1112 result = g_variant_new ("(u)", uid);
1116 case KDBUS_ITEM_SECLABEL:
1117 case KDBUS_ITEM_PID_COMM:
1118 case KDBUS_ITEM_TID_COMM:
1119 case KDBUS_ITEM_EXE:
1120 case KDBUS_ITEM_CMDLINE:
1121 case KDBUS_ITEM_CGROUP:
1122 case KDBUS_ITEM_CAPS:
1123 case KDBUS_ITEM_AUDIT:
1124 case KDBUS_ITEM_CONN_DESCRIPTION:
1125 case KDBUS_ITEM_AUXGROUPS:
1126 case KDBUS_ITEM_OWNED_NAME:
1132 g_kdbus_free_data (worker, cmd->offset);
1138 * _g_kdbus_GetNameOwner:
1142 _g_kdbus_GetNameOwner (GKDBusWorker *worker,
1146 return g_kdbus_GetConnInfo_internal (worker,
1148 G_BUS_CREDS_UNIQUE_NAME,
1154 * _g_kdbus_GetConnectionUnixProcessID:
1158 _g_kdbus_GetConnectionUnixProcessID (GKDBusWorker *worker,
1162 return g_kdbus_GetConnInfo_internal (worker,
1170 * _g_kdbus_GetConnectionUnixUser:
1174 _g_kdbus_GetConnectionUnixUser (GKDBusWorker *worker,
1178 return g_kdbus_GetConnInfo_internal (worker,
1186 * g_kdbus_bloom_add_data:
1187 * Based on bus-bloom.c from systemd
1188 * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1191 g_kdbus_bloom_add_data (GKDBusWorker *worker,
1192 guint64 bloom_data [],
1198 guint bytes_num = 0;
1204 bit_num = worker->bloom_size * 8;
1207 bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8;
1209 for (cnt_1 = 0; cnt_1 < (worker->bloom_n_hash); cnt_1++)
1211 for (cnt_2 = 0; cnt_2 < bytes_num; cnt_2++)
1215 g_siphash24(hash, data, n, hash_keys[cnt_1++]);
1219 p = (p << 8ULL) | (guint64) hash[8 - c];
1224 bloom_data[p >> 6] |= 1ULL << (p & 63);
1230 * g_kdbus_bloom_add_pair:
1234 g_kdbus_bloom_add_pair (GKDBusWorker *worker,
1235 guint64 bloom_data [],
1236 const gchar *parameter,
1242 size = strlen(parameter) + strlen(value) + 1;
1246 strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1247 g_kdbus_bloom_add_data(worker, bloom_data, buf, size);
1252 * g_kdbus_bloom_add_prefixes:
1256 g_kdbus_bloom_add_prefixes (GKDBusWorker *worker,
1257 guint64 bloom_data [],
1258 const gchar *parameter,
1265 size = strlen(parameter) + strlen(value) + 1;
1269 strcpy(stpcpy(stpcpy(buf, parameter), ":"), value);
1274 last_sep = strrchr(buf, separator);
1275 if (!last_sep || last_sep == buf)
1279 g_kdbus_bloom_add_data(worker, bloom_data, buf, last_sep-buf);
1285 * _g_kdbus_AddMatch:
1289 _g_kdbus_AddMatch (GKDBusWorker *worker,
1290 const gchar *match_rule,
1294 MatchElement *element;
1295 const gchar *sender_name;
1296 gsize sender_len, size;
1297 struct kdbus_cmd_match *cmd_match;
1298 struct kdbus_item *item;
1304 if (match_rule[0] == '-')
1307 match = match_new (match_rule);
1315 src_id = KDBUS_MATCH_ID_ANY;
1317 bloom = g_alloca0 (worker->bloom_size);
1318 size = KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_cmd_match, items));
1319 match = match_new (match_rule);
1321 for (cnt = 0; cnt < match->n_elements; cnt++)
1323 element = &match->elements[cnt];
1324 switch (element->type)
1326 case MATCH_ELEMENT_SENDER:
1327 if (g_dbus_is_unique_name(element->value))
1329 src_id = g_ascii_strtoull ((element->value)+3, NULL, 10);
1330 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id));
1332 else if (g_dbus_is_name (element->value))
1334 sender_name = element->value;
1335 sender_len = strlen(element->value) + 1;
1336 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len);
1340 g_critical ("Error while adding a match: %d", cookie);
1346 case MATCH_ELEMENT_TYPE:
1347 g_kdbus_bloom_add_pair (worker, bloom, "message-type", element->value);
1350 case MATCH_ELEMENT_INTERFACE:
1351 g_kdbus_bloom_add_pair (worker, bloom, "interface", element->value);
1354 case MATCH_ELEMENT_MEMBER:
1355 g_kdbus_bloom_add_pair (worker, bloom, "member", element->value);
1358 case MATCH_ELEMENT_PATH:
1359 g_kdbus_bloom_add_pair (worker, bloom, "path", element->value);
1362 case MATCH_ELEMENT_PATH_NAMESPACE:
1363 if (g_strcmp0 (element->value, "/"))
1364 g_kdbus_bloom_add_pair (worker, bloom, "path-slash-prefix", element->value);
1367 case MATCH_ELEMENT_ARGN:
1368 asprintf (&type, "arg%u", element->arg);
1369 g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1373 case MATCH_ELEMENT_ARGNPATH:
1374 asprintf (&type, "arg%u-slash-prefix", element->arg);
1375 g_kdbus_bloom_add_pair (worker, bloom, type, element->value);
1379 case MATCH_ELEMENT_ARG0NAMESPACE:
1380 g_kdbus_bloom_add_pair (worker, bloom, "arg0-dot-prefix", element->value);
1383 case MATCH_ELEMENT_DESTINATION:
1384 case MATCH_ELEMENT_EAVESDROP:
1389 size += KDBUS_ALIGN8 (G_STRUCT_OFFSET (struct kdbus_item, data64) + worker->bloom_size);
1390 cmd_match = g_alloca0 (size);
1391 cmd_match->size = size;
1392 cmd_match->cookie = cookie;
1394 item = cmd_match->items;
1395 item->size = G_STRUCT_OFFSET(struct kdbus_item, data64) + worker->bloom_size;
1396 item->type = KDBUS_ITEM_BLOOM_MASK;
1397 memcpy(item->data64, bloom, worker->bloom_size);
1398 item = KDBUS_ITEM_NEXT(item);
1400 if (src_id != KDBUS_MATCH_ID_ANY)
1402 item->size = G_STRUCT_OFFSET (struct kdbus_item, id) + sizeof(src_id);
1403 item->type = KDBUS_ITEM_ID;
1405 item = KDBUS_ITEM_NEXT(item);
1410 item->size = G_STRUCT_OFFSET (struct kdbus_item, str) + sender_len;
1411 item->type = KDBUS_ITEM_NAME;
1412 memcpy (item->str, sender_name, sender_len);
1415 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd_match);
1417 g_critical ("Error while adding a match: %d", cookie);
1424 * _g_kdbus_RemoveMatch:
1428 _g_kdbus_RemoveMatch (GKDBusWorker *worker,
1431 struct kdbus_cmd_match cmd_match = {};
1434 cmd_match.size = sizeof (cmd_match);
1435 cmd_match.cookie = cookie;
1437 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_REMOVE, &cmd_match);
1439 g_warning ("Error while removing a match: %d\n", (int) errno);
1444 * _g_kdbus_subscribe_name_acquired:
1448 _g_kdbus_subscribe_name_owner_changed (GKDBusWorker *worker,
1450 const gchar *old_name,
1451 const gchar *new_name,
1454 struct kdbus_item *item;
1455 struct kdbus_cmd_match *cmd_match;
1458 guint64 old_id = 0; /* XXX why? */
1459 guint64 new_id = KDBUS_MATCH_ID_ANY;
1461 len = strlen(name) + 1;
1462 size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1463 G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1464 G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1466 cmd_match = g_alloca0 (size);
1467 cmd_match->size = size;
1468 cmd_match->cookie = cookie;
1469 item = cmd_match->items;
1471 if (old_name[0] == 0)
1473 old_id = KDBUS_MATCH_ID_ANY;
1477 if (g_dbus_is_unique_name(old_name))
1483 if (new_name[0] == 0)
1485 new_id = KDBUS_MATCH_ID_ANY;
1489 if (g_dbus_is_unique_name(new_name))
1495 cmd_match = g_alloca0 (size);
1496 cmd_match->size = size;
1497 cmd_match->cookie = cookie;
1498 item = cmd_match->items;
1500 /* KDBUS_ITEM_NAME_CHANGE */
1501 item->type = KDBUS_ITEM_NAME_CHANGE;
1502 item->name_change.old_id.id = old_id;
1503 item->name_change.new_id.id = new_id;
1504 memcpy(item->name_change.name, name, len);
1505 item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1506 G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1507 item = KDBUS_ITEM_NEXT(item);
1509 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd_match);
1511 g_warning ("ERROR - %d\n", (int) errno);
1516 * _g_kdbus_subscribe_name_acquired:
1520 _g_kdbus_subscribe_name_acquired (GKDBusWorker *worker,
1523 struct kdbus_item *item;
1524 struct kdbus_cmd_match *cmd_match;
1529 len = strlen(name) + 1;
1530 size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1531 G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1532 G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1534 cookie = 0xbeefbeefbeefbeef;
1535 cmd_match = g_alloca0 (size);
1536 cmd_match->size = size;
1537 cmd_match->cookie = cookie;
1538 item = cmd_match->items;
1540 /* KDBUS_ITEM_NAME_ADD */
1541 item->type = KDBUS_ITEM_NAME_ADD;
1542 item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
1543 item->name_change.new_id.id = worker->unique_id;
1544 memcpy(item->name_change.name, name, len);
1545 item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1546 G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1547 item = KDBUS_ITEM_NEXT(item);
1549 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd_match);
1551 g_warning ("ERROR - %d\n", (int) errno);
1553 _g_kdbus_subscribe_name_owner_changed (worker, name, "", worker->unique_name, cookie);
1558 * _g_kdbus_subscribe_name_lost:
1562 _g_kdbus_subscribe_name_lost (GKDBusWorker *worker,
1565 struct kdbus_item *item;
1566 struct kdbus_cmd_match *cmd_match;
1571 len = strlen(name) + 1;
1572 size = KDBUS_ALIGN8(G_STRUCT_OFFSET (struct kdbus_cmd_match, items) +
1573 G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1574 G_STRUCT_OFFSET (struct kdbus_notify_name_change, name) + len);
1576 cookie = 0xdeafdeafdeafdeaf;
1577 cmd_match = g_alloca0 (size);
1578 cmd_match->size = size;
1579 cmd_match->cookie = cookie;
1580 item = cmd_match->items;
1582 /* KDBUS_ITEM_NAME_REMOVE */
1583 item->type = KDBUS_ITEM_NAME_REMOVE;
1584 item->name_change.old_id.id = worker->unique_id;
1585 item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
1586 memcpy(item->name_change.name, name, len);
1587 item->size = G_STRUCT_OFFSET (struct kdbus_item, name_change) +
1588 G_STRUCT_OFFSET(struct kdbus_notify_name_change, name) + len;
1589 item = KDBUS_ITEM_NEXT(item);
1591 ret = ioctl(worker->fd, KDBUS_CMD_MATCH_ADD, cmd_match);
1593 g_warning ("ERROR - %d\n", (int) errno);
1595 _g_kdbus_subscribe_name_owner_changed (worker, name, worker->unique_name, "", cookie);
1600 * _g_kdbus_unsubscribe_name_acquired:
1604 _g_kdbus_unsubscribe_name_acquired (GKDBusWorker *worker)
1608 cookie = 0xbeefbeefbeefbeef;
1609 _g_kdbus_RemoveMatch (worker, cookie);
1614 * _g_kdbus_unsubscribe_name_lost:
1618 _g_kdbus_unsubscribe_name_lost (GKDBusWorker *worker)
1622 cookie = 0xdeafdeafdeafdeaf;
1623 _g_kdbus_RemoveMatch (worker, cookie);
1628 * g_kdbus_append_payload_bloom:
1631 static struct kdbus_bloom_filter *
1632 g_kdbus_append_bloom (struct kdbus_item **item,
1635 struct kdbus_item *bloom_item;
1637 bloom_item = KDBUS_ALIGN8_PTR(*item);
1638 bloom_item->size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
1639 G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
1642 bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
1644 *item = KDBUS_ITEM_NEXT(bloom_item);
1645 return &bloom_item->bloom_filter;
1650 * g_kdbus_setup_bloom:
1651 * Based on bus-bloom.c from systemd
1652 * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
1655 g_kdbus_setup_bloom (GKDBusWorker *worker,
1656 GDBusMessage *dbus_msg,
1657 struct kdbus_bloom_filter *bloom_filter)
1661 const gchar *message_type;
1662 const gchar *interface;
1663 const gchar *member;
1668 body = g_dbus_message_get_body (dbus_msg);
1669 message_type = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, g_dbus_message_get_message_type (dbus_msg));
1670 interface = g_dbus_message_get_interface (dbus_msg);
1671 member = g_dbus_message_get_member (dbus_msg);
1672 path = g_dbus_message_get_path (dbus_msg);
1674 bloom_data = bloom_filter->data;
1675 memset (bloom_data, 0, worker->bloom_size);
1676 bloom_filter->generation = 0;
1678 g_kdbus_bloom_add_pair(worker, bloom_data, "message-type", message_type);
1681 g_kdbus_bloom_add_pair(worker, bloom_data, "interface", interface);
1684 g_kdbus_bloom_add_pair(worker, bloom_data, "member", member);
1688 g_kdbus_bloom_add_pair(worker, bloom_data, "path", path);
1689 g_kdbus_bloom_add_pair(worker, bloom_data, "path-slash-prefix", path);
1690 g_kdbus_bloom_add_prefixes(worker, bloom_data, "path-slash-prefix", path, '/');
1695 const GVariantType *body_type;
1696 const GVariantType *arg_type;
1699 body_type = g_variant_get_type (body);
1701 for (arg_type = g_variant_type_first (body_type), cnt = 0;
1703 arg_type = g_variant_type_next (arg_type), cnt++)
1705 gchar type_char = g_variant_type_peek_string (arg_type)[0];
1706 gchar buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1711 if (type_char != 's' && type_char != 'o')
1712 /* XXX: kdbus docs say "stop after first non-string" but I
1713 * think they're wrong (vs. dbus-1 compat)...
1717 child = g_variant_get_child_value (body, cnt);
1718 str = g_variant_get_string (child, NULL);
1720 e = stpcpy(buf, "arg");
1722 *(e++) = '0' + (char) cnt;
1725 *(e++) = '0' + (char) (cnt / 10);
1726 *(e++) = '0' + (char) (cnt % 10);
1729 /* We add this one for both strings and object paths */
1730 strcpy(e, "-slash-prefix");
1731 g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '/');
1733 /* But the others are only for strings */
1734 if (type_char == 's')
1736 strcpy(e, "-dot-prefix");
1737 g_kdbus_bloom_add_prefixes(worker, bloom_data, buf, str, '.');
1740 g_kdbus_bloom_add_pair(worker, bloom_data, buf, str);
1743 g_variant_unref (child);
1750 * TODO: g_kdbus_NameOwnerChanged_generate, g_kdbus_KernelMethodError_generate
1754 * g_kdbus_decode_kernel_msg:
1758 g_kdbus_decode_kernel_msg (GKDBusWorker *worker,
1759 struct kdbus_msg *msg)
1761 struct kdbus_item *item = NULL;
1763 KDBUS_ITEM_FOREACH(item, msg, items)
1767 case KDBUS_ITEM_ID_ADD:
1768 case KDBUS_ITEM_ID_REMOVE:
1769 case KDBUS_ITEM_NAME_ADD:
1770 case KDBUS_ITEM_NAME_REMOVE:
1771 case KDBUS_ITEM_NAME_CHANGE:
1772 //size = g_kdbus_NameOwnerChanged_generate (worker, item);
1773 g_error ("'NameOwnerChanged'");
1776 case KDBUS_ITEM_REPLY_TIMEOUT:
1777 case KDBUS_ITEM_REPLY_DEAD:
1778 //size = g_kdbus_KernelMethodError_generate (worker, item);
1779 g_error ("'KernelMethodError'");
1783 g_warning ("Unknown field in kernel message - %lld", item->type);
1788 /* Override information from the user header with data from the kernel */
1789 g_string_printf (worker->msg_sender, "org.freedesktop.DBus");
1791 /* for destination */
1792 if (worker->kmsg->dst_id == KDBUS_DST_ID_BROADCAST)
1793 /* for broadcast messages we don't have to set destination */
1795 else if (worker->kmsg->dst_id == KDBUS_DST_ID_NAME)
1796 g_string_printf (worker->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64) worker->unique_id);
1798 g_string_printf (worker->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64) worker->kmsg->dst_id);
1806 * g_kdbus_decode_dbus_msg:
1809 static GDBusMessage *
1810 g_kdbus_decode_dbus_msg (GKDBusWorker *worker,
1811 struct kdbus_msg *msg)
1813 GDBusMessage *message;
1814 struct kdbus_item *item;
1815 gssize data_size = 0;
1816 GArray *body_vectors;
1822 GVariantIter *fields_iter;
1823 guint8 endianness, type, flags, version;
1829 message = g_dbus_message_new ();
1831 body_vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
1833 tmp = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) msg->src_id);
1834 g_dbus_message_set_sender (message, tmp);
1840 KDBUS_ITEM_FOREACH(item, msg, items)
1842 if (item->size <= KDBUS_ITEM_HEADER_SIZE)
1843 g_error("[KDBUS] %llu bytes - invalid data record\n", item->size);
1845 data_size = item->size - KDBUS_ITEM_HEADER_SIZE;
1849 /* KDBUS_ITEM_DST_NAME */
1850 case KDBUS_ITEM_DST_NAME:
1851 /* Classic D-Bus doesn't make this known to the receiver, so
1852 * we don't do it here either (for compatibility with the
1857 /* KDBUS_ITEM_PALOAD_OFF */
1858 case KDBUS_ITEM_PAYLOAD_OFF:
1860 GVariantVector vector;
1863 /* We want to make sure the bytes are aligned the same as
1864 * they would be if they appeared in a contiguously
1865 * allocated chunk of aligned memory.
1867 * We decide what the alignment 'should' be by consulting
1868 * body_size, which has been tracking the total size of the
1869 * message up to this point.
1871 * We then play around with the pointer by removing as many
1872 * bytes as required to get it to the proper alignment (and
1873 * copy extra bytes accordingly). This means that we will
1874 * grab some extra data in the 'bytes', but it won't be
1875 * shared with GVariant (which means there is no chance of
1876 * it being accidentally retransmitted).
1878 * The kernel does the same thing, so make sure we get the
1879 * expected result. Because of the kernel doing the same,
1880 * the result is that we will always be rounding-down to a
1881 * multiple of 8 for the pointer, which means that the
1882 * pointer will always be valid, assuming the original
1885 * We could fix this with a new GBytes constructor that took
1886 * 'flavour' as a parameter, but it's not worth it...
1888 flavour = body_size & 7;
1889 g_assert ((item->vec.offset & 7) == flavour);
1891 vector.gbytes = g_bytes_new (((guchar *) worker->kdbus_buffer) + item->vec.offset - flavour, item->vec.size + flavour);
1892 vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL);
1893 vector.data.pointer += flavour;
1894 vector.size = item->vec.size;
1896 g_array_append_val (body_vectors, vector);
1897 body_size += vector.size;
1901 /* KDBUS_ITEM_PAYLOAD_MEMFD */
1902 case KDBUS_ITEM_PAYLOAD_MEMFD:
1904 GVariantVector vector;
1908 vector.gbytes = g_bytes_new_take_zero_copy_fd (item->memfd.fd);
1909 data = g_bytes_get_data (vector.gbytes, &size);
1911 g_assert (item->memfd.start + item->memfd.size <= size);
1913 vector.data.pointer = data + item->memfd.start;
1914 vector.size = item->memfd.size;
1916 g_array_append_val (body_vectors, vector);
1917 body_size += vector.size;
1921 /* KDBUS_ITEM_FDS */
1922 case KDBUS_ITEM_FDS:
1924 GUnixFDList *fd_list;
1926 fd_list = g_unix_fd_list_new_from_array (item->fds, data_size / sizeof (int));
1927 g_dbus_message_set_unix_fd_list (message, fd_list);
1928 g_object_unref (fd_list);
1932 /* All of the following items, like CMDLINE,
1933 CGROUP, etc. need some GDBUS API extensions and
1934 should be implemented in the future */
1935 case KDBUS_ITEM_TIMESTAMP:
1937 g_print ("time: seq %llu mon %llu real %llu\n",
1938 item->timestamp.seqnum, item->timestamp.monotonic_ns, item->timestamp.realtime_ns);
1939 //g_dbus_message_set_timestamp (message, item->timestamp.monotonic_ns / 1000);
1940 //g_dbus_message_set_serial (message, item->timestamp.seqnum);
1944 case KDBUS_ITEM_CREDS:
1946 g_print ("creds: u%u eu %u su%u fsu%u g%u eg%u sg%u fsg%u\n",
1947 item->creds.uid, item->creds.euid, item->creds.suid, item->creds.fsuid,
1948 item->creds.gid, item->creds.egid, item->creds.sgid, item->creds.fsgid);
1952 case KDBUS_ITEM_PIDS:
1953 case KDBUS_ITEM_PID_COMM:
1954 case KDBUS_ITEM_TID_COMM:
1955 case KDBUS_ITEM_EXE:
1956 case KDBUS_ITEM_CMDLINE:
1957 case KDBUS_ITEM_CGROUP:
1958 case KDBUS_ITEM_AUDIT:
1959 case KDBUS_ITEM_CAPS:
1960 case KDBUS_ITEM_SECLABEL:
1961 case KDBUS_ITEM_CONN_DESCRIPTION:
1962 case KDBUS_ITEM_AUXGROUPS:
1963 case KDBUS_ITEM_OWNED_NAME:
1964 case KDBUS_ITEM_NAME:
1965 g_print ("unhandled %04x\n", (int) item->type);
1969 g_error ("[KDBUS] DBUS_PAYLOAD: Unknown filed - %lld", item->type);
1974 body = GLIB_PRIVATE_CALL(g_variant_from_vectors) (G_VARIANT_TYPE ("((yyyyuta{tv})v)"),
1975 (GVariantVector *) body_vectors->data,
1976 body_vectors->len, body_size, FALSE);
1979 for (i = 0; i < body_vectors->len; i++)
1980 g_bytes_unref (g_array_index (body_vectors, GVariantVector, i).gbytes);
1982 g_array_free (body_vectors, TRUE);
1984 parts[0] = g_variant_get_child_value (body, 0);
1985 parts[1] = g_variant_get_child_value (body, 1);
1986 g_variant_unref (body);
1988 body = g_variant_get_variant (parts[1]);
1989 g_variant_unref (parts[1]);
1990 g_dbus_message_set_body (message, body);
1991 g_variant_unref (body);
1993 g_variant_get (parts[0], "(yyyyuta{tv})", &endianness, &type, &flags, &version, NULL, &serial, &fields_iter);
1994 g_variant_unref (parts[0]);
1996 while (g_variant_iter_loop (fields_iter, "{tv}", &key, &value))
1997 g_dbus_message_set_header (message, key, value);
1999 g_dbus_message_set_flags (message, flags);
2000 g_dbus_message_set_serial (message, serial);
2001 g_dbus_message_set_message_type (message, type);
2003 g_print ("Received:\n%s\n", g_dbus_message_print (message, 2));
2005 (* worker->message_received_callback) (message, worker->user_data);
2007 g_object_unref (message);
2018 _g_kdbus_receive (GKDBusWorker *kdbus,
2019 GCancellable *cancellable,
2022 struct kdbus_cmd_recv recv;
2023 struct kdbus_msg *msg;
2025 memset (&recv, 0, sizeof recv);
2026 recv.size = sizeof (recv);
2028 if (g_cancellable_set_error_if_cancelled (cancellable, error))
2032 if (ioctl(kdbus->fd, KDBUS_CMD_RECV, &recv) < 0)
2037 if (errno == EAGAIN)
2040 g_warning ("in holding pattern over %d %d\n", kdbus->fd, errno);
2044 g_set_error (error, G_IO_ERROR,
2045 g_io_error_from_errno (errno),
2046 _("Error while receiving message: %s"),
2047 g_strerror (errno));
2051 g_print ("but sometimes that's okay\n");
2053 msg = (struct kdbus_msg *)((guint8 *)kdbus->kdbus_buffer + recv.msg.offset);
2055 if (msg->payload_type == KDBUS_PAYLOAD_DBUS)
2056 g_kdbus_decode_dbus_msg (kdbus, msg);
2057 else if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
2058 g_kdbus_decode_kernel_msg (kdbus, msg);
2063 G_DBUS_ERROR_FAILED,
2064 _("Received unknown payload type"));
2068 ioctl(kdbus->fd, KDBUS_CMD_FREE, &recv.msg.offset);
2074 g_kdbus_msg_append_item (struct kdbus_msg *msg,
2079 struct kdbus_item *item;
2082 item_size = size + G_STRUCT_OFFSET(struct kdbus_item, data);
2084 if (msg->size + item_size > KDBUS_MSG_MAX_SIZE)
2088 msg->size += (-msg->size) & 7;
2089 item = (struct kdbus_item *) ((guchar *) msg + msg->size);
2091 item->size = item_size;
2092 memcpy (item->data, data, size);
2094 msg->size += item_size;
2100 g_kdbus_msg_append_payload_vec (struct kdbus_msg *msg,
2104 struct kdbus_vec vec = {
2106 .address = (gsize) data
2109 return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_VEC, &vec, sizeof vec);
2113 g_kdbus_msg_append_payload_memfd (struct kdbus_msg *msg,
2118 struct kdbus_memfd mfd = {
2124 return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd);
2128 #include "dbusheader.h"
2130 void dump_header (gconstpointer data, gsize size) ;
2132 dump_header (gconstpointer data,
2135 GDBusMessageHeaderFieldsIterator iter;
2136 GDBusMessageHeader header;
2138 header = g_dbus_message_header_new (data, size);
2139 g_print ("header e/%c t/%u f/x%x v/%u s/%"G_GUINT64_FORMAT"\n",
2140 g_dbus_message_header_get_endian (header),
2141 g_dbus_message_header_get_type (header),
2142 g_dbus_message_header_get_flags (header),
2143 g_dbus_message_header_get_version (header),
2144 g_dbus_message_header_get_serial (header));
2146 iter = g_dbus_message_header_iterate_fields (header);
2148 while (g_dbus_message_header_fields_iterator_next (&iter))
2150 const gchar *string;
2154 key = g_dbus_message_header_fields_iterator_get_key (iter);
2158 case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2159 if (g_dbus_message_header_fields_iterator_get_value_as_object_path (iter, &string))
2160 g_print (" path: %s\n", string);
2162 g_print (" path: <<invalid string>>\n");
2165 case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2166 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2167 g_print (" interface: %s\n", string);
2169 g_print (" interface: <<invalid string>>\n");
2172 case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2173 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2174 g_print (" member: %s\n", string);
2176 g_print (" member: <<invalid string>>\n");
2179 case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2180 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2181 g_print (" error: %s\n", string);
2183 g_print (" error: <<invalid string>>\n");
2186 case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2187 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2188 g_print (" serial: %s\n", string);
2190 g_print (" serial: <<invalid string>>\n");
2193 case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2194 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2195 g_print (" destination: %s\n", string);
2197 g_print (" destination: <<invalid string>>\n");
2200 case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2201 if (g_dbus_message_header_fields_iterator_get_value_as_string (iter, &string))
2202 g_print (" sender: %s\n", string);
2204 g_print (" sender: <<invalid string>>\n");
2208 g_print ("unknown field code %"G_GUINT64_FORMAT"\n", key);
2209 g_assert_not_reached ();
2220 * Returns: size of data sent or -1 when error
2223 _g_kdbus_send (GKDBusWorker *kdbus,
2224 GDBusMessage *message,
2227 struct kdbus_msg *msg = alloca (KDBUS_MSG_MAX_SIZE);
2228 GVariantVectors body_vectors;
2229 struct kdbus_cmd_send send;
2231 g_return_val_if_fail (G_IS_KDBUS_WORKER (kdbus), -1);
2233 /* fill in as we go... */
2234 memset (msg, 0, sizeof (struct kdbus_msg));
2235 msg->size = sizeof (struct kdbus_msg);
2236 msg->payload_type = KDBUS_PAYLOAD_DBUS;
2237 msg->src_id = kdbus->unique_id;
2238 msg->cookie = g_dbus_message_get_serial(message);
2240 /* Message destination */
2242 const gchar *dst_name;
2244 dst_name = g_dbus_message_get_destination (message);
2246 if (dst_name != NULL)
2248 if (g_dbus_is_unique_name (dst_name))
2250 if (dst_name[1] != '1' || dst_name[2] != '.')
2252 g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
2253 "Invalid unique D-Bus name '%s'", dst_name);
2257 /* We already know that it passes the checks for unique
2258 * names, so no need to perform error checking on strtoull.
2260 msg->dst_id = strtoull (dst_name + 3, NULL, 10);
2265 g_kdbus_msg_append_item (msg, KDBUS_ITEM_DST_NAME, dst_name, strlen (dst_name) + 1);
2266 msg->dst_id = KDBUS_DST_ID_NAME;
2270 msg->dst_id = KDBUS_DST_ID_BROADCAST;
2273 /* File descriptors */
2275 GUnixFDList *fd_list;
2277 fd_list = g_dbus_message_get_unix_fd_list (message);
2279 if (fd_list != NULL)
2284 fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
2287 g_kdbus_msg_append_item (msg, KDBUS_ITEM_FDS, fds, sizeof (gint) * n_fds);
2293 struct dbus_fixed_header fh;
2294 GHashTableIter header_iter;
2295 GVariantBuilder builder;
2296 gpointer key, value;
2300 fh.endian = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? 'l': 'B';
2301 fh.type = g_dbus_message_get_message_type (message);
2302 fh.flags = g_dbus_message_get_flags (message);
2305 fh.serial = g_dbus_message_get_serial (message);
2306 parts[0] = g_variant_new_from_data (DBUS_FIXED_HEADER_TYPE, &fh, sizeof fh, TRUE, NULL, NULL);
2308 g_dbus_message_init_header_iter (message, &header_iter);
2309 g_variant_builder_init (&builder, DBUS_EXTENDED_HEADER_TYPE);
2311 /* We set the sender field to the correct value for ourselves */
2312 g_variant_builder_add (&builder, "{tv}",
2313 (guint64) G_DBUS_MESSAGE_HEADER_FIELD_SENDER,
2314 g_variant_new_printf (":1.%"G_GUINT64_FORMAT, kdbus->unique_id));
2316 while (g_hash_table_iter_next (&header_iter, &key, &value))
2318 guint64 key_int = (gsize) key;
2322 /* These are the normal header fields that get passed
2325 case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
2326 case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
2327 case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
2328 case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
2329 case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
2330 case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
2331 g_variant_builder_add (&builder, "{tv}", key_int, value);
2332 /* This is a little bit gross.
2334 * We must send the header part of the message in a single
2335 * vector as per kdbus rules, but the GVariant serialiser
2336 * code will split any item >= 128 bytes into its own
2337 * vector to save the copy.
2339 * No header field should be that big anyway... right?
2341 g_assert_cmpint (g_variant_get_size (value), <, 128);
2344 /* We send this one unconditionally, but set it ourselves */
2345 case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
2348 /* We don't send these at all in GVariant format */
2349 case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
2350 case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
2354 g_assert_not_reached ();
2357 parts[1] = g_variant_builder_end (&builder);
2359 body = g_dbus_message_get_body (message);
2361 body = g_variant_new ("()");
2362 parts[2] = g_variant_new_variant (body);
2364 body = g_variant_ref_sink (g_variant_new_tuple (parts, G_N_ELEMENTS (parts)));
2365 GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, &body_vectors);
2367 /* Sanity check to make sure the header is really contiguous:
2369 * - we must have at least one vector in the output
2370 * - the first vector must completely contain at least the header
2372 g_assert_cmpint (body_vectors.vectors->len, >, 0);
2373 g_assert_cmpint (g_array_index (body_vectors.vectors, GVariantVector, 0).size, >=,
2374 g_variant_get_size (parts[0]) + g_variant_get_size (parts[1]));
2376 g_variant_unref (body);
2382 for (i = 0; i < body_vectors.vectors->len; i++)
2384 GVariantVector vector = g_array_index (body_vectors.vectors, GVariantVector, i);
2390 fd = g_bytes_get_zero_copy_fd (vector.gbytes);
2394 const guchar *bytes_data;
2397 bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
2399 if (bytes_data <= vector.data.pointer && vector.data.pointer + vector.size <= bytes_data + bytes_size)
2401 if (!g_kdbus_msg_append_payload_memfd (msg, fd, vector.data.pointer - bytes_data, vector.size))
2406 if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2412 if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
2417 if (!g_kdbus_msg_append_payload_vec (msg, body_vectors.extra_bytes->data + vector.data.offset, vector.size))
2425 msg->flags = ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
2426 ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0);
2428 if ((msg->flags) & KDBUS_MSG_EXPECT_REPLY)
2429 msg->timeout_ns = 1000LU * g_get_monotonic_time() + KDBUS_TIMEOUT_NS;
2431 msg->cookie_reply = g_dbus_message_get_reply_serial(message);
2435 if (dst_id == KDBUS_DST_ID_BROADCAST)
2437 struct kdbus_bloom_filter *bloom_filter;
2439 bloom_filter = g_kdbus_append_bloom (&item, kdbus->bloom_size);
2440 g_kdbus_setup_bloom (kdbus, message, bloom_filter);
2444 send.size = sizeof (send);
2446 send.msg_address = (gsize) msg;
2452 if (ioctl(kdbus->fd, KDBUS_CMD_SEND, &send))
2455 GString *error_name;
2456 error_name = g_string_new (NULL);
2460 g_string_free (error_name,TRUE);
2463 else if (errno == ENXIO)
2465 g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg));
2466 g_kdbus_generate_local_error (worker,
2468 g_variant_new ("(s)",error_name->str),
2469 G_DBUS_ERROR_SERVICE_UNKNOWN);
2470 g_string_free (error_name,TRUE);
2473 else if ((errno == ESRCH) || (errno == EADDRNOTAVAIL))
2475 if (kmsg->flags & KDBUS_MSG_FLAGS_NO_AUTO_START)
2477 g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg));
2478 g_kdbus_generate_local_error (worker,
2480 g_variant_new ("(s)",error_name->str),
2481 G_DBUS_ERROR_SERVICE_UNKNOWN);
2482 g_string_free (error_name,TRUE);
2487 g_string_printf (error_name, "The name %s was not provided by any .service files", g_dbus_message_get_destination(dbus_msg));
2488 g_kdbus_generate_local_error (worker,
2490 g_variant_new ("(s)",error_name->str),
2491 G_DBUS_ERROR_SERVICE_UNKNOWN);
2492 g_string_free (error_name,TRUE);
2497 g_print ("[KDBUS] ioctl error sending kdbus message:%d (%m)\n",errno);
2498 g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno), _("Error sending message - KDBUS_CMD_MSG_SEND error"));
2500 perror("ioctl send");
2501 g_error ("IOCTL SEND: %d\n",errno);
2508 /* We end up here if:
2509 * - too many kdbus_items
2510 * - too large kdbus_msg size
2511 * - too much vector data
2513 * We need to compact the message before sending it.
2515 g_assert_not_reached ();
2519 g_kdbus_worker_new (const gchar *address,
2522 GKDBusWorker *worker;
2524 worker = g_object_new (G_TYPE_KDBUS_WORKER, NULL);
2525 if (!_g_kdbus_open (worker, address, error))
2527 g_object_unref (worker);
2535 g_kdbus_worker_associate (GKDBusWorker *worker,
2536 GDBusCapabilityFlags capabilities,
2537 GDBusWorkerMessageReceivedCallback message_received_callback,
2538 GDBusWorkerMessageAboutToBeSentCallback message_about_to_be_sent_callback,
2539 GDBusWorkerDisconnectedCallback disconnected_callback,
2542 worker->capabilities = capabilities;
2543 worker->message_received_callback = message_received_callback;
2544 worker->message_about_to_be_sent_callback = message_about_to_be_sent_callback;
2545 worker->disconnected_callback = disconnected_callback;
2546 worker->user_data = user_data;
2550 g_kdbus_worker_unfreeze (GKDBusWorker *worker)
2554 if (worker->source != NULL)
2557 worker->context = g_main_context_ref_thread_default ();
2558 worker->source = g_unix_fd_source_new (worker->fd, G_IO_IN);
2560 g_source_set_callback (worker->source, (GSourceFunc) kdbus_ready, worker, NULL);
2561 name = g_strdup_printf ("kdbus worker");
2562 g_source_set_name (worker->source, name);
2565 g_source_attach (worker->source, worker->context);
2569 g_kdbus_worker_send_message (GKDBusWorker *worker,
2570 GDBusMessage *message,
2573 return _g_kdbus_send (worker, message, error);
2577 g_kdbus_worker_stop (GKDBusWorker *worker)
2582 g_kdbus_worker_flush_sync (GKDBusWorker *worker)
2587 g_kdbus_worker_close (GKDBusWorker *worker,
2588 GCancellable *cancellable,
2589 GSimpleAsyncResult *result)