1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* kdbus-common.c kdbus related utils for daemon and libdbus
4 * Copyright (C) 2013 Samsung Electronics
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version and under the terms of the GNU
12 * Lesser General Public License as published by the
13 * Free Software Foundation; either version 2.1 of the License, or (at
14 * your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <linux/kdbus.h>
28 #include "kdbus-common.h"
29 #include "dbus-transport-kdbus.h"
30 #include "dbus-valgrind-internal.h"
36 #include <dbus/dbus-internals.h>
37 #include <dbus/dbus-shared.h>
38 #include "dbus-signals.h"
40 #include <sys/ioctl.h>
41 #include <sys/types.h>
48 const char *path; /**< Path to kdbus file */
49 int fd; /**< File descriptor */
50 void *mmap_ptr; /**< Mapped memory where kdbus (kernel) writes
51 * messages incoming to us.
53 size_t pool_size; /**< Size of mapped memory */
54 __u64 id; /**< unique id of the connection */
55 char bus_id[sizeof (((struct kdbus_cmd_hello *)(0))->id128)]; /**< id of the bus */
56 struct kdbus_bloom_parameter bloom; /**< bloom parameters*/
59 /* ALIGN8 and KDBUS_FOREACH taken from systemd */
60 #define ALIGN8(l) (((l) + 7) & ~7)
61 #define KDBUS_FOREACH(iter, first, _size) \
62 for (iter = (first); \
63 ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
64 ((uint8_t *)(iter) >= (uint8_t *)(first)); \
65 iter = (void*)(((uint8_t *)iter) + ALIGN8((iter)->size)))
69 unsigned long request,
75 ret = ioctl (fd, request, data);
77 while (-1 == ret && EINTR == errno);
83 free_by_offset (kdbus_t *kdbus,
86 struct kdbus_cmd_free cmd;
89 * Kdbus requires to initialize ioctl params partially. Some parts
90 * are for data passed from user to kernel, and other parts
91 * for data passed from kernel to user.
93 * Valgrind detects when uninitialized data is passed to kernel
94 * and has no way to know that it is meant to be filled by kernel.
95 * Thus, we initialize params for Valgrind to stop complaining.
97 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
99 cmd.size = sizeof (cmd);
103 if (safe_ioctl (kdbus->fd, KDBUS_CMD_FREE, &cmd )!= 0)
109 static void make_item_name (const char *name, struct kdbus_item *item)
111 size_t len = strlen (name) + 1;
112 item->size = KDBUS_ITEM_HEADER_SIZE + len;
113 item->type = KDBUS_ITEM_NAME;
115 memcpy (item->str, name, len);
119 * Adds an item in the current position of items array.
121 * @param item item to fill
122 * @param item_type type of the item
123 * @param string value of the item
124 * @param string_size size of the value
125 * @returns pointer to the next item
128 _kdbus_item_add_string (struct kdbus_item *item,
130 const char *item_string,
131 __u64 item_string_size)
133 item->size = KDBUS_ITEM_HEADER_SIZE + item_string_size;
134 item->type = item_type;
135 memcpy (item->str, item_string, item_string_size);
136 return KDBUS_ITEM_NEXT (item);
140 _kdbus_item_add_payload_memfd (struct kdbus_item *item,
145 item->type = KDBUS_ITEM_PAYLOAD_MEMFD;
146 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_memfd);
147 item->memfd.start = start;
148 item->memfd.size = size;
150 return KDBUS_ITEM_NEXT (item);
154 _kdbus_item_add_payload_vec (struct kdbus_item *item,
156 __u64 address_or_offset)
158 item->type = KDBUS_ITEM_PAYLOAD_VEC;
159 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_vec);
160 item->vec.size = size;
161 item->vec.address = address_or_offset;
162 return KDBUS_ITEM_NEXT (item);
166 _kdbus_item_add_fds (struct kdbus_item *item,
170 item->type = KDBUS_ITEM_FDS;
171 item->size = KDBUS_ITEM_HEADER_SIZE + (__u64)fds_count * sizeof (int);
172 memcpy (item->fds, fds, fds_count * sizeof (int));
173 return KDBUS_ITEM_NEXT (item);
177 _kdbus_item_add_bloom_filter (struct kdbus_item *item,
179 struct kdbus_bloom_filter **out_ptr)
181 item->type = KDBUS_ITEM_BLOOM_FILTER;
182 item->size = KDBUS_ITEM_HEADER_SIZE
183 + sizeof (struct kdbus_bloom_filter)
185 memset (item->bloom_filter.data, 0, kdbus->bloom.size);
186 item->bloom_filter.generation = 0;
187 *out_ptr = &item->bloom_filter;
188 return KDBUS_ITEM_NEXT (item);
192 _kdbus_bloom_filter_get_data (struct kdbus_bloom_filter *bloom_filter)
194 return bloom_filter->data;
198 _kdbus_item_add_name_change (struct kdbus_item *item,
204 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_notify_name_change);
205 item->type = KDBUS_ITEM_NAME_CHANGE;
206 item->name_change.old_id.id = old_id;
207 item->name_change.old_id.flags = old_id_flags;
208 item->name_change.new_id.id = new_id;
209 item->name_change.new_id.flags = new_id_flags;
210 return KDBUS_ITEM_NEXT (item);
214 _kdbus_item_add_id_add (struct kdbus_item *item,
218 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_notify_id_change);
219 item->type = KDBUS_ITEM_ID_ADD;
220 item->id_change.id = id;
221 item->id_change.flags = id_flags;
222 return KDBUS_ITEM_NEXT (item);
226 _kdbus_item_add_id (struct kdbus_item *item,
229 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (id);
230 item->type = KDBUS_ITEM_ID;
232 return KDBUS_ITEM_NEXT (item);
236 _kdbus_item_add_bloom_mask (struct kdbus_item *item,
238 kdbus_bloom_data_t **bloom)
240 item->size = KDBUS_ITEM_HEADER_SIZE + kdbus->bloom.size;
241 item->type = KDBUS_ITEM_BLOOM_MASK;
242 memset (item->data64, 0, kdbus->bloom.size);
244 *bloom = item->data64;
245 return KDBUS_ITEM_NEXT (item);
249 get_from_offset (kdbus_t *kdbus,
252 return ((char *)kdbus->mmap_ptr) + offset;
256 _kdbus_new (const char *path)
258 kdbus_t *kdbus = dbus_new (kdbus_t, 1);
261 kdbus->path = _dbus_strdup(path);
262 if (NULL == kdbus->path)
272 _kdbus_free (kdbus_t *kdbus)
274 dbus_free ((char*)kdbus->path);
279 * Opens a connection to the kdbus bus
281 * @param kdbus kdbus object
282 * @returns 0 on success, -errno on failure
285 _kdbus_open (kdbus_t *kdbus)
287 int fd = open (kdbus->path, O_RDWR|O_CLOEXEC|O_NONBLOCK);
296 _kdbus_close (kdbus_t *kdbus)
304 ret = close (kdbus->fd);
305 } while (-1 == ret && EINTR == errno);
309 ret = munmap (kdbus->mmap_ptr, kdbus->pool_size);
321 _kdbus_get_pool (kdbus_t *kdbus)
323 return kdbus->mmap_ptr;
327 _kdbus_get_path (kdbus_t *kdbus)
333 _kdbus_get_fd (kdbus_t *kdbus)
339 _kdbus_get_id (kdbus_t *kdbus)
345 _kdbus_get_bus_id (kdbus_t *kdbus)
347 return kdbus->bus_id;
351 _kdbus_get_bus_id_size (void)
353 return sizeof (((struct kdbus_t *)(0))->bus_id);
357 _kdbus_hello (kdbus_t *kdbus,
359 __u64 attach_flags_send,
360 __u64 attach_flags_recv,
362 const char *activator_name,
363 const char *connection_name)
365 struct kdbus_cmd_hello *hello;
366 struct kdbus_item *item, *items;
368 size_t activator_name_size = 0;
369 size_t connection_name_size = 0;
373 hello_size = sizeof (struct kdbus_cmd_hello);
375 if (NULL != activator_name)
377 activator_name_size = strlen (activator_name) + 1;
378 hello_size += KDBUS_ITEM_SIZE (activator_name_size);
381 if (NULL != connection_name)
383 connection_name_size = strlen (connection_name) + 1;
384 hello_size += KDBUS_ITEM_SIZE (connection_name_size);
387 hello = dbus_malloc (hello_size);
391 VALGRIND_MAKE_MEM_DEFINED (hello, hello_size);
393 hello->flags = flags;
394 hello->attach_flags_send = attach_flags_send;
395 hello->attach_flags_recv = attach_flags_recv;
396 hello->pool_size = pool_size;
399 if (connection_name_size > 0)
400 item = _kdbus_item_add_string (item,
401 KDBUS_ITEM_CONN_DESCRIPTION,
403 connection_name_size);
404 if (activator_name_size > 0)
406 _kdbus_item_add_string (item,
409 activator_name_size);
410 hello->flags |= KDBUS_HELLO_ACTIVATOR;
413 hello->size = hello_size;
415 if (safe_ioctl (kdbus->fd, KDBUS_CMD_HELLO, hello) != 0)
421 kdbus->id = hello->id;
422 memcpy (kdbus->bus_id, hello->id128, sizeof (kdbus->bus_id));
424 offset = hello->offset;
425 items_size = hello->items_size;
428 kdbus->mmap_ptr = mmap (NULL, pool_size, PROT_READ, MAP_SHARED, kdbus->fd, 0);
429 if (MAP_FAILED == kdbus->mmap_ptr)
432 kdbus->pool_size = pool_size;
434 items = get_from_offset (kdbus, offset);
435 KDBUS_FOREACH (item, items, items_size)
437 if (KDBUS_ITEM_BLOOM_PARAMETER == item->type)
438 kdbus->bloom = item->bloom_parameter;
441 free_by_offset (kdbus, offset);
447 _kdbus_send (kdbus_t *kdbus,
449 struct kdbus_msg *msg,
450 struct kdbus_msg **msg_reply)
452 struct kdbus_cmd_send cmd;
454 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
456 cmd.size = sizeof (cmd);
457 cmd.msg_address = (uintptr_t)msg;
460 if (-1 == safe_ioctl (kdbus->fd, KDBUS_CMD_SEND, &cmd))
463 if (flags & KDBUS_SEND_SYNC_REPLY)
465 if (NULL != msg_reply)
466 *msg_reply = get_from_offset (kdbus, cmd.reply.offset);
468 free_by_offset (kdbus, cmd.reply.offset);
475 _kdbus_recv (kdbus_t *kdbus,
478 struct kdbus_msg **msg)
480 struct kdbus_cmd_recv cmd;
482 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
484 cmd.size = sizeof (cmd);
486 cmd.priority = priority;
488 if (-1 == safe_ioctl (kdbus->fd, KDBUS_CMD_RECV, &cmd))
491 *msg = get_from_offset (kdbus, cmd.msg.offset);
497 * Provides list of names on the bus.
499 * @param kdbus kdbus object
500 * @param flags specification of required names. See enum kdbus_list_flags in kdbus.h.
501 * @param name_list data from kdbus response - the list
502 * @param list_size size of name_list in bytes
503 * @return 0 on success, errno on failure
505 * Note that name_list is allocated in kdbus pool and must be freed by _kdbus_free_mem.
508 _kdbus_list (kdbus_t *kdbus,
510 struct kdbus_info **name_list,
513 struct kdbus_cmd_list cmd;
515 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
517 cmd.size = sizeof (cmd);
520 if (-1 == safe_ioctl (kdbus->fd, KDBUS_CMD_LIST, &cmd))
523 *name_list = get_from_offset (kdbus, cmd.offset);
524 *list_size = cmd.list_size;
530 _kdbus_compute_match_items_size (kdbus_t *kdbus,
531 dbus_bool_t with_bloom_mask,
533 const char *sender_name)
538 size += KDBUS_ITEM_SIZE (kdbus->bloom.size);
540 if (KDBUS_MATCH_ID_ANY != sender_id) /* unique name present */
541 size += KDBUS_ITEM_SIZE (sizeof (sender_id));
542 else if (NULL != sender_name)
543 size += KDBUS_ITEM_SIZE (strlen (sender_name) + 1);
548 struct kdbus_cmd_match *
549 _kdbus_new_cmd_match (kdbus_t *kdbus,
554 struct kdbus_cmd_match *cmd;
555 __u64 cmd_size = sizeof (*cmd) + items_size;
556 cmd = dbus_malloc (cmd_size);
560 VALGRIND_MAKE_MEM_DEFINED (cmd, cmd_size);
562 cmd->size = cmd_size;
564 cmd->cookie = cookie;
570 _kdbus_free_cmd_match (struct kdbus_cmd_match *cmd)
576 _kdbus_add_match_name_acquired (kdbus_t *kdbus,
585 struct kdbus_cmd_match *cmd;
586 struct kdbus_item *item;
588 unsigned int len = 0;
591 len = strlen(name) + 1;
592 cmd = _kdbus_new_cmd_match (kdbus,
593 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_name_change) + len),
600 _kdbus_item_add_name_change (item,
601 old_id, old_id_flags,
602 new_id, new_id_flags);
605 memcpy(item->name_change.name, name, len);
607 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
609 goto err_name_acquired;
611 item->type = KDBUS_ITEM_NAME_ADD;
612 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
614 goto err_name_acquired;
619 _kdbus_free_cmd_match (cmd);
624 _kdbus_add_match_name_lost (kdbus_t *kdbus,
633 struct kdbus_cmd_match *cmd;
634 struct kdbus_item *item;
636 unsigned int len = 0;
639 len = strlen(name) + 1;
641 cmd = _kdbus_new_cmd_match (kdbus,
642 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_name_change) + len),
649 _kdbus_item_add_name_change (item,
650 old_id, old_id_flags,
651 new_id, new_id_flags);
655 memcpy(item->name_change.name, name, len);
657 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
659 goto err_name_remove;
661 item->type = KDBUS_ITEM_NAME_REMOVE;
662 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
664 goto err_name_remove;
669 _kdbus_free_cmd_match (cmd);
674 _kdbus_add_match_name_change (kdbus_t *kdbus,
683 struct kdbus_cmd_match *cmd;
684 struct kdbus_item *item;
686 unsigned int len = 0;
689 len = strlen(name) + 1;
691 /* name = NULL or Well-known Name */
692 if (name == NULL || (name[0] != ':')) {
693 cmd = _kdbus_new_cmd_match (kdbus,
694 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_name_change) + len),
701 _kdbus_item_add_name_change (item,
702 old_id, old_id_flags,
703 new_id, new_id_flags);
707 memcpy(item->name_change.name, name, len);
709 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
712 item->type = KDBUS_ITEM_NAME_ADD;
713 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
716 item->type = KDBUS_ITEM_NAME_REMOVE;
717 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
724 _kdbus_free_cmd_match (cmd);
732 _kdbus_add_match_id_change (kdbus_t *kdbus,
739 struct kdbus_cmd_match *cmd;
740 struct kdbus_item *item;
743 /* name = NULL or Unique Name */
744 if (name == NULL || name[0] == ':')
746 cmd = _kdbus_new_cmd_match (kdbus,
747 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_id_change)),
754 _kdbus_item_add_id_add (item, id, id_flags);
757 item->id_change.id = strtoull (name + 3, NULL, 10);
759 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
762 item->type = KDBUS_ITEM_ID_REMOVE;
763 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
769 _kdbus_free_cmd_match (cmd);
775 int _kdbus_add_match (kdbus_t *kdbus,
776 struct kdbus_cmd_match *cmd)
778 int ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
786 * Allocates and initializes kdbus message structure.
787 * @param kdbus kdbus object
788 * @param size_for_items size of items that will be attached to this message
789 * @param flags flags for message
790 * @returns initialized kdbus message or NULL if malloc failed
793 _kdbus_new_msg (kdbus_t *kdbus,
794 __u64 size_for_items,
799 enum kdbus_payload_type payload_type,
801 __u64 timeout_ns_or_cookie_reply)
803 struct kdbus_msg *msg;
804 __u64 msg_size = sizeof (struct kdbus_msg) + size_for_items;
806 msg = dbus_malloc (msg_size);
810 msg->size = msg_size;
812 msg->priority = priority;
813 msg->dst_id = dst_id;
814 msg->src_id = src_id;
815 msg->payload_type = payload_type;
816 msg->cookie = cookie;
817 msg->timeout_ns = timeout_ns_or_cookie_reply;
823 _kdbus_free_msg (struct kdbus_msg *msg)
829 _kdbus_free_mem (kdbus_t *kdbus, void *mem)
831 char *base_ptr = kdbus->mmap_ptr;
832 char *mem_ptr = (char *)mem;
834 return free_by_offset (kdbus, mem_ptr - base_ptr);
838 * Computes size of items that will be attached to a message.
840 * @param kdbus kdbus object
841 * @param destination Well-known name or NULL. If NULL, dst_id must be supplied.
842 * @param dst_id Numeric id of recipient. Ignored if name is not NULL.
843 * @param body_size Size of message body (may be 0).
844 * @param use_memfd Flag to build memfd message.
845 * @param fds_count Number of file descriptors sent in the message.
846 * @returns size in bytes needed for the message object
849 _kdbus_compute_msg_items_size (kdbus_t *kdbus,
850 const char *destination,
853 dbus_bool_t use_memfd,
856 __u64 items_size = 0;
859 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
864 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_memfd));
867 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
871 __u64 vectors = (body_size + KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE - 1)
872 / KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
873 /* subsequent vectors -> parts of body */
874 items_size += vectors * KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
878 items_size += KDBUS_ITEM_SIZE (sizeof (int) * fds_count);
881 items_size += KDBUS_ITEM_SIZE (strlen (destination) + 1);
882 else if (KDBUS_DST_ID_BROADCAST == dst_id)
883 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_bloom_filter))
890 * Asks the bus to assign the given name to the connection.
892 * Use same flags as original dbus version with one exception below.
893 * Result flag #DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER is currently
894 * never returned by kdbus, instead DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
895 * is returned by kdbus.
897 * @param transport transport of the connection
898 * @param name the name to request
900 * @returns a DBus result code on success, -errno on error
903 _kdbus_request_name (kdbus_t *kdbus,
907 struct kdbus_cmd *cmd_name;
908 size_t len = strlen (name) + 1;
909 __u64 size = sizeof (*cmd_name) + KDBUS_ITEM_SIZE (len);
910 __u64 flags_kdbus = 0;
912 cmd_name = alloca (size);
913 cmd_name->size = size;
915 if (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)
916 flags_kdbus |= KDBUS_NAME_ALLOW_REPLACEMENT;
917 if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE))
918 flags_kdbus |= KDBUS_NAME_QUEUE;
919 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
920 flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
922 cmd_name->flags = flags_kdbus;
923 make_item_name (name, &(cmd_name->items[0]));
925 _dbus_verbose ("Request name - flags sent: 0x%llx !!!!!!!!!\n", cmd_name->flags);
927 if (ioctl (kdbus->fd, KDBUS_CMD_NAME_ACQUIRE, cmd_name) < 0)
929 _dbus_verbose ("error acquiring name '%s': %m, %d\n", name, errno);
931 return DBUS_REQUEST_NAME_REPLY_EXISTS;
932 if (errno == EALREADY)
933 return DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
936 else if ((cmd_name->return_flags & KDBUS_NAME_PRIMARY)
937 && !(cmd_name->return_flags & KDBUS_NAME_ACQUIRED))
938 return DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
940 _dbus_verbose ("Request name - received flag: 0x%llx !!!!!!!!!\n", cmd_name->flags);
942 if (cmd_name->return_flags & KDBUS_NAME_IN_QUEUE)
943 return DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
945 return DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
950 * Releases well-known name - the connections resign from the name
951 * which can be then assigned to another connection or the connection
952 * is being removed from the queue for that name
954 * @param name the name to request
955 * @param id unique id of the connection for which the name is being released
956 * @returns a DBus result code on success, -errno on error
959 _kdbus_release_name (kdbus_t *kdbus,
962 struct kdbus_cmd *cmd_name;
963 size_t len = strlen (name)+1;
964 __u64 size = sizeof (*cmd_name) + KDBUS_ITEM_SIZE (len);
966 cmd_name = alloca (size);
967 cmd_name->size = size;
969 make_item_name (name, &(cmd_name->items[0]));
971 if (ioctl (kdbus->fd, KDBUS_CMD_NAME_RELEASE, cmd_name))
973 if ((errno == ESRCH))
974 return DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
975 else if (errno == EADDRINUSE)
976 return DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
977 _dbus_verbose ("error releasing name '%s'. Error: %m, %d\n", name, errno);
981 _dbus_verbose ("Name '%s' released\n", name);
983 return DBUS_RELEASE_NAME_REPLY_RELEASED;
987 decode_connection_info (struct kdbus_info *connection_info,
988 struct nameInfo *pInfo,
989 dbus_bool_t get_sec_label)
991 struct kdbus_item *item;
993 memset (pInfo, 0, sizeof (*pInfo));
995 pInfo->uniqueId = connection_info->id;
996 pInfo->flags = connection_info->flags;
998 item = connection_info->items;
1000 while ((uint8_t *)item < ((uint8_t *)connection_info) + connection_info->size)
1004 case KDBUS_ITEM_PIDS:
1005 pInfo->processId = item->pids.pid;
1007 case KDBUS_ITEM_CREDS:
1008 pInfo->userId = item->creds.uid;
1010 case KDBUS_ITEM_SECLABEL:
1013 pInfo->sec_label_len = item->size - KDBUS_ITEM_HEADER_SIZE;
1014 if (0 != pInfo->sec_label_len)
1016 pInfo->sec_label = dbus_malloc (pInfo->sec_label_len);
1017 if (NULL == pInfo->sec_label)
1020 memcpy (pInfo->sec_label, item->data, pInfo->sec_label_len);
1026 item = KDBUS_ITEM_NEXT (item);
1032 process_connection_info_cmd (kdbus_t *kdbus,
1033 struct kdbus_cmd_info *cmd,
1034 struct nameInfo *pInfo,
1035 dbus_bool_t get_sec_label)
1038 struct kdbus_info *kdbus_info;
1043 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_CONN_INFO, cmd);
1047 pInfo->uniqueId = 0;
1052 kdbus_info = get_from_offset (kdbus, cmd->offset);
1053 ret = decode_connection_info (kdbus_info,
1061 ret = free_by_offset (kdbus, cmd->offset);
1064 _dbus_verbose ("kdbus error freeing pool: %d (%m)\n", errno);
1067 free (pInfo->sec_label);
1068 pInfo->sec_label = NULL;
1078 * In this function either id is equal to 0 AND name is not NULL,
1079 * or id is greater than 0 AND name is NULL.
1080 * Thus, condition NULL != name is equivalent to 0 == id.
1082 static struct kdbus_cmd_info *
1083 prepare_connection_info_cmd (__u64 id,
1085 dbus_bool_t get_sec_label)
1087 struct kdbus_cmd_info *cmd;
1088 __u64 size = sizeof (*cmd);
1091 size += KDBUS_ITEM_SIZE (strlen (name) + 1);
1093 cmd = dbus_malloc (size);
1100 make_item_name (name, &(cmd->items[0]));
1102 cmd->attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_PIDS;
1104 cmd->attach_flags |= KDBUS_ATTACH_SECLABEL;
1112 * Gets connection info for the given unique id.
1114 * @param kdbus kdbus object
1115 * @param id unique id to query for
1116 * @param get_sec_label #TRUE if sec_label field in pInfo should be filled
1117 * @param pInfo nameInfo structure address to store info about the name
1118 * @return 0 on success, errno if failed
1120 * @note If you specify #TRUE in get_sec_label param, you must free
1121 * pInfo.sec_label with dbus_free() after use.
1124 _kdbus_connection_info_by_id (kdbus_t *kdbus,
1126 dbus_bool_t get_sec_label,
1127 struct nameInfo *pInfo)
1129 struct kdbus_cmd_info *cmd = prepare_connection_info_cmd (id, NULL, get_sec_label);
1131 return process_connection_info_cmd (kdbus, cmd, pInfo, get_sec_label);
1135 * Gets connection info for the given name
1137 * @param kdbus kdbus object
1138 * @param name name to query for
1139 * @param get_sec_label #TRUE if sec_label field in pInfo should be filled
1140 * @param pInfo nameInfo structure address to store info about the name
1141 * @return 0 on success, errno if failed
1143 * @note If you specify #TRUE in get_sec_label param, you must free
1144 * pInfo.sec_label with dbus_free() after use.
1147 _kdbus_connection_info_by_name (kdbus_t *kdbus,
1149 dbus_bool_t get_sec_label,
1150 struct nameInfo *pInfo)
1152 struct kdbus_cmd_info *cmd;
1154 /* if name starts with ":1." it is a unique name and should be send as number */
1155 if ((name[0] == ':') && (name[1] == '1') && (name[2] == '.'))
1157 return _kdbus_connection_info_by_id (kdbus,
1158 strtoull (&name[3], NULL, 10),
1163 cmd = prepare_connection_info_cmd (0, name, get_sec_label);
1165 return process_connection_info_cmd (kdbus, cmd, pInfo, get_sec_label);
1169 * Removes match rule in kdbus on behalf of sender of the message
1170 * @param kdbus kdbus object
1171 * @param cookie cookie of the rules to be removed
1174 _kdbus_remove_match (kdbus_t *kdbus,
1177 struct kdbus_cmd_match cmd;
1179 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
1181 cmd.cookie = cookie;
1182 cmd.size = sizeof (struct kdbus_cmd_match);
1185 if (safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_REMOVE, &cmd) != 0)
1191 /************************* BLOOM FILTERS ***********************/
1194 * Macros for SipHash algorithm
1196 #define ROTL(x,b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
1198 #define U32TO8_LE(p, v) \
1199 (p)[0] = (unsigned char)((v) ); (p)[1] = (unsigned char)((v) >> 8); \
1200 (p)[2] = (unsigned char)((v) >> 16); (p)[3] = (unsigned char)((v) >> 24);
1202 #define U64TO8_LE(p, v) \
1203 U32TO8_LE((p), (uint32_t)((v) )); \
1204 U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
1206 #define U8TO64_LE(p) \
1207 (((uint64_t)((p)[0]) ) | \
1208 ((uint64_t)((p)[1]) << 8) | \
1209 ((uint64_t)((p)[2]) << 16) | \
1210 ((uint64_t)((p)[3]) << 24) | \
1211 ((uint64_t)((p)[4]) << 32) | \
1212 ((uint64_t)((p)[5]) << 40) | \
1213 ((uint64_t)((p)[6]) << 48) | \
1214 ((uint64_t)((p)[7]) << 56))
1218 v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
1219 v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \
1220 v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \
1221 v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
1226 * Hash keys for bloom filters
1228 static const unsigned char hash_keys[8][16] =
1230 {0xb9,0x66,0x0b,0xf0,0x46,0x70,0x47,0xc1,0x88,0x75,0xc4,0x9c,0x54,0xb9,0xbd,0x15},
1231 {0xaa,0xa1,0x54,0xa2,0xe0,0x71,0x4b,0x39,0xbf,0xe1,0xdd,0x2e,0x9f,0xc5,0x4a,0x3b},
1232 {0x63,0xfd,0xae,0xbe,0xcd,0x82,0x48,0x12,0xa1,0x6e,0x41,0x26,0xcb,0xfa,0xa0,0xc8},
1233 {0x23,0xbe,0x45,0x29,0x32,0xd2,0x46,0x2d,0x82,0x03,0x52,0x28,0xfe,0x37,0x17,0xf5},
1234 {0x56,0x3b,0xbf,0xee,0x5a,0x4f,0x43,0x39,0xaf,0xaa,0x94,0x08,0xdf,0xf0,0xfc,0x10},
1235 {0x31,0x80,0xc8,0x73,0xc7,0xea,0x46,0xd3,0xaa,0x25,0x75,0x0f,0x9e,0x4c,0x09,0x29},
1236 {0x7d,0xf7,0x18,0x4b,0x7b,0xa4,0x44,0xd5,0x85,0x3c,0x06,0xe0,0x65,0x53,0x96,0x6d},
1237 {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35}
1244 _g_siphash24 (unsigned char out[8],
1247 const unsigned char k[16])
1249 uint64_t v0 = 0x736f6d6570736575ULL;
1250 uint64_t v1 = 0x646f72616e646f6dULL;
1251 uint64_t v2 = 0x6c7967656e657261ULL;
1252 uint64_t v3 = 0x7465646279746573ULL;
1254 uint64_t k0 = U8TO64_LE (k);
1255 uint64_t k1 = U8TO64_LE (k + 8);
1257 const unsigned char *in = _in;
1258 const unsigned char *end = in + inlen - (inlen % sizeof (uint64_t));
1259 const int left = inlen & 7;
1260 b = ((uint64_t) inlen) << 56;
1266 for (; in != end; in += 8)
1277 case 7: b |= ((uint64_t) in[6]) << 48;
1278 case 6: b |= ((uint64_t) in[5]) << 40;
1279 case 5: b |= ((uint64_t) in[4]) << 32;
1280 case 4: b |= ((uint64_t) in[3]) << 24;
1281 case 3: b |= ((uint64_t) in[2]) << 16;
1282 case 2: b |= ((uint64_t) in[1]) << 8;
1283 case 1: b |= ((uint64_t) in[0]); break;
1297 b = v0 ^ v1 ^ v2 ^ v3;
1302 _kdbus_bloom_add_data (kdbus_t *kdbus,
1303 kdbus_bloom_data_t *bloom_data,
1307 unsigned char hash[8];
1309 unsigned int bytes_num = 0;
1310 unsigned int cnt_1, cnt_2;
1311 unsigned int hash_index = 0;
1315 bit_num = kdbus->bloom.size * 8;
1318 bytes_num = ((__builtin_clzll (bit_num) ^ 63U) + 7) / 8;
1320 for (cnt_1 = 0, hash_index = 0; cnt_1 < kdbus->bloom.n_hash; cnt_1++)
1323 for (cnt_2 = 0; cnt_2 < bytes_num; cnt_2++)
1327 _g_siphash24 (hash, data, data_size, hash_keys[hash_index++]);
1331 p = (p << 8ULL) | (uint64_t) hash[8 - c];
1336 bloom_data[p >> 6] |= 1ULL << (p & 63);