]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
de1c301e | 2 | |
de1c301e | 3 | #include "sd-bus.h" |
07630cea | 4 | |
b5efdb8a | 5 | #include "alloc-util.h" |
ee104e11 | 6 | #include "bus-control.h" |
de1c301e LP |
7 | #include "bus-internal.h" |
8 | #include "bus-message.h" | |
71be6406 | 9 | #include "fd-util.h" |
93a1f792 | 10 | #include "log.h" |
5cdf13c7 | 11 | #include "pidref.h" |
dccca82b | 12 | #include "process-util.h" |
07630cea LP |
13 | #include "string-util.h" |
14 | #include "strv.h" | |
ee104e11 | 15 | #include "user-util.h" |
de1c301e | 16 | |
d9f644e2 | 17 | _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { |
20902f3e LP |
18 | int r; |
19 | ||
9bb058a1 | 20 | assert_return(bus, -EINVAL); |
45b1f410 | 21 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
9bb058a1 | 22 | assert_return(unique, -EINVAL); |
bf876e3f | 23 | assert_return(!bus_origin_changed(bus), -ECHILD); |
20902f3e | 24 | |
33c62dcb LP |
25 | if (!bus->bus_client) |
26 | return -EINVAL; | |
27 | ||
20902f3e LP |
28 | r = bus_ensure_running(bus); |
29 | if (r < 0) | |
30 | return r; | |
de1c301e | 31 | |
20902f3e LP |
32 | *unique = bus->unique_name; |
33 | return 0; | |
de1c301e LP |
34 | } |
35 | ||
98c5bbc8 LP |
36 | static int validate_request_name_parameters( |
37 | sd_bus *bus, | |
38 | const char *name, | |
39 | uint64_t flags, | |
40 | uint32_t *ret_param) { | |
41 | ||
42 | uint32_t param = 0; | |
43 | ||
44 | assert(bus); | |
45 | assert(name); | |
46 | assert(ret_param); | |
de1c301e | 47 | |
e8bd7b09 LP |
48 | assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL); |
49 | assert_return(service_name_is_valid(name), -EINVAL); | |
50 | assert_return(name[0] != ':', -EINVAL); | |
51 | ||
52 | if (!bus->bus_client) | |
53 | return -EINVAL; | |
54 | ||
55 | /* Don't allow requesting the special driver and local names */ | |
56 | if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) | |
57 | return -EINVAL; | |
58 | ||
59 | if (!BUS_IS_OPEN(bus->state)) | |
60 | return -ENOTCONN; | |
e7176abb | 61 | |
29a07cdb LP |
62 | if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT) |
63 | param |= BUS_NAME_ALLOW_REPLACEMENT; | |
64 | if (flags & SD_BUS_NAME_REPLACE_EXISTING) | |
65 | param |= BUS_NAME_REPLACE_EXISTING; | |
66 | if (!(flags & SD_BUS_NAME_QUEUE)) | |
67 | param |= BUS_NAME_DO_NOT_QUEUE; | |
68 | ||
98c5bbc8 LP |
69 | *ret_param = param; |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
74 | _public_ int sd_bus_request_name( | |
75 | sd_bus *bus, | |
76 | const char *name, | |
77 | uint64_t flags) { | |
78 | ||
79 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; | |
80 | uint32_t ret, param = 0; | |
81 | int r; | |
82 | ||
83 | assert_return(bus, -EINVAL); | |
45b1f410 | 84 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
98c5bbc8 | 85 | assert_return(name, -EINVAL); |
bf876e3f | 86 | assert_return(!bus_origin_changed(bus), -ECHILD); |
98c5bbc8 LP |
87 | |
88 | r = validate_request_name_parameters(bus, name, flags, ¶m); | |
89 | if (r < 0) | |
90 | return r; | |
91 | ||
e7176abb LP |
92 | r = sd_bus_call_method( |
93 | bus, | |
94 | "org.freedesktop.DBus", | |
cd789fdf | 95 | "/org/freedesktop/DBus", |
e7176abb LP |
96 | "org.freedesktop.DBus", |
97 | "RequestName", | |
98 | NULL, | |
99 | &reply, | |
100 | "su", | |
101 | name, | |
29a07cdb | 102 | param); |
e7176abb LP |
103 | if (r < 0) |
104 | return r; | |
105 | ||
106 | r = sd_bus_message_read(reply, "u", &ret); | |
107 | if (r < 0) | |
108 | return r; | |
109 | ||
98c5bbc8 LP |
110 | switch (ret) { |
111 | ||
112 | case BUS_NAME_ALREADY_OWNER: | |
e7176abb | 113 | return -EALREADY; |
98c5bbc8 LP |
114 | |
115 | case BUS_NAME_EXISTS: | |
e7176abb | 116 | return -EEXIST; |
98c5bbc8 LP |
117 | |
118 | case BUS_NAME_IN_QUEUE: | |
e7176abb | 119 | return 0; |
98c5bbc8 LP |
120 | |
121 | case BUS_NAME_PRIMARY_OWNER: | |
c0a09132 | 122 | return 1; |
98c5bbc8 | 123 | } |
e7176abb | 124 | |
c0a09132 | 125 | return -EIO; |
e7176abb LP |
126 | } |
127 | ||
98c5bbc8 LP |
128 | static int default_request_name_handler( |
129 | sd_bus_message *m, | |
130 | void *userdata, | |
131 | sd_bus_error *ret_error) { | |
132 | ||
e8bd7b09 LP |
133 | uint32_t ret; |
134 | int r; | |
135 | ||
98c5bbc8 LP |
136 | assert(m); |
137 | ||
138 | if (sd_bus_message_is_method_error(m, NULL)) { | |
139 | log_debug_errno(sd_bus_message_get_errno(m), | |
140 | "Unable to request name, failing connection: %s", | |
141 | sd_bus_message_get_error(m)->message); | |
142 | ||
143 | bus_enter_closing(sd_bus_message_get_bus(m)); | |
144 | return 1; | |
145 | } | |
146 | ||
147 | r = sd_bus_message_read(m, "u", &ret); | |
148 | if (r < 0) | |
149 | return r; | |
150 | ||
151 | switch (ret) { | |
152 | ||
153 | case BUS_NAME_ALREADY_OWNER: | |
154 | log_debug("Already owner of requested service name, ignoring."); | |
155 | return 1; | |
156 | ||
157 | case BUS_NAME_IN_QUEUE: | |
158 | log_debug("In queue for requested service name."); | |
159 | return 1; | |
160 | ||
161 | case BUS_NAME_PRIMARY_OWNER: | |
162 | log_debug("Successfully acquired requested service name."); | |
163 | return 1; | |
164 | ||
165 | case BUS_NAME_EXISTS: | |
166 | log_debug("Requested service name already owned, failing connection."); | |
167 | bus_enter_closing(sd_bus_message_get_bus(m)); | |
168 | return 1; | |
169 | } | |
170 | ||
171 | log_debug("Unexpected response from RequestName(), failing connection."); | |
172 | bus_enter_closing(sd_bus_message_get_bus(m)); | |
173 | return 1; | |
174 | } | |
175 | ||
176 | _public_ int sd_bus_request_name_async( | |
177 | sd_bus *bus, | |
178 | sd_bus_slot **ret_slot, | |
179 | const char *name, | |
180 | uint64_t flags, | |
181 | sd_bus_message_handler_t callback, | |
182 | void *userdata) { | |
183 | ||
184 | uint32_t param = 0; | |
185 | int r; | |
186 | ||
9bb058a1 | 187 | assert_return(bus, -EINVAL); |
45b1f410 | 188 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
9bb058a1 | 189 | assert_return(name, -EINVAL); |
bf876e3f | 190 | assert_return(!bus_origin_changed(bus), -ECHILD); |
98c5bbc8 LP |
191 | |
192 | r = validate_request_name_parameters(bus, name, flags, ¶m); | |
193 | if (r < 0) | |
194 | return r; | |
195 | ||
196 | return sd_bus_call_method_async( | |
197 | bus, | |
198 | ret_slot, | |
199 | "org.freedesktop.DBus", | |
200 | "/org/freedesktop/DBus", | |
201 | "org.freedesktop.DBus", | |
202 | "RequestName", | |
203 | callback ?: default_request_name_handler, | |
204 | userdata, | |
205 | "su", | |
206 | name, | |
207 | param); | |
208 | } | |
209 | ||
210 | static int validate_release_name_parameters( | |
211 | sd_bus *bus, | |
212 | const char *name) { | |
213 | ||
214 | assert(bus); | |
215 | assert(name); | |
216 | ||
45fd5e4d LP |
217 | assert_return(service_name_is_valid(name), -EINVAL); |
218 | assert_return(name[0] != ':', -EINVAL); | |
de1c301e | 219 | |
33c62dcb LP |
220 | if (!bus->bus_client) |
221 | return -EINVAL; | |
222 | ||
e8bd7b09 | 223 | /* Don't allow releasing the special driver and local names */ |
210a6882 LP |
224 | if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) |
225 | return -EINVAL; | |
226 | ||
a3d59cd1 LP |
227 | if (!BUS_IS_OPEN(bus->state)) |
228 | return -ENOTCONN; | |
229 | ||
98c5bbc8 LP |
230 | return 0; |
231 | } | |
232 | ||
233 | _public_ int sd_bus_release_name( | |
234 | sd_bus *bus, | |
235 | const char *name) { | |
236 | ||
237 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; | |
238 | uint32_t ret; | |
239 | int r; | |
240 | ||
241 | assert_return(bus, -EINVAL); | |
45b1f410 | 242 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
98c5bbc8 | 243 | assert_return(name, -EINVAL); |
bf876e3f | 244 | assert_return(!bus_origin_changed(bus), -ECHILD); |
98c5bbc8 LP |
245 | |
246 | r = validate_release_name_parameters(bus, name); | |
247 | if (r < 0) | |
248 | return r; | |
249 | ||
e7176abb LP |
250 | r = sd_bus_call_method( |
251 | bus, | |
252 | "org.freedesktop.DBus", | |
cd789fdf | 253 | "/org/freedesktop/DBus", |
e7176abb LP |
254 | "org.freedesktop.DBus", |
255 | "ReleaseName", | |
256 | NULL, | |
257 | &reply, | |
258 | "s", | |
259 | name); | |
260 | if (r < 0) | |
261 | return r; | |
262 | ||
263 | r = sd_bus_message_read(reply, "u", &ret); | |
264 | if (r < 0) | |
265 | return r; | |
98c5bbc8 LP |
266 | |
267 | switch (ret) { | |
268 | ||
269 | case BUS_NAME_NON_EXISTENT: | |
043ccd83 | 270 | return -ESRCH; |
98c5bbc8 LP |
271 | |
272 | case BUS_NAME_NOT_OWNER: | |
043ccd83 | 273 | return -EADDRINUSE; |
98c5bbc8 LP |
274 | |
275 | case BUS_NAME_RELEASED: | |
e7176abb | 276 | return 0; |
98c5bbc8 LP |
277 | } |
278 | ||
279 | return -EIO; | |
280 | } | |
281 | ||
282 | static int default_release_name_handler( | |
283 | sd_bus_message *m, | |
284 | void *userdata, | |
285 | sd_bus_error *ret_error) { | |
286 | ||
287 | uint32_t ret; | |
288 | int r; | |
289 | ||
290 | assert(m); | |
291 | ||
292 | if (sd_bus_message_is_method_error(m, NULL)) { | |
293 | log_debug_errno(sd_bus_message_get_errno(m), | |
294 | "Unable to release name, failing connection: %s", | |
295 | sd_bus_message_get_error(m)->message); | |
e7176abb | 296 | |
98c5bbc8 LP |
297 | bus_enter_closing(sd_bus_message_get_bus(m)); |
298 | return 1; | |
299 | } | |
300 | ||
301 | r = sd_bus_message_read(m, "u", &ret); | |
302 | if (r < 0) | |
303 | return r; | |
304 | ||
305 | switch (ret) { | |
306 | ||
307 | case BUS_NAME_NON_EXISTENT: | |
308 | log_debug("Name asked to release is not taken currently, ignoring."); | |
309 | return 1; | |
310 | ||
311 | case BUS_NAME_NOT_OWNER: | |
312 | log_debug("Name asked to release is owned by somebody else, ignoring."); | |
313 | return 1; | |
314 | ||
315 | case BUS_NAME_RELEASED: | |
316 | log_debug("Name successfully released."); | |
317 | return 1; | |
318 | } | |
319 | ||
320 | log_debug("Unexpected response from ReleaseName(), failing connection."); | |
321 | bus_enter_closing(sd_bus_message_get_bus(m)); | |
322 | return 1; | |
323 | } | |
324 | ||
325 | _public_ int sd_bus_release_name_async( | |
326 | sd_bus *bus, | |
327 | sd_bus_slot **ret_slot, | |
328 | const char *name, | |
329 | sd_bus_message_handler_t callback, | |
330 | void *userdata) { | |
331 | ||
332 | int r; | |
333 | ||
334 | assert_return(bus, -EINVAL); | |
45b1f410 | 335 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
98c5bbc8 | 336 | assert_return(name, -EINVAL); |
bf876e3f | 337 | assert_return(!bus_origin_changed(bus), -ECHILD); |
98c5bbc8 LP |
338 | |
339 | r = validate_release_name_parameters(bus, name); | |
340 | if (r < 0) | |
341 | return r; | |
342 | ||
343 | return sd_bus_call_method_async( | |
344 | bus, | |
345 | ret_slot, | |
346 | "org.freedesktop.DBus", | |
347 | "/org/freedesktop/DBus", | |
348 | "org.freedesktop.DBus", | |
349 | "ReleaseName", | |
350 | callback ?: default_release_name_handler, | |
351 | userdata, | |
352 | "s", | |
353 | name); | |
e7176abb LP |
354 | } |
355 | ||
31a1e15c | 356 | _public_ int sd_bus_list_names(sd_bus *bus, char ***ret_acquired, char ***ret_activatable) { |
e8bd7b09 LP |
357 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; |
358 | _cleanup_strv_free_ char **x = NULL, **y = NULL; | |
359 | int r; | |
360 | ||
9bb058a1 | 361 | assert_return(bus, -EINVAL); |
45b1f410 | 362 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
31a1e15c | 363 | assert_return(ret_acquired || ret_activatable, -EINVAL); |
bf876e3f | 364 | assert_return(!bus_origin_changed(bus), -ECHILD); |
de1c301e | 365 | |
33c62dcb LP |
366 | if (!bus->bus_client) |
367 | return -EINVAL; | |
368 | ||
a3d59cd1 LP |
369 | if (!BUS_IS_OPEN(bus->state)) |
370 | return -ENOTCONN; | |
371 | ||
31a1e15c | 372 | if (ret_acquired) { |
71f2ab46 LP |
373 | r = sd_bus_call_method( |
374 | bus, | |
375 | "org.freedesktop.DBus", | |
cd789fdf | 376 | "/org/freedesktop/DBus", |
71f2ab46 LP |
377 | "org.freedesktop.DBus", |
378 | "ListNames", | |
379 | NULL, | |
380 | &reply, | |
381 | NULL); | |
382 | if (r < 0) | |
383 | return r; | |
384 | ||
385 | r = sd_bus_message_read_strv(reply, &x); | |
386 | if (r < 0) | |
387 | return r; | |
388 | ||
389 | reply = sd_bus_message_unref(reply); | |
390 | } | |
391 | ||
31a1e15c | 392 | if (ret_activatable) { |
71f2ab46 LP |
393 | r = sd_bus_call_method( |
394 | bus, | |
395 | "org.freedesktop.DBus", | |
cd789fdf | 396 | "/org/freedesktop/DBus", |
71f2ab46 LP |
397 | "org.freedesktop.DBus", |
398 | "ListActivatableNames", | |
399 | NULL, | |
400 | &reply, | |
401 | NULL); | |
402 | if (r < 0) | |
403 | return r; | |
404 | ||
405 | r = sd_bus_message_read_strv(reply, &y); | |
406 | if (r < 0) | |
407 | return r; | |
408 | ||
31a1e15c | 409 | *ret_activatable = TAKE_PTR(y); |
71f2ab46 LP |
410 | } |
411 | ||
31a1e15c YW |
412 | if (ret_acquired) |
413 | *ret_acquired = TAKE_PTR(x); | |
de1c301e | 414 | |
49b832c5 LP |
415 | return 0; |
416 | } | |
417 | ||
e8bd7b09 | 418 | _public_ int sd_bus_get_name_creds( |
e7176abb LP |
419 | sd_bus *bus, |
420 | const char *name, | |
421 | uint64_t mask, | |
31a1e15c | 422 | sd_bus_creds **ret) { |
e7176abb | 423 | |
4afd3348 LP |
424 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL; |
425 | _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; | |
a845e53a | 426 | const char *unique; |
e7176abb LP |
427 | int r; |
428 | ||
e8bd7b09 | 429 | assert_return(bus, -EINVAL); |
45b1f410 | 430 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
e8bd7b09 LP |
431 | assert_return(name, -EINVAL); |
432 | assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); | |
31a1e15c | 433 | assert_return(mask == 0 || ret, -EINVAL); |
bf876e3f | 434 | assert_return(!bus_origin_changed(bus), -ECHILD); |
e8bd7b09 LP |
435 | assert_return(service_name_is_valid(name), -EINVAL); |
436 | ||
437 | if (!bus->bus_client) | |
438 | return -EINVAL; | |
439 | ||
440 | /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not | |
441 | * going to match. */ | |
442 | if (!bus->is_local) | |
443 | mask &= ~SD_BUS_CREDS_AUGMENT; | |
444 | ||
445 | if (streq(name, "org.freedesktop.DBus.Local")) | |
446 | return -EINVAL; | |
447 | ||
448 | if (streq(name, "org.freedesktop.DBus")) | |
31a1e15c | 449 | return sd_bus_get_owner_creds(bus, mask, ret); |
e8bd7b09 LP |
450 | |
451 | if (!BUS_IS_OPEN(bus->state)) | |
452 | return -ENOTCONN; | |
453 | ||
a845e53a LP |
454 | /* If the name is unique anyway, we can use it directly */ |
455 | unique = name[0] == ':' ? name : NULL; | |
456 | ||
457 | /* Only query the owner if the caller wants to know it and the name is not unique anyway, or if the caller just | |
458 | * wants to check whether a name exists */ | |
459 | if ((FLAGS_SET(mask, SD_BUS_CREDS_UNIQUE_NAME) && !unique) || mask == 0) { | |
e7176abb LP |
460 | r = sd_bus_call_method( |
461 | bus, | |
462 | "org.freedesktop.DBus", | |
cd789fdf | 463 | "/org/freedesktop/DBus", |
e7176abb LP |
464 | "org.freedesktop.DBus", |
465 | "GetNameOwner", | |
466 | NULL, | |
467 | &reply_unique, | |
468 | "s", | |
469 | name); | |
470 | if (r < 0) | |
471 | return r; | |
472 | ||
473 | r = sd_bus_message_read(reply_unique, "s", &unique); | |
474 | if (r < 0) | |
475 | return r; | |
476 | } | |
477 | ||
478 | if (mask != 0) { | |
25fd5343 | 479 | bool need_pid, need_uid, need_gids, need_selinux, need_separate_calls, need_pidfd, need_augment; |
40f35505 | 480 | _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; |
71be6406 | 481 | _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; |
a845e53a | 482 | |
e7176abb LP |
483 | c = bus_creds_new(); |
484 | if (!c) | |
485 | return -ENOMEM; | |
486 | ||
487 | if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) { | |
488 | c->unique_name = strdup(unique); | |
489 | if (!c->unique_name) | |
490 | return -ENOMEM; | |
491 | ||
492 | c->mask |= SD_BUS_CREDS_UNIQUE_NAME; | |
493 | } | |
49b832c5 | 494 | |
71be6406 LP |
495 | need_augment = |
496 | (mask & SD_BUS_CREDS_AUGMENT) && | |
497 | (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| | |
498 | SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| | |
499 | SD_BUS_CREDS_SUPPLEMENTARY_GIDS| | |
500 | SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| | |
501 | 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| | |
502 | SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS| | |
503 | SD_BUS_CREDS_SELINUX_CONTEXT| | |
504 | SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID| | |
505 | SD_BUS_CREDS_PIDFD)); | |
506 | ||
507 | need_pid = (mask & SD_BUS_CREDS_PID) || need_augment; | |
40f35505 | 508 | need_uid = mask & SD_BUS_CREDS_EUID; |
25fd5343 | 509 | need_gids = mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS; |
40f35505 | 510 | need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT; |
71be6406 | 511 | need_pidfd = (mask & SD_BUS_CREDS_PIDFD) || need_augment; |
705a415f | 512 | |
25fd5343 | 513 | if (need_pid + need_uid + need_selinux + need_pidfd + need_gids > 1) { |
40f35505 LP |
514 | |
515 | /* If we need more than one of the credentials, then use GetConnectionCredentials() */ | |
49b832c5 | 516 | |
e7176abb LP |
517 | r = sd_bus_call_method( |
518 | bus, | |
519 | "org.freedesktop.DBus", | |
cd789fdf | 520 | "/org/freedesktop/DBus", |
e7176abb | 521 | "org.freedesktop.DBus", |
40f35505 LP |
522 | "GetConnectionCredentials", |
523 | &error, | |
e7176abb LP |
524 | &reply, |
525 | "s", | |
40f35505 | 526 | unique ?: name); |
49b832c5 | 527 | |
40f35505 | 528 | if (r < 0) { |
e7176abb | 529 | |
40f35505 LP |
530 | if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) |
531 | return r; | |
49b832c5 | 532 | |
5238e957 | 533 | /* If we got an unknown method error, fall back to the individual calls... */ |
40f35505 LP |
534 | need_separate_calls = true; |
535 | sd_bus_error_free(&error); | |
49b832c5 | 536 | |
40f35505 LP |
537 | } else { |
538 | need_separate_calls = false; | |
49b832c5 | 539 | |
40f35505 LP |
540 | r = sd_bus_message_enter_container(reply, 'a', "{sv}"); |
541 | if (r < 0) | |
542 | return r; | |
49b832c5 | 543 | |
40f35505 LP |
544 | for (;;) { |
545 | const char *m; | |
49b832c5 | 546 | |
40f35505 LP |
547 | r = sd_bus_message_enter_container(reply, 'e', "sv"); |
548 | if (r < 0) | |
549 | return r; | |
550 | if (r == 0) | |
551 | break; | |
49b832c5 | 552 | |
40f35505 LP |
553 | r = sd_bus_message_read(reply, "s", &m); |
554 | if (r < 0) | |
555 | return r; | |
49b832c5 | 556 | |
40f35505 LP |
557 | if (need_uid && streq(m, "UnixUserID")) { |
558 | uint32_t u; | |
49b832c5 | 559 | |
40f35505 LP |
560 | r = sd_bus_message_read(reply, "v", "u", &u); |
561 | if (r < 0) | |
562 | return r; | |
563 | ||
564 | c->euid = u; | |
565 | c->mask |= SD_BUS_CREDS_EUID; | |
566 | ||
567 | } else if (need_pid && streq(m, "ProcessID")) { | |
568 | uint32_t p; | |
569 | ||
570 | r = sd_bus_message_read(reply, "v", "u", &p); | |
571 | if (r < 0) | |
572 | return r; | |
573 | ||
71be6406 LP |
574 | if (!pidref_is_set(&pidref)) |
575 | pidref = PIDREF_MAKE_FROM_PID(p); | |
576 | ||
40f35505 LP |
577 | if (mask & SD_BUS_CREDS_PID) { |
578 | c->pid = p; | |
579 | c->mask |= SD_BUS_CREDS_PID; | |
580 | } | |
581 | ||
582 | } else if (need_selinux && streq(m, "LinuxSecurityLabel")) { | |
583 | const void *p = NULL; | |
584 | size_t sz = 0; | |
585 | ||
586 | r = sd_bus_message_enter_container(reply, 'v', "ay"); | |
587 | if (r < 0) | |
588 | return r; | |
589 | ||
590 | r = sd_bus_message_read_array(reply, 'y', &p, &sz); | |
591 | if (r < 0) | |
592 | return r; | |
593 | ||
a73e5eb9 DT |
594 | r = free_and_strndup(&c->label, p, sz); |
595 | if (r < 0) | |
596 | return r; | |
40f35505 LP |
597 | |
598 | c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; | |
599 | ||
600 | r = sd_bus_message_exit_container(reply); | |
601 | if (r < 0) | |
602 | return r; | |
71be6406 LP |
603 | } else if (need_pidfd && streq(m, "ProcessFD")) { |
604 | int fd; | |
605 | ||
606 | r = sd_bus_message_read(reply, "v", "h", &fd); | |
607 | if (r < 0) | |
608 | return r; | |
609 | ||
610 | pidref_done(&pidref); | |
611 | r = pidref_set_pidfd(&pidref, fd); | |
612 | if (r < 0) | |
613 | return r; | |
614 | ||
615 | if (mask & SD_BUS_CREDS_PIDFD) { | |
616 | fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); | |
617 | if (fd < 0) | |
618 | return -errno; | |
619 | ||
620 | close_and_replace(c->pidfd, fd); | |
621 | c->mask |= SD_BUS_CREDS_PIDFD; | |
622 | } | |
25fd5343 LP |
623 | } else if (need_gids && streq(m, "UnixGroupIDs")) { |
624 | ||
35dab29d | 625 | /* Note that D-Bus actually only gives us a combined list of |
25fd5343 LP |
626 | * primary gid and supplementary gids. And we don't know |
627 | * which one the primary one is. We'll take the whole shebang | |
628 | * hence and use it as the supplementary group list, and not | |
629 | * initialize the primary gid field. This is slightly | |
630 | * incorrect of course, but only slightly, as in effect if | |
631 | * the primary gid is also listed in the supplementary gid | |
632 | * it has zero effect. */ | |
633 | ||
634 | r = sd_bus_message_enter_container(reply, 'v', "au"); | |
635 | if (r < 0) | |
636 | return r; | |
637 | ||
638 | r = sd_bus_message_enter_container(reply, 'a', "u"); | |
639 | if (r < 0) | |
640 | return r; | |
641 | ||
642 | for (;;) { | |
643 | uint32_t u; | |
644 | ||
645 | r = sd_bus_message_read(reply, "u", &u); | |
646 | if (r < 0) | |
647 | return r; | |
648 | if (r == 0) | |
649 | break; | |
650 | ||
651 | if (!GREEDY_REALLOC(c->supplementary_gids, c->n_supplementary_gids+1)) | |
652 | return -ENOMEM; | |
653 | ||
654 | c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) u; | |
655 | } | |
656 | ||
657 | r = sd_bus_message_exit_container(reply); | |
658 | if (r < 0) | |
659 | return r; | |
660 | ||
661 | r = sd_bus_message_exit_container(reply); | |
662 | if (r < 0) | |
663 | return r; | |
664 | ||
665 | c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; | |
40f35505 LP |
666 | } else { |
667 | r = sd_bus_message_skip(reply, "v"); | |
668 | if (r < 0) | |
669 | return r; | |
670 | } | |
671 | ||
672 | r = sd_bus_message_exit_container(reply); | |
673 | if (r < 0) | |
674 | return r; | |
675 | } | |
676 | ||
677 | r = sd_bus_message_exit_container(reply); | |
678 | if (r < 0) | |
359c09b1 | 679 | return r; |
40f35505 | 680 | |
71be6406 | 681 | if (need_pid && !pidref_is_set(&pidref)) |
40f35505 LP |
682 | return -EPROTO; |
683 | } | |
684 | ||
685 | } else /* When we only need a single field, then let's use separate calls */ | |
686 | need_separate_calls = true; | |
687 | ||
688 | if (need_separate_calls) { | |
689 | if (need_pid) { | |
690 | uint32_t u; | |
691 | ||
692 | r = sd_bus_call_method( | |
693 | bus, | |
694 | "org.freedesktop.DBus", | |
695 | "/org/freedesktop/DBus", | |
696 | "org.freedesktop.DBus", | |
697 | "GetConnectionUnixProcessID", | |
698 | NULL, | |
699 | &reply, | |
700 | "s", | |
701 | unique ?: name); | |
359c09b1 LP |
702 | if (r < 0) |
703 | return r; | |
e7176abb | 704 | |
40f35505 LP |
705 | r = sd_bus_message_read(reply, "u", &u); |
706 | if (r < 0) | |
707 | return r; | |
e7176abb | 708 | |
71be6406 LP |
709 | if (!pidref_is_set(&pidref)) |
710 | pidref = PIDREF_MAKE_FROM_PID(u); | |
711 | ||
40f35505 LP |
712 | if (mask & SD_BUS_CREDS_PID) { |
713 | c->pid = u; | |
714 | c->mask |= SD_BUS_CREDS_PID; | |
715 | } | |
716 | ||
717 | reply = sd_bus_message_unref(reply); | |
718 | } | |
719 | ||
720 | if (need_uid) { | |
721 | uint32_t u; | |
722 | ||
723 | r = sd_bus_call_method( | |
724 | bus, | |
725 | "org.freedesktop.DBus", | |
726 | "/org/freedesktop/DBus", | |
727 | "org.freedesktop.DBus", | |
728 | "GetConnectionUnixUser", | |
729 | NULL, | |
730 | &reply, | |
731 | "s", | |
84a35687 | 732 | unique ?: name); |
40f35505 LP |
733 | if (r < 0) |
734 | return r; | |
735 | ||
736 | r = sd_bus_message_read(reply, "u", &u); | |
737 | if (r < 0) | |
738 | return r; | |
739 | ||
740 | c->euid = u; | |
741 | c->mask |= SD_BUS_CREDS_EUID; | |
742 | ||
743 | reply = sd_bus_message_unref(reply); | |
744 | } | |
745 | ||
746 | if (need_selinux) { | |
747 | const void *p = NULL; | |
748 | size_t sz = 0; | |
749 | ||
750 | r = sd_bus_call_method( | |
751 | bus, | |
752 | "org.freedesktop.DBus", | |
753 | "/org/freedesktop/DBus", | |
754 | "org.freedesktop.DBus", | |
755 | "GetConnectionSELinuxSecurityContext", | |
756 | &error, | |
757 | &reply, | |
758 | "s", | |
84a35687 | 759 | unique ?: name); |
40f35505 | 760 | if (r < 0) { |
91053fc9 | 761 | if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN)) |
40f35505 LP |
762 | return r; |
763 | ||
764 | /* no data is fine */ | |
765 | } else { | |
766 | r = sd_bus_message_read_array(reply, 'y', &p, &sz); | |
767 | if (r < 0) | |
768 | return r; | |
769 | ||
1a64f8c6 | 770 | c->label = memdup_suffix0(p, sz); |
40f35505 LP |
771 | if (!c->label) |
772 | return -ENOMEM; | |
773 | ||
774 | c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; | |
775 | } | |
359c09b1 | 776 | } |
49b832c5 | 777 | } |
e7176abb | 778 | |
71be6406 LP |
779 | if (pidref_is_set(&pidref)) { |
780 | r = bus_creds_add_more(c, mask, &pidref, 0); | |
781 | if (r < 0 && r != -ESRCH) /* Return the error, but ignore ESRCH which just means the process is already gone */ | |
782 | return r; | |
783 | } | |
49b832c5 LP |
784 | } |
785 | ||
31a1e15c YW |
786 | if (ret) |
787 | *ret = TAKE_PTR(c); | |
49b832c5 | 788 | |
e7176abb | 789 | return 0; |
49b832c5 LP |
790 | } |
791 | ||
c32f9648 LP |
792 | static int parse_sockaddr_string(const char *t, char **ret_comm, char **ret_description) { |
793 | _cleanup_free_ char *comm = NULL, *description = NULL; | |
794 | const char *e, *sl; | |
795 | ||
796 | assert(t); | |
797 | assert(ret_comm); | |
798 | assert(ret_description); | |
799 | ||
800 | e = strstrafter(t, "/bus/"); | |
801 | if (!e) { | |
802 | log_debug("Didn't find /bus/ substring in peer socket address, ignoring."); | |
803 | goto not_found; | |
804 | } | |
805 | ||
806 | sl = strchr(e, '/'); | |
807 | if (!sl) { | |
808 | log_debug("Didn't find / substring after /bus/ in peer socket address, ignoring."); | |
809 | goto not_found; | |
810 | } | |
811 | ||
812 | if (sl - e > 0) { | |
813 | comm = strndup(e, sl - e); | |
814 | if (!comm) | |
815 | return -ENOMEM; | |
816 | } | |
817 | ||
818 | sl++; | |
819 | if (!isempty(sl)) { | |
820 | description = strdup(sl); | |
821 | if (!description) | |
822 | return -ENOMEM; | |
823 | } | |
824 | ||
825 | *ret_comm = TAKE_PTR(comm); | |
826 | *ret_description = TAKE_PTR(description); | |
827 | return 0; | |
828 | ||
829 | not_found: | |
830 | *ret_comm = *ret_description = NULL; | |
831 | return 0; | |
832 | } | |
833 | ||
e8bd7b09 LP |
834 | _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { |
835 | _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; | |
71be6406 LP |
836 | _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; |
837 | bool do_label, do_groups, do_sockaddr_peer, do_pidfd; | |
e8bd7b09 | 838 | int r; |
49b832c5 LP |
839 | |
840 | assert_return(bus, -EINVAL); | |
45b1f410 | 841 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
15411c0c | 842 | assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); |
e8bd7b09 | 843 | assert_return(ret, -EINVAL); |
bf876e3f | 844 | assert_return(!bus_origin_changed(bus), -ECHILD); |
51c7d5aa | 845 | |
a3d59cd1 LP |
846 | if (!BUS_IS_OPEN(bus->state)) |
847 | return -ENOTCONN; | |
848 | ||
e8bd7b09 LP |
849 | if (!bus->is_local) |
850 | mask &= ~SD_BUS_CREDS_AUGMENT; | |
7fc04b12 LP |
851 | |
852 | do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); | |
f5fbe71d | 853 | do_groups = bus->n_groups != SIZE_MAX && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS); |
c32f9648 LP |
854 | do_sockaddr_peer = bus->sockaddr_size_peer >= offsetof(struct sockaddr_un, sun_path) + 1 && |
855 | bus->sockaddr_peer.sa.sa_family == AF_UNIX && | |
856 | bus->sockaddr_peer.un.sun_path[0] == 0; | |
71be6406 | 857 | do_pidfd = bus->pidfd >= 0 && (mask & SD_BUS_CREDS_PIDFD); |
8f44e3ea | 858 | |
c4e6556c | 859 | /* Avoid allocating anything if we have no chance of returning useful data */ |
71be6406 | 860 | if (!bus->ucred_valid && !do_label && !do_groups && !do_sockaddr_peer && !do_pidfd) |
8f44e3ea DM |
861 | return -ENODATA; |
862 | ||
863 | c = bus_creds_new(); | |
864 | if (!c) | |
865 | return -ENOMEM; | |
866 | ||
867 | if (bus->ucred_valid) { | |
bbcc701e | 868 | if (pid_is_valid(bus->ucred.pid)) { |
71be6406 | 869 | c->pid = bus->ucred.pid; |
52cfc037 | 870 | c->mask |= SD_BUS_CREDS_PID & mask; |
71be6406 LP |
871 | |
872 | pidref = PIDREF_MAKE_FROM_PID(c->pid); | |
52cfc037 | 873 | } |
8f44e3ea | 874 | |
bbcc701e | 875 | if (uid_is_valid(bus->ucred.uid)) { |
05bae4a6 DH |
876 | c->euid = bus->ucred.uid; |
877 | c->mask |= SD_BUS_CREDS_EUID & mask; | |
52cfc037 LP |
878 | } |
879 | ||
bbcc701e | 880 | if (gid_is_valid(bus->ucred.gid)) { |
05bae4a6 DH |
881 | c->egid = bus->ucred.gid; |
882 | c->mask |= SD_BUS_CREDS_EGID & mask; | |
52cfc037 | 883 | } |
8f44e3ea DM |
884 | } |
885 | ||
c4e6556c | 886 | if (do_label) { |
8f44e3ea | 887 | c->label = strdup(bus->label); |
505e77ca | 888 | if (!c->label) |
8f44e3ea | 889 | return -ENOMEM; |
8f44e3ea DM |
890 | |
891 | c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; | |
892 | } | |
893 | ||
18ac4643 LP |
894 | if (do_groups) { |
895 | c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups); | |
896 | if (!c->supplementary_gids) | |
897 | return -ENOMEM; | |
898 | ||
899 | c->n_supplementary_gids = bus->n_groups; | |
900 | ||
901 | c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; | |
902 | } | |
903 | ||
c32f9648 LP |
904 | if (do_sockaddr_peer) { |
905 | _cleanup_free_ char *t = NULL; | |
906 | ||
907 | assert(bus->sockaddr_size_peer >= offsetof(struct sockaddr_un, sun_path) + 1); | |
908 | assert(bus->sockaddr_peer.sa.sa_family == AF_UNIX); | |
909 | assert(bus->sockaddr_peer.un.sun_path[0] == 0); | |
910 | ||
911 | /* So this is an abstract namespace socket, good. Now let's find the data we are interested in */ | |
912 | r = make_cstring(bus->sockaddr_peer.un.sun_path + 1, | |
913 | bus->sockaddr_size_peer - offsetof(struct sockaddr_un, sun_path) - 1, | |
914 | MAKE_CSTRING_ALLOW_TRAILING_NUL, | |
915 | &t); | |
916 | if (r == -ENOMEM) | |
917 | return r; | |
918 | if (r < 0) | |
919 | log_debug_errno(r, "Can't extract string from peer socket address, ignoring: %m"); | |
920 | else { | |
921 | r = parse_sockaddr_string(t, &c->comm, &c->description); | |
922 | if (r < 0) | |
923 | return r; | |
924 | ||
925 | if (c->comm) | |
926 | c->mask |= SD_BUS_CREDS_COMM & mask; | |
927 | ||
928 | if (c->description) | |
929 | c->mask |= SD_BUS_CREDS_DESCRIPTION & mask; | |
930 | } | |
931 | } | |
932 | ||
71be6406 LP |
933 | if (do_pidfd) { |
934 | c->pidfd = fcntl(bus->pidfd, F_DUPFD_CLOEXEC, 3); | |
935 | if (c->pidfd < 0) | |
936 | return -errno; | |
937 | ||
938 | pidref_done(&pidref); | |
939 | r = pidref_set_pidfd(&pidref, bus->pidfd); | |
940 | if (r < 0) | |
941 | return r; | |
942 | ||
943 | c->mask |= SD_BUS_CREDS_PIDFD; | |
944 | } | |
945 | ||
946 | r = bus_creds_add_more(c, mask, &pidref, 0); | |
f8ecc2c0 | 947 | if (r < 0 && r != -ESRCH) /* If the process vanished, then don't complain, just return what we got */ |
705a415f LP |
948 | return r; |
949 | ||
1cc6c93a YW |
950 | *ret = TAKE_PTR(c); |
951 | ||
8f44e3ea DM |
952 | return 0; |
953 | } | |
954 | ||
e8bd7b09 | 955 | #define append_eavesdrop(bus, m) \ |
c7db1984 | 956 | ((bus)->is_monitor \ |
63c372cb | 957 | ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \ |
09365592 LP |
958 | : (m)) |
959 | ||
e8bd7b09 | 960 | int bus_add_match_internal( |
e7176abb | 961 | sd_bus *bus, |
6b39223c | 962 | const char *match, |
bb30e58f | 963 | uint64_t timeout_usec, |
6b39223c | 964 | uint64_t *ret_counter) { |
777d7a61 | 965 | |
bb30e58f | 966 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; |
09365592 | 967 | const char *e; |
6b39223c | 968 | int r; |
09365592 | 969 | |
e7176abb | 970 | assert(bus); |
777d7a61 | 971 | |
e8bd7b09 LP |
972 | if (!bus->bus_client) |
973 | return -EINVAL; | |
974 | ||
975 | e = append_eavesdrop(bus, match); | |
09365592 | 976 | |
bb30e58f | 977 | r = sd_bus_message_new_method_call( |
e7176abb | 978 | bus, |
bb30e58f | 979 | &m, |
e7176abb | 980 | "org.freedesktop.DBus", |
cd789fdf | 981 | "/org/freedesktop/DBus", |
e7176abb | 982 | "org.freedesktop.DBus", |
bb30e58f | 983 | "AddMatch"); |
984 | if (r < 0) | |
985 | return r; | |
986 | ||
987 | r = sd_bus_message_append(m, "s", e); | |
988 | if (r < 0) | |
989 | return r; | |
990 | ||
991 | r = sd_bus_call( | |
992 | bus, | |
993 | m, | |
994 | timeout_usec, | |
e7176abb | 995 | NULL, |
bb30e58f | 996 | &reply); |
6b39223c LP |
997 | if (r < 0) |
998 | return r; | |
999 | ||
1000 | /* If the caller asked for it, return the read counter of the reply */ | |
1001 | if (ret_counter) | |
1002 | *ret_counter = reply->read_counter; | |
1003 | ||
1004 | return r; | |
7593c7a4 | 1005 | } |
c0b471e1 | 1006 | |
7593c7a4 LP |
1007 | int bus_add_match_internal_async( |
1008 | sd_bus *bus, | |
1009 | sd_bus_slot **ret_slot, | |
1010 | const char *match, | |
1011 | sd_bus_message_handler_t callback, | |
bb30e58f | 1012 | void *userdata, |
1013 | uint64_t timeout_usec) { | |
7593c7a4 | 1014 | |
bb30e58f | 1015 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; |
7593c7a4 | 1016 | const char *e; |
bb30e58f | 1017 | int r; |
7593c7a4 LP |
1018 | |
1019 | assert(bus); | |
1020 | ||
1021 | if (!bus->bus_client) | |
1022 | return -EINVAL; | |
1023 | ||
1024 | e = append_eavesdrop(bus, match); | |
1025 | ||
bb30e58f | 1026 | r = sd_bus_message_new_method_call( |
7593c7a4 | 1027 | bus, |
bb30e58f | 1028 | &m, |
7593c7a4 LP |
1029 | "org.freedesktop.DBus", |
1030 | "/org/freedesktop/DBus", | |
1031 | "org.freedesktop.DBus", | |
bb30e58f | 1032 | "AddMatch"); |
1033 | if (r < 0) | |
1034 | return r; | |
1035 | ||
1036 | r = sd_bus_message_append(m, "s", e); | |
1037 | if (r < 0) | |
1038 | return r; | |
1039 | ||
1040 | return sd_bus_call_async( | |
1041 | bus, | |
1042 | ret_slot, | |
1043 | m, | |
7593c7a4 LP |
1044 | callback, |
1045 | userdata, | |
bb30e58f | 1046 | timeout_usec); |
de1c301e LP |
1047 | } |
1048 | ||
e8bd7b09 | 1049 | int bus_remove_match_internal( |
e7176abb LP |
1050 | sd_bus *bus, |
1051 | const char *match) { | |
777d7a61 | 1052 | |
09365592 LP |
1053 | const char *e; |
1054 | ||
e7176abb LP |
1055 | assert(bus); |
1056 | assert(match); | |
1057 | ||
e8bd7b09 LP |
1058 | if (!bus->bus_client) |
1059 | return -EINVAL; | |
1060 | ||
1061 | e = append_eavesdrop(bus, match); | |
09365592 | 1062 | |
acd34015 LP |
1063 | /* Fire and forget */ |
1064 | ||
1065 | return sd_bus_call_method_async( | |
e7176abb | 1066 | bus, |
acd34015 | 1067 | NULL, |
e7176abb | 1068 | "org.freedesktop.DBus", |
cd789fdf | 1069 | "/org/freedesktop/DBus", |
e7176abb LP |
1070 | "org.freedesktop.DBus", |
1071 | "RemoveMatch", | |
1072 | NULL, | |
1073 | NULL, | |
1074 | "s", | |
09365592 | 1075 | e); |
e7176abb LP |
1076 | } |
1077 | ||
31a1e15c | 1078 | _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *ret) { |
4afd3348 | 1079 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; |
70666185 LP |
1080 | const char *mid; |
1081 | int r; | |
1082 | ||
8d162091 | 1083 | assert_return(bus, -EINVAL); |
45b1f410 | 1084 | assert_return(bus = bus_resolve(bus), -ENOPKG); |
8d162091 | 1085 | assert_return(name, -EINVAL); |
31a1e15c | 1086 | assert_return(ret, -EINVAL); |
bf876e3f | 1087 | assert_return(!bus_origin_changed(bus), -ECHILD); |
45fd5e4d | 1088 | assert_return(service_name_is_valid(name), -EINVAL); |
70666185 | 1089 | |
33c62dcb LP |
1090 | if (!bus->bus_client) |
1091 | return -EINVAL; | |
1092 | ||
a3d59cd1 LP |
1093 | if (!BUS_IS_OPEN(bus->state)) |
1094 | return -ENOTCONN; | |
1095 | ||
70666185 | 1096 | if (streq_ptr(name, bus->unique_name)) |
31a1e15c | 1097 | return sd_id128_get_machine(ret); |
70666185 | 1098 | |
8d162091 LP |
1099 | r = sd_bus_message_new_method_call( |
1100 | bus, | |
151b9b96 | 1101 | &m, |
8d162091 LP |
1102 | name, |
1103 | "/", | |
1104 | "org.freedesktop.DBus.Peer", | |
151b9b96 | 1105 | "GetMachineId"); |
8d162091 LP |
1106 | if (r < 0) |
1107 | return r; | |
1108 | ||
eee9ec0e | 1109 | r = sd_bus_message_set_auto_start(m, false); |
8d162091 LP |
1110 | if (r < 0) |
1111 | return r; | |
70666185 | 1112 | |
8d162091 | 1113 | r = sd_bus_call(bus, m, 0, NULL, &reply); |
70666185 LP |
1114 | if (r < 0) |
1115 | return r; | |
1116 | ||
1117 | r = sd_bus_message_read(reply, "s", &mid); | |
1118 | if (r < 0) | |
1119 | return r; | |
1120 | ||
31a1e15c | 1121 | return sd_id128_from_string(mid, ret); |
70666185 | 1122 | } |