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