chiark / gitweb /
libsystemd-bus: catch up with latest kdbus changes
[elogind.git] / src / libsystemd-bus / bus-control.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <stddef.h>
27 #include <errno.h>
28
29 #include "strv.h"
30
31 #include "sd-bus.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-control.h"
35 #include "bus-bloom.h"
36 #include "bus-util.h"
37
38 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
39         int r;
40
41         assert_return(bus, -EINVAL);
42         assert_return(unique, -EINVAL);
43         assert_return(!bus_pid_changed(bus), -ECHILD);
44
45         r = bus_ensure_running(bus);
46         if (r < 0)
47                 return r;
48
49         *unique = bus->unique_name;
50         return 0;
51 }
52
53 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
54         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
55         uint32_t ret;
56         int r;
57
58         assert_return(bus, -EINVAL);
59         assert_return(name, -EINVAL);
60         assert_return(bus->bus_client, -EINVAL);
61         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
62         assert_return(!bus_pid_changed(bus), -ECHILD);
63
64         if (bus->is_kernel) {
65                 struct kdbus_cmd_name *n;
66                 size_t l;
67
68                 l = strlen(name);
69                 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
70                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
71                 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
72                 memcpy(n->name, name, l+1);
73
74 #ifdef HAVE_VALGRIND_MEMCHECK_H
75                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
76 #endif
77
78                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
79                 if (r < 0) {
80                         if (errno == -EALREADY)
81                                 return SD_BUS_NAME_ALREADY_OWNER;
82
83                         if (errno == -EEXIST)
84                                 return SD_BUS_NAME_EXISTS;
85
86                         return -errno;
87                 }
88
89                 if (n->flags & KDBUS_NAME_IN_QUEUE)
90                         return SD_BUS_NAME_IN_QUEUE;
91
92                 return SD_BUS_NAME_PRIMARY_OWNER;
93         } else {
94                 r = sd_bus_call_method(
95                                 bus,
96                                 "org.freedesktop.DBus",
97                                 "/",
98                                 "org.freedesktop.DBus",
99                                 "RequestName",
100                                 NULL,
101                                 &reply,
102                                 "su",
103                                 name,
104                                 flags);
105                 if (r < 0)
106                         return r;
107
108                 r = sd_bus_message_read(reply, "u", &ret);
109                 if (r < 0)
110                         return r;
111
112                 return ret;
113         }
114 }
115
116 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
117         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
118         uint32_t ret;
119         int r;
120
121         assert_return(bus, -EINVAL);
122         assert_return(name, -EINVAL);
123         assert_return(bus->bus_client, -EINVAL);
124         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
125         assert_return(!bus_pid_changed(bus), -ECHILD);
126
127         if (bus->is_kernel) {
128                 struct kdbus_cmd_name *n;
129                 size_t l;
130
131                 l = strlen(name);
132                 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
133                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
134                 memcpy(n->name, name, l+1);
135
136 #ifdef HAVE_VALGRIND_MEMCHECK_H
137                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
138 #endif
139                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
140                 if (r < 0)
141                         return -errno;
142
143                 return n->flags;
144         } else {
145                 r = sd_bus_call_method(
146                                 bus,
147                                 "org.freedesktop.DBus",
148                                 "/",
149                                 "org.freedesktop.DBus",
150                                 "ReleaseName",
151                                 NULL,
152                                 &reply,
153                                 "s",
154                                 name);
155                 if (r < 0)
156                         return r;
157
158                 r = sd_bus_message_read(reply, "u", &ret);
159                 if (r < 0)
160                         return r;
161         }
162
163         return ret;
164 }
165
166 _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
167         _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
168         char **x = NULL;
169         int r;
170
171         assert_return(bus, -EINVAL);
172         assert_return(l, -EINVAL);
173         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
174         assert_return(!bus_pid_changed(bus), -ECHILD);
175
176         if (bus->is_kernel) {
177                 _cleanup_free_ struct kdbus_cmd_name_list *cmd = NULL;
178                 struct kdbus_name_list *name_list;
179                 struct kdbus_cmd_name *name;
180
181                 cmd = malloc0(sizeof(struct kdbus_cmd_name_list));
182                 if (!cmd)
183                         return -ENOMEM;
184
185                 cmd->size = sizeof(struct kdbus_cmd_name_list);
186                 cmd->flags = KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES;
187
188                 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, cmd);
189                 if (r < 0)
190                         return -errno;
191
192                 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
193
194                 KDBUS_PART_FOREACH(name, name_list, names) {
195                         char *n;
196
197                         if (name->size > sizeof(*name))
198                                 n = name->name;
199                         else
200                                 asprintf(&n, ":1.%llu", (unsigned long long) name->id);
201
202                         r = strv_extend(&x, n);
203                         if (r < 0)
204                                 return -ENOMEM;
205                 }
206
207                 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
208                 if (r < 0)
209                         return -errno;
210
211                 *l = x;
212         } else {
213                 r = sd_bus_call_method(
214                                 bus,
215                                 "org.freedesktop.DBus",
216                                 "/",
217                                 "org.freedesktop.DBus",
218                                 "ListNames",
219                                 NULL,
220                                 &reply1,
221                                 NULL);
222                 if (r < 0)
223                         return r;
224
225                 r = sd_bus_call_method(
226                                 bus,
227                                 "org.freedesktop.DBus",
228                                 "/",
229                                 "org.freedesktop.DBus",
230                                 "ListActivatableNames",
231                                 NULL,
232                                 &reply2,
233                                 NULL);
234                 if (r < 0)
235                         return r;
236
237                 r = bus_message_read_strv_extend(reply1, &x);
238                 if (r < 0) {
239                         strv_free(x);
240                         return r;
241                 }
242
243                 r = bus_message_read_strv_extend(reply2, &x);
244                 if (r < 0) {
245                         strv_free(x);
246                         return r;
247                 }
248
249                 *l = strv_uniq(x);
250         }
251
252         return 0;
253 }
254
255 static int bus_get_owner_dbus(
256                 sd_bus *bus,
257                 const char *name,
258                 uint64_t mask,
259                 sd_bus_creds **creds) {
260
261         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
262         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
263         const char *unique = NULL;
264         pid_t pid = 0;
265         int r;
266
267         /* Only query the owner if the caller wants to know it or if
268          * the caller just wants to check whether a name exists */
269         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
270                 r = sd_bus_call_method(
271                                 bus,
272                                 "org.freedesktop.DBus",
273                                 "/",
274                                 "org.freedesktop.DBus",
275                                 "GetNameOwner",
276                                 NULL,
277                                 &reply_unique,
278                                 "s",
279                                 name);
280                 if (r < 0)
281                         return r;
282
283                 r = sd_bus_message_read(reply_unique, "s", &unique);
284                 if (r < 0)
285                         return r;
286         }
287
288         if (mask != 0) {
289                 c = bus_creds_new();
290                 if (!c)
291                         return -ENOMEM;
292
293                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
294                         c->unique_name = strdup(unique);
295                         if (!c->unique_name)
296                                 return -ENOMEM;
297
298                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
299                 }
300
301                 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
302                             SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
303                             SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
304                             SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
305                             SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
306                         uint32_t u;
307
308                         r = sd_bus_call_method(
309                                         bus,
310                                         "org.freedesktop.DBus",
311                                         "/",
312                                         "org.freedesktop.DBus",
313                                         "GetConnectionUnixProcessID",
314                                         NULL,
315                                         &reply,
316                                         "s",
317                                         unique ? unique : name);
318                         if (r < 0)
319                                 return r;
320
321                         r = sd_bus_message_read(reply, "u", &u);
322                         if (r < 0)
323                                 return r;
324
325                         pid = u;
326                         if (mask & SD_BUS_CREDS_PID) {
327                                 c->pid = u;
328                                 c->mask |= SD_BUS_CREDS_PID;
329                         }
330
331                         reply = sd_bus_message_unref(reply);
332                 }
333
334                 if (mask & SD_BUS_CREDS_UID) {
335                         uint32_t u;
336
337                         r = sd_bus_call_method(
338                                         bus,
339                                         "org.freedesktop.DBus",
340                                         "/",
341                                         "org.freedesktop.DBus",
342                                         "GetConnectionUnixUser",
343                                         NULL,
344                                         &reply,
345                                         "s",
346                                         unique ? unique : name);
347                         if (r < 0)
348                                 return r;
349
350                         r = sd_bus_message_read(reply, "u", &u);
351                         if (r < 0)
352                                 return r;
353
354                         c->uid = u;
355                         c->mask |= SD_BUS_CREDS_UID;
356
357                         reply = sd_bus_message_unref(reply);
358                 }
359
360                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
361                         const void *p;
362                         size_t sz;
363
364                         r = sd_bus_call_method(
365                                         bus,
366                                         "org.freedesktop.DBus",
367                                         "/",
368                                         "org.freedesktop.DBus",
369                                         "GetConnectionSELinuxSecurityContext",
370                                         NULL,
371                                         &reply,
372                                         "s",
373                                         unique ? unique : name);
374                         if (r < 0)
375                                 return r;
376
377                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
378                         if (r < 0)
379                                 return r;
380
381                         c->label = strndup(p, sz);
382                         if (!c->label)
383                                 return -ENOMEM;
384
385                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
386                 }
387
388                 r = bus_creds_add_more(c, mask, pid, 0);
389                 if (r < 0)
390                         return r;
391         }
392
393         if (creds) {
394                 *creds = c;
395                 c = NULL;
396         }
397
398         return 0;
399 }
400
401 static int bus_get_owner_kdbus(
402                 sd_bus *bus,
403                 const char *name,
404                 uint64_t mask,
405                 sd_bus_creds **creds) {
406
407         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
408         struct kdbus_cmd_conn_info *cmd;
409         struct kdbus_conn_info *conn_info;
410         struct kdbus_item *item;
411         size_t size;
412         uint64_t m, id;
413         int r;
414
415         r = bus_kernel_parse_unique_name(name, &id);
416         if (r < 0)
417                 return r;
418         if (r > 0) {
419                 size = offsetof(struct kdbus_cmd_conn_info, name);
420                 cmd = alloca0(size);
421                 cmd->id = id;
422         } else {
423                 size = offsetof(struct kdbus_cmd_conn_info, name) + strlen(name) + 1;
424                 cmd = alloca0(size);
425                 strcpy(cmd->name, name);
426         }
427
428         cmd->size = size;
429         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
430         if (r < 0)
431                 return -errno;
432
433         conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
434
435         c = bus_creds_new();
436         if (!c)
437                 return -ENOMEM;
438
439         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
440                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
441                         return -ENOMEM;
442
443                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
444         }
445
446         KDBUS_PART_FOREACH(item, conn_info, items) {
447
448                 switch (item->type) {
449
450                 case KDBUS_ITEM_CREDS:
451                         m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID |
452                              SD_BUS_CREDS_TID | SD_BUS_CREDS_PID_STARTTIME) & mask;
453
454                         if (m) {
455                                 c->uid = item->creds.uid;
456                                 c->pid = item->creds.pid;
457                                 c->gid = item->creds.gid;
458                                 c->tid = item->creds.tid;
459                                 c->pid_starttime = item->creds.starttime;
460                                 c->mask |= m;
461                         }
462                         break;
463
464                 case KDBUS_ITEM_PID_COMM:
465                         if (mask & SD_BUS_CREDS_COMM) {
466                                 c->comm = strdup(item->str);
467                                 if (!c->comm) {
468                                         r = -ENOMEM;
469                                         goto fail;
470                                 }
471
472                                 c->mask |= SD_BUS_CREDS_COMM;
473                         }
474                         break;
475
476                 case KDBUS_ITEM_TID_COMM:
477                         if (mask & SD_BUS_CREDS_TID_COMM) {
478                                 c->tid_comm = strdup(item->str);
479                                 if (!c->tid_comm) {
480                                         r = -ENOMEM;
481                                         goto fail;
482                                 }
483
484                                 c->mask |= SD_BUS_CREDS_TID_COMM;
485                         }
486                         break;
487
488                 case KDBUS_ITEM_EXE:
489                         if (mask & SD_BUS_CREDS_EXE) {
490                                 c->exe = strdup(item->str);
491                                 if (!c->exe) {
492                                         r = -ENOMEM;
493                                         goto fail;
494                                 }
495
496                                 c->mask |= SD_BUS_CREDS_EXE;
497                         }
498                         break;
499
500                 case KDBUS_ITEM_CMDLINE:
501                         if (mask & SD_BUS_CREDS_CMDLINE) {
502                                 c->cmdline_size = item->size - KDBUS_PART_HEADER_SIZE;
503                                 c->cmdline = memdup(item->data, c->cmdline_size);
504                                 if (!c->cmdline) {
505                                         r = -ENOMEM;
506                                         goto fail;
507                                 }
508
509                                 c->mask |= SD_BUS_CREDS_CMDLINE;
510                         }
511                         break;
512
513                 case KDBUS_ITEM_CGROUP:
514                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
515                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
516                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
517
518                         if (m) {
519                                 c->cgroup = strdup(item->str);
520                                 if (!c->cgroup) {
521                                         r = -ENOMEM;
522                                         goto fail;
523                                 }
524
525                                 c->mask |= m;
526                         }
527                         break;
528
529                 case KDBUS_ITEM_CAPS:
530                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
531                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
532
533                         if (m) {
534                                 c->capability_size = item->size - KDBUS_PART_HEADER_SIZE;
535                                 c->capability = memdup(item->data, c->capability_size);
536                                 if (!c->capability) {
537                                         r = -ENOMEM;
538                                         goto fail;
539                                 }
540
541                                 c->mask |= m;
542                         }
543                         break;
544
545                 case KDBUS_ITEM_SECLABEL:
546                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
547                                 c->label = strdup(item->str);
548                                 if (!c->label) {
549                                         r = -ENOMEM;
550                                         goto fail;
551                                 }
552
553                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
554                         }
555                         break;
556
557                 case KDBUS_ITEM_AUDIT:
558                         m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
559
560                         if (m) {
561                                 c->audit_session_id = item->audit.sessionid;
562                                 c->audit_login_uid = item->audit.loginuid;
563                                 c->mask |= m;
564                         }
565                         break;
566
567                 case KDBUS_ITEM_NAMES:
568                         if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
569                                 c->well_known_names_size = item->size - KDBUS_PART_HEADER_SIZE;
570                                 c->well_known_names = memdup(item->data, c->well_known_names_size);
571                                 if (!c->well_known_names) {
572                                         r = -ENOMEM;
573                                         goto fail;
574                                 }
575
576                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
577                         }
578                         break;
579                 }
580         }
581
582         if (creds) {
583                 *creds = c;
584                 c = NULL;
585         }
586
587         r = 0;
588
589 fail:
590         ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
591         return r;
592 }
593
594 _public_ int sd_bus_get_owner(
595                 sd_bus *bus,
596                 const char *name,
597                 uint64_t mask,
598                 sd_bus_creds **creds) {
599
600         assert_return(bus, -EINVAL);
601         assert_return(name, -EINVAL);
602         assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
603         assert_return(mask == 0 || creds, -EINVAL);
604         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
605         assert_return(!bus_pid_changed(bus), -ECHILD);
606
607         if (bus->is_kernel)
608                 return bus_get_owner_kdbus(bus, name, mask, creds);
609         else
610                 return bus_get_owner_dbus(bus, name, mask, creds);
611 }
612
613 static int add_name_change_match(sd_bus *bus,
614                                  uint64_t cookie,
615                                  const char *name,
616                                  const char *old_owner,
617                                  const char *new_owner) {
618
619         uint64_t name_id = 0, old_owner_id = 0, new_owner_id = 0;
620         int is_name_id = -1, r;
621         struct kdbus_item *item;
622
623         assert(bus);
624
625         /* If we encounter a match that could match against
626          * NameOwnerChanged messages, then we need to create
627          * KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE} and
628          * KDBUS_MATCH_ID_{ADD,REMOVE} matches for it, possibly
629          * multiple if the match is underspecified.
630          *
631          * The NameOwnerChanged signals take three parameters with
632          * unique or well-known names, but only some forms actually
633          * exist:
634          *
635          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_MATCH_NAME_ADD
636          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_MATCH_NAME_REMOVE
637          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_MATCH_NAME_CHANGE
638          * UNIQUE, "", UNIQUE          â†’ KDBUS_MATCH_ID_ADD
639          * UNIQUE, UNIQUE, ""          â†’ KDBUS_MATCH_ID_REMOVE
640          *
641          * For the latter two the two unique names must be identical.
642          *
643          * */
644
645         if (name) {
646                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
647                 if (is_name_id < 0)
648                         return 0;
649         }
650
651         if (old_owner) {
652                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
653                 if (r < 0)
654                         return 0;
655                 if (r == 0)
656                         return 0;
657                 if (is_name_id > 0 && old_owner_id != name_id)
658                         return 0;
659         }
660
661         if (new_owner) {
662                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
663                 if (r < 0)
664                         return r;
665                 if (r == 0)
666                         return 0;
667                 if (is_name_id > 0 && new_owner_id != name_id)
668                         return 0;
669         }
670
671         if (is_name_id <= 0) {
672                 struct kdbus_cmd_match *m;
673                 size_t sz, l;
674
675                 /* If the name argument is missing or is a well-known
676                  * name, then add KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE}
677                  * matches for it */
678
679                 l = name ? strlen(name) : 0;
680
681                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
682                             offsetof(struct kdbus_item, name_change) +
683                             offsetof(struct kdbus_notify_name_change, name) +
684                             l+1);
685
686                 m = alloca0(sz);
687                 m->size = sz;
688                 m->cookie = cookie;
689                 m->src_id = KDBUS_SRC_ID_KERNEL;
690
691                 item = m->items;
692                 item->size =
693                         offsetof(struct kdbus_item, name_change) +
694                         offsetof(struct kdbus_notify_name_change, name) +
695                         l+1;
696
697                 item->name_change.old_id = old_owner_id;
698                 item->name_change.new_id = new_owner_id;
699
700                 if (name)
701                         strcpy(item->name_change.name, name);
702
703                 /* If the old name is unset or empty, then
704                  * this can match against added names */
705                 if (!old_owner || old_owner[0] == 0) {
706                         item->type = KDBUS_MATCH_NAME_ADD;
707
708                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
709                         if (r < 0)
710                                 return -errno;
711                 }
712
713                 /* If the new name is unset or empty, then
714                  * this can match against removed names */
715                 if (!new_owner || new_owner[0] == 0) {
716                         item->type = KDBUS_MATCH_NAME_REMOVE;
717
718                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
719                         if (r < 0)
720                                 return -errno;
721                 }
722
723                 /* If the neither name is explicitly set to
724                  * the empty string, then this can match
725                  * agains changed names */
726                 if (!(old_owner && old_owner[0] == 0) &&
727                     !(new_owner && new_owner[0] == 0)) {
728                         item->type = KDBUS_MATCH_NAME_CHANGE;
729
730                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
731                         if (r < 0)
732                                 return -errno;
733                 }
734         }
735
736         if (is_name_id != 0) {
737                 struct kdbus_cmd_match *m;
738                 uint64_t sz;
739
740                 /* If the name argument is missing or is a unique
741                  * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
742                  * for it */
743
744                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
745                             offsetof(struct kdbus_item, id_change) +
746                             sizeof(struct kdbus_notify_id_change));
747
748                 m = alloca0(sz);
749                 m->size = sz;
750                 m->cookie = cookie;
751                 m->src_id = KDBUS_SRC_ID_KERNEL;
752
753                 item = m->items;
754                 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
755                 item->id_change.id = name_id;
756
757                 /* If the old name is unset or empty, then this can
758                  * match against added ids */
759                 if (!old_owner || old_owner[0] == 0) {
760                         item->type = KDBUS_MATCH_ID_ADD;
761
762                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
763                         if (r < 0)
764                                 return -errno;
765                 }
766
767                 /* If thew new name is unset or empty, then this can
768                 match against removed ids */
769                 if (!new_owner || new_owner[0] == 0) {
770                         item->type = KDBUS_MATCH_ID_REMOVE;
771
772                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
773                         if (r < 0)
774                                 return -errno;
775                 }
776         }
777
778         return 0;
779 }
780
781 int bus_add_match_internal(
782                 sd_bus *bus,
783                 const char *match,
784                 struct bus_match_component *components,
785                 unsigned n_components,
786                 uint64_t cookie) {
787
788         int r;
789
790         assert(bus);
791         assert(match);
792
793         if (bus->is_kernel) {
794                 struct kdbus_cmd_match *m;
795                 struct kdbus_item *item;
796                 uint64_t bloom[BLOOM_SIZE/8];
797                 size_t sz;
798                 const char *sender = NULL;
799                 size_t sender_length = 0;
800                 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
801                 bool using_bloom = false;
802                 unsigned i;
803                 bool matches_name_change = true;
804                 const char *name_change_arg[3] = {};
805
806                 zero(bloom);
807
808                 sz = offsetof(struct kdbus_cmd_match, items);
809
810                 for (i = 0; i < n_components; i++) {
811                         struct bus_match_component *c = &components[i];
812
813                         switch (c->type) {
814
815                         case BUS_MATCH_SENDER:
816                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
817                                         matches_name_change = false;
818
819                                 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
820                                 if (r < 0)
821                                         return r;
822
823                                 if (r > 0) {
824                                         sender = c->value_str;
825                                         sender_length = strlen(sender);
826                                         sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
827                                 }
828
829                                 break;
830
831                         case BUS_MATCH_MESSAGE_TYPE:
832                                 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
833                                         matches_name_change = false;
834
835                                 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
836                                 using_bloom = true;
837                                 break;
838
839                         case BUS_MATCH_INTERFACE:
840                                 if (!streq(c->value_str, "org.freedesktop.DBus"))
841                                         matches_name_change = false;
842
843                                 bloom_add_pair(bloom, "interface", c->value_str);
844                                 using_bloom = true;
845                                 break;
846
847                         case BUS_MATCH_MEMBER:
848                                 if (!streq(c->value_str, "NameOwnerChanged"))
849                                         matches_name_change = false;
850
851                                 bloom_add_pair(bloom, "member", c->value_str);
852                                 using_bloom = true;
853                                 break;
854
855                         case BUS_MATCH_PATH:
856                                 if (!streq(c->value_str, "/org/freedesktop/DBus"))
857                                         matches_name_change = false;
858
859                                 bloom_add_pair(bloom, "path", c->value_str);
860                                 using_bloom = true;
861                                 break;
862
863                         case BUS_MATCH_PATH_NAMESPACE:
864                                 if (!streq(c->value_str, "/")) {
865                                         bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
866                                         using_bloom = true;
867                                 }
868                                 break;
869
870                         case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
871                                 char buf[sizeof("arg")-1 + 2 + 1];
872
873                                 if (c->type - BUS_MATCH_ARG < 3)
874                                         name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
875
876                                 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
877                                 bloom_add_pair(bloom, buf, c->value_str);
878                                 using_bloom = true;
879                                 break;
880                         }
881
882                         case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
883                                 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
884
885                                 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
886                                 bloom_add_pair(bloom, buf, c->value_str);
887                                 using_bloom = true;
888                                 break;
889                         }
890
891                         case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
892                                 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
893
894                                 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
895                                 bloom_add_pair(bloom, buf, c->value_str);
896                                 using_bloom = true;
897                                 break;
898                         }
899
900                         case BUS_MATCH_DESTINATION:
901                                 /* The bloom filter does not include
902                                    the destination, since it is only
903                                    available for broadcast messages
904                                    which do not carry a destination
905                                    since they are undirected. */
906                                 break;
907
908                         case BUS_MATCH_ROOT:
909                         case BUS_MATCH_VALUE:
910                         case BUS_MATCH_LEAF:
911                         case _BUS_MATCH_NODE_TYPE_MAX:
912                         case _BUS_MATCH_NODE_TYPE_INVALID:
913                                 assert_not_reached("Invalid match type?");
914                         }
915                 }
916
917                 if (using_bloom)
918                         sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
919
920                 m = alloca0(sz);
921                 m->size = sz;
922                 m->cookie = cookie;
923                 m->src_id = src_id;
924
925                 item = m->items;
926
927                 if (using_bloom) {
928                         item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
929                         item->type = KDBUS_MATCH_BLOOM;
930                         memcpy(item->data64, bloom, BLOOM_SIZE);
931
932                         item = KDBUS_PART_NEXT(item);
933                 }
934
935                 if (sender) {
936                         item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
937                         item->type = KDBUS_MATCH_SRC_NAME;
938                         memcpy(item->str, sender, sender_length + 1);
939                 }
940
941                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
942                 if (r < 0)
943                         return -errno;
944
945                 if (matches_name_change) {
946
947                         /* If this match could theoretically match
948                          * NameOwnerChanged messages, we need to
949                          * install a second non-bloom filter explitly
950                          * for it */
951
952                         r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
953                         if (r < 0)
954                                 return r;
955                 }
956
957                 return 0;
958         } else
959                 return sd_bus_call_method(
960                                 bus,
961                                 "org.freedesktop.DBus",
962                                 "/",
963                                 "org.freedesktop.DBus",
964                                 "AddMatch",
965                                 NULL,
966                                 NULL,
967                                 "s",
968                                 match);
969 }
970
971 int bus_remove_match_internal(
972                 sd_bus *bus,
973                 const char *match,
974                 uint64_t cookie) {
975
976         int r;
977
978         assert(bus);
979         assert(match);
980
981         if (bus->is_kernel) {
982                 struct kdbus_cmd_match m;
983
984                 zero(m);
985                 m.size = offsetof(struct kdbus_cmd_match, items);
986                 m.cookie = cookie;
987
988                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
989                 if (r < 0)
990                         return -errno;
991
992                 return 0;
993
994         } else {
995                 return sd_bus_call_method(
996                                 bus,
997                                 "org.freedesktop.DBus",
998                                 "/",
999                                 "org.freedesktop.DBus",
1000                                 "RemoveMatch",
1001                                 NULL,
1002                                 NULL,
1003                                 "s",
1004                                 match);
1005         }
1006 }
1007
1008 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1009         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1010         const char *mid;
1011         int r;
1012
1013         assert_return(bus, -EINVAL);
1014         assert_return(name, -EINVAL);
1015         assert_return(machine, -EINVAL);
1016         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1017         assert_return(!bus_pid_changed(bus), -ECHILD);
1018
1019         if (streq_ptr(name, bus->unique_name))
1020                 return sd_id128_get_machine(machine);
1021
1022         r = sd_bus_message_new_method_call(
1023                         bus,
1024                         name,
1025                         "/",
1026                         "org.freedesktop.DBus.Peer",
1027                         "GetMachineId", &m);
1028         if (r < 0)
1029                 return r;
1030
1031         r = sd_bus_message_set_no_auto_start(m, true);
1032         if (r < 0)
1033                 return r;
1034
1035         r = sd_bus_call(bus, m, 0, NULL, &reply);
1036         if (r < 0)
1037                 return r;
1038
1039         r = sd_bus_message_read(reply, "s", &mid);
1040         if (r < 0)
1041                 return r;
1042
1043         return sd_id128_from_string(mid, machine);
1044 }