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