]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-control.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-control.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
de1c301e
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
349cc4a5 21#if HAVE_VALGRIND_MEMCHECK_H
75722f1d
LP
22#include <valgrind/memcheck.h>
23#endif
24
de1c301e 25#include <errno.h>
cf0fbc49 26#include <stddef.h>
de1c301e 27
de1c301e 28#include "sd-bus.h"
07630cea 29
b5efdb8a 30#include "alloc-util.h"
07630cea 31#include "bus-bloom.h"
ee104e11 32#include "bus-control.h"
de1c301e
LP
33#include "bus-internal.h"
34#include "bus-message.h"
057171ef 35#include "bus-util.h"
430f0182 36#include "capability-util.h"
15a5e950 37#include "stdio-util.h"
07630cea
LP
38#include "string-util.h"
39#include "strv.h"
ee104e11 40#include "user-util.h"
de1c301e 41
d9f644e2 42_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
20902f3e
LP
43 int r;
44
9bb058a1
LS
45 assert_return(bus, -EINVAL);
46 assert_return(unique, -EINVAL);
47 assert_return(!bus_pid_changed(bus), -ECHILD);
20902f3e 48
33c62dcb
LP
49 if (!bus->bus_client)
50 return -EINVAL;
51
20902f3e
LP
52 r = bus_ensure_running(bus);
53 if (r < 0)
54 return r;
de1c301e 55
20902f3e
LP
56 *unique = bus->unique_name;
57 return 0;
de1c301e
LP
58}
59
29a07cdb 60static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
4afd3348 61 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
29a07cdb 62 uint32_t ret, param = 0;
de1c301e
LP
63 int r;
64
e7176abb
LP
65 assert(bus);
66 assert(name);
67
29a07cdb
LP
68 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
69 param |= BUS_NAME_ALLOW_REPLACEMENT;
70 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
71 param |= BUS_NAME_REPLACE_EXISTING;
72 if (!(flags & SD_BUS_NAME_QUEUE))
73 param |= BUS_NAME_DO_NOT_QUEUE;
74
e7176abb
LP
75 r = sd_bus_call_method(
76 bus,
77 "org.freedesktop.DBus",
cd789fdf 78 "/org/freedesktop/DBus",
e7176abb
LP
79 "org.freedesktop.DBus",
80 "RequestName",
81 NULL,
82 &reply,
83 "su",
84 name,
29a07cdb 85 param);
e7176abb
LP
86 if (r < 0)
87 return r;
88
89 r = sd_bus_message_read(reply, "u", &ret);
90 if (r < 0)
91 return r;
92
0461f8cd 93 if (ret == BUS_NAME_ALREADY_OWNER)
e7176abb 94 return -EALREADY;
0461f8cd 95 else if (ret == BUS_NAME_EXISTS)
e7176abb 96 return -EEXIST;
0461f8cd 97 else if (ret == BUS_NAME_IN_QUEUE)
e7176abb 98 return 0;
c0a09132
LP
99 else if (ret == BUS_NAME_PRIMARY_OWNER)
100 return 1;
e7176abb 101
c0a09132 102 return -EIO;
e7176abb
LP
103}
104
29a07cdb 105_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
9bb058a1
LS
106 assert_return(bus, -EINVAL);
107 assert_return(name, -EINVAL);
9bb058a1 108 assert_return(!bus_pid_changed(bus), -ECHILD);
29a07cdb 109 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
45fd5e4d
LP
110 assert_return(service_name_is_valid(name), -EINVAL);
111 assert_return(name[0] != ':', -EINVAL);
de1c301e 112
33c62dcb
LP
113 if (!bus->bus_client)
114 return -EINVAL;
115
210a6882
LP
116 /* Don't allow requesting the special driver and local names */
117 if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
118 return -EINVAL;
119
a3d59cd1
LP
120 if (!BUS_IS_OPEN(bus->state))
121 return -ENOTCONN;
122
a132bef0 123 return bus_request_name_dbus1(bus, name, flags);
de1c301e
LP
124}
125
e7176abb 126static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
4afd3348 127 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
e7176abb 128 uint32_t ret;
de1c301e
LP
129 int r;
130
e7176abb
LP
131 assert(bus);
132 assert(name);
133
134 r = sd_bus_call_method(
135 bus,
136 "org.freedesktop.DBus",
cd789fdf 137 "/org/freedesktop/DBus",
e7176abb
LP
138 "org.freedesktop.DBus",
139 "ReleaseName",
140 NULL,
141 &reply,
142 "s",
143 name);
144 if (r < 0)
145 return r;
146
147 r = sd_bus_message_read(reply, "u", &ret);
148 if (r < 0)
149 return r;
0461f8cd 150 if (ret == BUS_NAME_NON_EXISTENT)
043ccd83 151 return -ESRCH;
0461f8cd 152 if (ret == BUS_NAME_NOT_OWNER)
043ccd83 153 return -EADDRINUSE;
0461f8cd 154 if (ret == BUS_NAME_RELEASED)
e7176abb
LP
155 return 0;
156
157 return -EINVAL;
158}
159
160_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
9bb058a1 161 assert_return(bus, -EINVAL);
e7176abb 162 assert_return(name, -EINVAL);
9bb058a1 163 assert_return(!bus_pid_changed(bus), -ECHILD);
45fd5e4d
LP
164 assert_return(service_name_is_valid(name), -EINVAL);
165 assert_return(name[0] != ':', -EINVAL);
de1c301e 166
33c62dcb
LP
167 if (!bus->bus_client)
168 return -EINVAL;
169
23539f67 170 /* Don't allow releasing the special driver and local names */
210a6882
LP
171 if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
172 return -EINVAL;
173
a3d59cd1
LP
174 if (!BUS_IS_OPEN(bus->state))
175 return -ENOTCONN;
176
a132bef0 177 return bus_release_name_dbus1(bus, name);
71f2ab46
LP
178}
179
180static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
4afd3348 181 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
71f2ab46
LP
182 _cleanup_strv_free_ char **x = NULL, **y = NULL;
183 int r;
184
185 if (acquired) {
186 r = sd_bus_call_method(
187 bus,
188 "org.freedesktop.DBus",
cd789fdf 189 "/org/freedesktop/DBus",
71f2ab46
LP
190 "org.freedesktop.DBus",
191 "ListNames",
192 NULL,
193 &reply,
194 NULL);
195 if (r < 0)
196 return r;
197
198 r = sd_bus_message_read_strv(reply, &x);
199 if (r < 0)
200 return r;
201
202 reply = sd_bus_message_unref(reply);
203 }
204
205 if (activatable) {
206 r = sd_bus_call_method(
207 bus,
208 "org.freedesktop.DBus",
cd789fdf 209 "/org/freedesktop/DBus",
71f2ab46
LP
210 "org.freedesktop.DBus",
211 "ListActivatableNames",
212 NULL,
213 &reply,
214 NULL);
215 if (r < 0)
216 return r;
217
218 r = sd_bus_message_read_strv(reply, &y);
219 if (r < 0)
220 return r;
221
222 *activatable = y;
223 y = NULL;
224 }
225
226 if (acquired) {
227 *acquired = x;
228 x = NULL;
a4297f08 229 }
de1c301e 230
49b832c5
LP
231 return 0;
232}
233
71f2ab46 234_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
e7176abb 235 assert_return(bus, -EINVAL);
71f2ab46 236 assert_return(acquired || activatable, -EINVAL);
e7176abb
LP
237 assert_return(!bus_pid_changed(bus), -ECHILD);
238
33c62dcb
LP
239 if (!bus->bus_client)
240 return -EINVAL;
241
a3d59cd1
LP
242 if (!BUS_IS_OPEN(bus->state))
243 return -ENOTCONN;
244
a132bef0 245 return bus_list_names_dbus1(bus, acquired, activatable);
e7176abb
LP
246}
247
056f95d0 248static int bus_get_name_creds_dbus1(
e7176abb
LP
249 sd_bus *bus,
250 const char *name,
251 uint64_t mask,
252 sd_bus_creds **creds) {
253
4afd3348
LP
254 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
255 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
e7176abb
LP
256 const char *unique = NULL;
257 pid_t pid = 0;
258 int r;
259
260 /* Only query the owner if the caller wants to know it or if
261 * the caller just wants to check whether a name exists */
262 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
263 r = sd_bus_call_method(
264 bus,
265 "org.freedesktop.DBus",
cd789fdf 266 "/org/freedesktop/DBus",
e7176abb
LP
267 "org.freedesktop.DBus",
268 "GetNameOwner",
269 NULL,
270 &reply_unique,
271 "s",
272 name);
273 if (r < 0)
274 return r;
275
276 r = sd_bus_message_read(reply_unique, "s", &unique);
277 if (r < 0)
278 return r;
279 }
280
281 if (mask != 0) {
40f35505
LP
282 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
283 bool need_pid, need_uid, need_selinux, need_separate_calls;
e7176abb
LP
284 c = bus_creds_new();
285 if (!c)
286 return -ENOMEM;
287
288 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
289 c->unique_name = strdup(unique);
290 if (!c->unique_name)
291 return -ENOMEM;
292
293 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
294 }
49b832c5 295
40f35505
LP
296 need_pid = (mask & SD_BUS_CREDS_PID) ||
297 ((mask & SD_BUS_CREDS_AUGMENT) &&
298 (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
299 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
300 SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
301 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
302 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|
303 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
304 SD_BUS_CREDS_SELINUX_CONTEXT|
305 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
306 need_uid = mask & SD_BUS_CREDS_EUID;
307 need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
705a415f 308
40f35505
LP
309 if (need_pid + need_uid + need_selinux > 1) {
310
311 /* If we need more than one of the credentials, then use GetConnectionCredentials() */
49b832c5 312
e7176abb
LP
313 r = sd_bus_call_method(
314 bus,
315 "org.freedesktop.DBus",
cd789fdf 316 "/org/freedesktop/DBus",
e7176abb 317 "org.freedesktop.DBus",
40f35505
LP
318 "GetConnectionCredentials",
319 &error,
e7176abb
LP
320 &reply,
321 "s",
40f35505 322 unique ?: name);
49b832c5 323
40f35505 324 if (r < 0) {
e7176abb 325
40f35505
LP
326 if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
327 return r;
49b832c5 328
40f35505
LP
329 /* If we got an unknown method error, fall back to the invidual calls... */
330 need_separate_calls = true;
331 sd_bus_error_free(&error);
49b832c5 332
40f35505
LP
333 } else {
334 need_separate_calls = false;
49b832c5 335
40f35505
LP
336 r = sd_bus_message_enter_container(reply, 'a', "{sv}");
337 if (r < 0)
338 return r;
49b832c5 339
40f35505
LP
340 for (;;) {
341 const char *m;
49b832c5 342
40f35505
LP
343 r = sd_bus_message_enter_container(reply, 'e', "sv");
344 if (r < 0)
345 return r;
346 if (r == 0)
347 break;
49b832c5 348
40f35505
LP
349 r = sd_bus_message_read(reply, "s", &m);
350 if (r < 0)
351 return r;
49b832c5 352
40f35505
LP
353 if (need_uid && streq(m, "UnixUserID")) {
354 uint32_t u;
49b832c5 355
40f35505
LP
356 r = sd_bus_message_read(reply, "v", "u", &u);
357 if (r < 0)
358 return r;
359
360 c->euid = u;
361 c->mask |= SD_BUS_CREDS_EUID;
362
363 } else if (need_pid && streq(m, "ProcessID")) {
364 uint32_t p;
365
366 r = sd_bus_message_read(reply, "v", "u", &p);
367 if (r < 0)
368 return r;
369
370 pid = p;
371 if (mask & SD_BUS_CREDS_PID) {
372 c->pid = p;
373 c->mask |= SD_BUS_CREDS_PID;
374 }
375
376 } else if (need_selinux && streq(m, "LinuxSecurityLabel")) {
377 const void *p = NULL;
378 size_t sz = 0;
379
380 r = sd_bus_message_enter_container(reply, 'v', "ay");
381 if (r < 0)
382 return r;
383
384 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
385 if (r < 0)
386 return r;
387
388 free(c->label);
389 c->label = strndup(p, sz);
390 if (!c->label)
391 return -ENOMEM;
392
393 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
394
395 r = sd_bus_message_exit_container(reply);
396 if (r < 0)
397 return r;
398 } else {
399 r = sd_bus_message_skip(reply, "v");
400 if (r < 0)
401 return r;
402 }
403
404 r = sd_bus_message_exit_container(reply);
405 if (r < 0)
406 return r;
407 }
408
409 r = sd_bus_message_exit_container(reply);
410 if (r < 0)
359c09b1 411 return r;
40f35505
LP
412
413 if (need_pid && pid == 0)
414 return -EPROTO;
415 }
416
417 } else /* When we only need a single field, then let's use separate calls */
418 need_separate_calls = true;
419
420 if (need_separate_calls) {
421 if (need_pid) {
422 uint32_t u;
423
424 r = sd_bus_call_method(
425 bus,
426 "org.freedesktop.DBus",
427 "/org/freedesktop/DBus",
428 "org.freedesktop.DBus",
429 "GetConnectionUnixProcessID",
430 NULL,
431 &reply,
432 "s",
433 unique ?: name);
359c09b1
LP
434 if (r < 0)
435 return r;
e7176abb 436
40f35505
LP
437 r = sd_bus_message_read(reply, "u", &u);
438 if (r < 0)
439 return r;
e7176abb 440
40f35505
LP
441 pid = u;
442 if (mask & SD_BUS_CREDS_PID) {
443 c->pid = u;
444 c->mask |= SD_BUS_CREDS_PID;
445 }
446
447 reply = sd_bus_message_unref(reply);
448 }
449
450 if (need_uid) {
451 uint32_t u;
452
453 r = sd_bus_call_method(
454 bus,
455 "org.freedesktop.DBus",
456 "/org/freedesktop/DBus",
457 "org.freedesktop.DBus",
458 "GetConnectionUnixUser",
459 NULL,
460 &reply,
461 "s",
462 unique ? unique : name);
463 if (r < 0)
464 return r;
465
466 r = sd_bus_message_read(reply, "u", &u);
467 if (r < 0)
468 return r;
469
470 c->euid = u;
471 c->mask |= SD_BUS_CREDS_EUID;
472
473 reply = sd_bus_message_unref(reply);
474 }
475
476 if (need_selinux) {
477 const void *p = NULL;
478 size_t sz = 0;
479
480 r = sd_bus_call_method(
481 bus,
482 "org.freedesktop.DBus",
483 "/org/freedesktop/DBus",
484 "org.freedesktop.DBus",
485 "GetConnectionSELinuxSecurityContext",
486 &error,
487 &reply,
488 "s",
489 unique ? unique : name);
490 if (r < 0) {
491 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
492 return r;
493
494 /* no data is fine */
495 } else {
496 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
497 if (r < 0)
498 return r;
499
500 c->label = strndup(p, sz);
501 if (!c->label)
502 return -ENOMEM;
503
504 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
505 }
359c09b1 506 }
49b832c5 507 }
e7176abb
LP
508
509 r = bus_creds_add_more(c, mask, pid, 0);
510 if (r < 0)
511 return r;
49b832c5
LP
512 }
513
514 if (creds) {
515 *creds = c;
516 c = NULL;
517 }
518
e7176abb 519 return 0;
49b832c5
LP
520}
521
056f95d0 522_public_ int sd_bus_get_name_creds(
49b832c5
LP
523 sd_bus *bus,
524 const char *name,
525 uint64_t mask,
526 sd_bus_creds **creds) {
527
528 assert_return(bus, -EINVAL);
529 assert_return(name, -EINVAL);
15411c0c 530 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
49b832c5 531 assert_return(mask == 0 || creds, -EINVAL);
49b832c5 532 assert_return(!bus_pid_changed(bus), -ECHILD);
45fd5e4d 533 assert_return(service_name_is_valid(name), -EINVAL);
33c62dcb
LP
534
535 if (!bus->bus_client)
536 return -EINVAL;
49b832c5 537
694859b5
LP
538 /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
539 * going to match. */
540 if (!bus->is_local)
541 mask &= ~SD_BUS_CREDS_AUGMENT;
542
210a6882
LP
543 if (streq(name, "org.freedesktop.DBus.Local"))
544 return -EINVAL;
545
51c7d5aa
LP
546 if (streq(name, "org.freedesktop.DBus"))
547 return sd_bus_get_owner_creds(bus, mask, creds);
548
a3d59cd1
LP
549 if (!BUS_IS_OPEN(bus->state))
550 return -ENOTCONN;
551
a132bef0 552 return bus_get_name_creds_dbus1(bus, name, mask, creds);
52cfc037
LP
553}
554
555static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
4afd3348 556 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
52cfc037 557 pid_t pid = 0;
7fc04b12 558 bool do_label;
52cfc037 559 int r;
7fc04b12
LP
560
561 assert(bus);
562
563 do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
8f44e3ea 564
c4e6556c
ZJS
565 /* Avoid allocating anything if we have no chance of returning useful data */
566 if (!bus->ucred_valid && !do_label)
8f44e3ea
DM
567 return -ENODATA;
568
569 c = bus_creds_new();
570 if (!c)
571 return -ENOMEM;
572
573 if (bus->ucred_valid) {
52cfc037
LP
574 if (bus->ucred.pid > 0) {
575 pid = c->pid = bus->ucred.pid;
576 c->mask |= SD_BUS_CREDS_PID & mask;
577 }
8f44e3ea 578
fed1e721 579 if (bus->ucred.uid != UID_INVALID) {
05bae4a6
DH
580 c->euid = bus->ucred.uid;
581 c->mask |= SD_BUS_CREDS_EUID & mask;
52cfc037
LP
582 }
583
fed1e721 584 if (bus->ucred.gid != GID_INVALID) {
05bae4a6
DH
585 c->egid = bus->ucred.gid;
586 c->mask |= SD_BUS_CREDS_EGID & mask;
52cfc037 587 }
8f44e3ea
DM
588 }
589
c4e6556c 590 if (do_label) {
8f44e3ea 591 c->label = strdup(bus->label);
505e77ca 592 if (!c->label)
8f44e3ea 593 return -ENOMEM;
8f44e3ea
DM
594
595 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
596 }
597
705a415f
LP
598 r = bus_creds_add_more(c, mask, pid, 0);
599 if (r < 0)
600 return r;
601
8f44e3ea 602 *ret = c;
505e77ca 603 c = NULL;
8f44e3ea
DM
604 return 0;
605}
606
52cfc037
LP
607_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
608 assert_return(bus, -EINVAL);
15411c0c 609 assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
52cfc037
LP
610 assert_return(ret, -EINVAL);
611 assert_return(!bus_pid_changed(bus), -ECHILD);
612
613 if (!BUS_IS_OPEN(bus->state))
614 return -ENOTCONN;
615
694859b5
LP
616 if (!bus->is_local)
617 mask &= ~SD_BUS_CREDS_AUGMENT;
618
a132bef0 619 return bus_get_owner_creds_dbus1(bus, mask, ret);
e7176abb 620}
777d7a61 621
09365592
LP
622#define internal_match(bus, m) \
623 ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
63c372cb 624 ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
09365592
LP
625 : (m))
626
e7176abb
LP
627static int bus_add_match_internal_dbus1(
628 sd_bus *bus,
629 const char *match) {
777d7a61 630
09365592
LP
631 const char *e;
632
e7176abb
LP
633 assert(bus);
634 assert(match);
777d7a61 635
09365592
LP
636 e = internal_match(bus, match);
637
e7176abb
LP
638 return sd_bus_call_method(
639 bus,
640 "org.freedesktop.DBus",
cd789fdf 641 "/org/freedesktop/DBus",
e7176abb
LP
642 "org.freedesktop.DBus",
643 "AddMatch",
644 NULL,
645 NULL,
646 "s",
09365592 647 e);
de1c301e
LP
648}
649
e7176abb
LP
650int bus_add_match_internal(
651 sd_bus *bus,
652 const char *match,
653 struct bus_match_component *components,
532f808f 654 unsigned n_components) {
e7176abb
LP
655
656 assert(bus);
e7176abb 657
33c62dcb
LP
658 if (!bus->bus_client)
659 return -EINVAL;
660
a132bef0 661 return bus_add_match_internal_dbus1(bus, match);
e7176abb 662}
c7819669 663
e7176abb
LP
664static int bus_remove_match_internal_dbus1(
665 sd_bus *bus,
666 const char *match) {
777d7a61 667
09365592
LP
668 const char *e;
669
e7176abb
LP
670 assert(bus);
671 assert(match);
672
09365592
LP
673 e = internal_match(bus, match);
674
e7176abb
LP
675 return sd_bus_call_method(
676 bus,
677 "org.freedesktop.DBus",
cd789fdf 678 "/org/freedesktop/DBus",
e7176abb
LP
679 "org.freedesktop.DBus",
680 "RemoveMatch",
681 NULL,
682 NULL,
683 "s",
09365592 684 e);
e7176abb
LP
685}
686
687int bus_remove_match_internal(
688 sd_bus *bus,
532f808f 689 const char *match) {
e7176abb
LP
690
691 assert(bus);
e7176abb 692
33c62dcb
LP
693 if (!bus->bus_client)
694 return -EINVAL;
695
a132bef0 696 return bus_remove_match_internal_dbus1(bus, match);
de1c301e 697}
70666185 698
056f95d0 699_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
4afd3348 700 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
70666185
LP
701 const char *mid;
702 int r;
703
8d162091
LP
704 assert_return(bus, -EINVAL);
705 assert_return(name, -EINVAL);
706 assert_return(machine, -EINVAL);
8d162091 707 assert_return(!bus_pid_changed(bus), -ECHILD);
45fd5e4d 708 assert_return(service_name_is_valid(name), -EINVAL);
70666185 709
33c62dcb
LP
710 if (!bus->bus_client)
711 return -EINVAL;
712
a3d59cd1
LP
713 if (!BUS_IS_OPEN(bus->state))
714 return -ENOTCONN;
715
70666185
LP
716 if (streq_ptr(name, bus->unique_name))
717 return sd_id128_get_machine(machine);
718
8d162091
LP
719 r = sd_bus_message_new_method_call(
720 bus,
151b9b96 721 &m,
8d162091
LP
722 name,
723 "/",
724 "org.freedesktop.DBus.Peer",
151b9b96 725 "GetMachineId");
8d162091
LP
726 if (r < 0)
727 return r;
728
eee9ec0e 729 r = sd_bus_message_set_auto_start(m, false);
8d162091
LP
730 if (r < 0)
731 return r;
70666185 732
8d162091 733 r = sd_bus_call(bus, m, 0, NULL, &reply);
70666185
LP
734 if (r < 0)
735 return r;
736
737 r = sd_bus_message_read(reply, "s", &mid);
738 if (r < 0)
739 return r;
740
741 return sd_id128_from_string(mid, machine);
742}