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