chiark / gitweb /
eec70ed15270c56e246e01597caa56695e4e09d9
[elogind.git] / src / libsystemd-bus / bus-util.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 #include <sys/socket.h>
23
24 #include "util.h"
25 #include "strv.h"
26 #include "macro.h"
27 #include "def.h"
28
29 #include "sd-event.h"
30 #include "sd-bus.h"
31 #include "bus-error.h"
32 #include "bus-message.h"
33
34 #include "bus-util.h"
35
36 static int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
37         sd_event *e = userdata;
38
39         assert(bus);
40         assert(m);
41         assert(e);
42
43         sd_event_request_quit(e);
44         return 1;
45 }
46
47 int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) {
48         _cleanup_free_ char *match = NULL;
49         int r;
50
51         assert(e);
52         assert(bus);
53         assert(name);
54
55         r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name);
56         if (r < 0)
57                 return r;
58
59         r = sd_bus_add_match(bus, match, quit_callback, e);
60         if (r < 0)
61                 return r;
62
63         r = sd_bus_release_name(bus, name);
64         if (r < 0)
65                 return r;
66
67         if (r != SD_BUS_NAME_RELEASED)
68                 return -EIO;
69
70         return 0;
71 }
72
73 int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
74         bool exiting = false;
75         int r;
76
77         assert(e);
78         assert(bus);
79         assert(name);
80
81         for (;;) {
82                 r = sd_event_get_state(e);
83                 if (r < 0)
84                         return r;
85
86                 if (r == SD_EVENT_FINISHED)
87                         break;
88
89                 r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
90                 if (r < 0)
91                         return r;
92
93                 if (r == 0 && !exiting) {
94                         r = bus_async_unregister_and_quit(e, bus, name);
95                         if (r < 0)
96                                 return r;
97
98                         exiting = true;
99                 }
100         }
101
102         return 0;
103 }
104
105 int bus_property_get_tristate(
106                 sd_bus *bus,
107                 const char *path,
108                 const char *interface,
109                 const char *property,
110                 sd_bus_message *reply,
111                 sd_bus_error *error,
112                 void *userdata) {
113
114         int *tristate = userdata;
115         int r;
116
117         r = sd_bus_message_append(reply, "b", *tristate > 0);
118         if (r < 0)
119                 return r;
120
121         return 1;
122 }
123
124 int bus_verify_polkit(
125                 sd_bus *bus,
126                 sd_bus_message *m,
127                 const char *action,
128                 bool interactive,
129                 bool *_challenge,
130                 sd_bus_error *e) {
131
132         const char *sender;
133         uid_t uid;
134         int r;
135
136         assert(bus);
137         assert(m);
138         assert(action);
139
140         sender = sd_bus_message_get_sender(m);
141         if (!sender)
142                 return -EBADMSG;
143
144         r = sd_bus_get_owner_uid(bus, sender, &uid);
145         if (r < 0)
146                 return r;
147
148         if (uid == 0)
149                 return 1;
150
151 #ifdef ENABLE_POLKIT
152         else {
153                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
154                 unsigned authorized = false, challenge = false;
155
156                 r = sd_bus_call_method(
157                                 bus,
158                                 "org.freedesktop.PolicyKit1",
159                                 "/org/freedesktop/PolicyKit1/Authority",
160                                 "org.freedesktop.PolicyKit1.Authority",
161                                 "CheckAuthorization",
162                                 e,
163                                 &reply,
164                                 "(sa{sv})sa{ss}us",
165                                 "system-bus-name", 1, "name", "s", sender,
166                                 action,
167                                 0,
168                                 interactive ? 1 : 0,
169                                 "");
170
171                 if (r < 0) {
172                         /* Treat no PK available as access denied */
173                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
174                                 sd_bus_error_free(e);
175                                 return -EACCES;
176                         }
177
178                         return r;
179                 }
180
181                 r = sd_bus_message_read(reply, "(bb)", &authorized, &challenge);
182                 if (r < 0)
183                         return r;
184
185                 if (authorized)
186                         return 1;
187
188                 if (_challenge) {
189                         *_challenge = challenge;
190                         return 0;
191                 }
192         }
193 #endif
194
195         return -EACCES;
196 }
197
198 #ifdef ENABLE_POLKIT
199
200 typedef struct AsyncPolkitQuery {
201         sd_bus_message *request, *reply;
202         sd_bus_message_handler_t callback;
203         void *userdata;
204         uint64_t serial;
205 } AsyncPolkitQuery;
206
207 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
208         AsyncPolkitQuery *q = userdata;
209         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
210         int r;
211
212         assert(bus);
213         assert(reply);
214         assert(q);
215
216         q->reply = sd_bus_message_ref(reply);
217         q->serial = 0;
218
219         m = sd_bus_message_ref(q->request);
220
221         r = sd_bus_message_rewind(m, true);
222         if (r < 0)
223                 return r;
224
225         r = q->callback(bus, m, q->userdata);
226         if (r < 0)
227                 return r;
228
229         return 1;
230 }
231
232 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
233
234         if (!q)
235                 return;
236
237         if (q->serial >  0 && b)
238                 sd_bus_send_with_reply_cancel(b, q->serial);
239
240         sd_bus_message_unref(q->request);
241         sd_bus_message_unref(q->reply);
242         free(q);
243 }
244
245 #endif
246
247 int bus_verify_polkit_async(
248                 sd_bus *bus,
249                 Hashmap **registry,
250                 sd_bus_message *m,
251                 const char *action,
252                 bool interactive,
253                 sd_bus_error *error,
254                 sd_bus_message_handler_t callback,
255                 void *userdata) {
256
257 #ifdef ENABLE_POLKIT
258         _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
259         AsyncPolkitQuery *q;
260 #endif
261         const char *sender;
262         uid_t uid;
263         int r;
264
265         assert(bus);
266         assert(registry);
267         assert(m);
268         assert(action);
269
270 #ifdef ENABLE_POLKIT
271         q = hashmap_remove(*registry, m);
272         if (q) {
273                 unsigned authorized, challenge;
274
275                 /* This is the second invocation of this function, and
276                  * there's already a response from polkit, let's
277                  * process it */
278                 assert(q->reply);
279
280                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
281                         const sd_bus_error *e;
282
283                         /* Treat no PK available as access denied */
284                         if (sd_bus_message_is_method_error(q->reply, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
285                                 async_polkit_query_free(bus, q);
286                                 return -EACCES;
287                         }
288
289                         e = sd_bus_message_get_error(q->reply);
290                         sd_bus_error_copy(error, e);
291                         r = sd_bus_error_get_errno(e);
292
293                         async_polkit_query_free(bus, q);
294                         return r;
295                 }
296
297                 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
298                 if (r >= 0)
299                         r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
300
301                 async_polkit_query_free(bus, q);
302
303                 if (r < 0)
304                         return r;
305
306                 if (authorized)
307                         return 1;
308
309                 return -EACCES;
310         }
311 #endif
312
313         sender = sd_bus_message_get_sender(m);
314         if (!sender)
315                 return -EBADMSG;
316
317         r = sd_bus_get_owner_uid(bus, sender, &uid);
318         if (r < 0)
319                 return r;
320
321         if (uid == 0)
322                 return 1;
323 #ifdef ENABLE_POLKIT
324
325         r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
326         if (r < 0)
327                 return r;
328
329         r = sd_bus_message_new_method_call(
330                         bus,
331                         "org.freedesktop.PolicyKit1",
332                         "/org/freedesktop/PolicyKit1/Authority",
333                         "org.freedesktop.PolicyKit1.Authority",
334                         "CheckAuthorization",
335                         &pk);
336         if (r < 0)
337                 return r;
338
339         r = sd_bus_message_append(
340                         pk,
341                         "(sa{sv})sa{ss}us",
342                         "system-bus-name", 1, "name", "s", sender,
343                         action,
344                         0,
345                         interactive ? 1 : 0,
346                         "");
347         if (r < 0)
348                 return r;
349
350         q = new0(AsyncPolkitQuery, 1);
351         if (!q)
352                 return -ENOMEM;
353
354         q->request = sd_bus_message_ref(m);
355         q->callback = callback;
356         q->userdata = userdata;
357
358         r = hashmap_put(*registry, m, q);
359         if (r < 0) {
360                 async_polkit_query_free(bus, q);
361                 return r;
362         }
363
364         r = sd_bus_send_with_reply(bus, pk, async_polkit_callback, q, 0, &q->serial);
365         if (r < 0)
366                 return r;
367
368         return 0;
369 #endif
370
371         return -EACCES;
372 }
373
374 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
375 #ifdef ENABLE_POLKIT
376         AsyncPolkitQuery *q;
377
378         while ((q = hashmap_steal_first(registry)))
379                 async_polkit_query_free(bus, q);
380
381         hashmap_free(registry);
382 #endif
383 }
384
385 static int bus_check_peercred(sd_bus *c) {
386         struct ucred ucred;
387         socklen_t l;
388         int fd;
389
390         assert(c);
391
392         fd = sd_bus_get_fd(c);
393         if (fd < 0)
394                 return fd;
395
396         l = sizeof(struct ucred);
397         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
398                 return -errno;
399
400         if (l != sizeof(struct ucred))
401                 return -E2BIG;
402
403         if (ucred.uid != 0 && ucred.uid != geteuid())
404                 return -EPERM;
405
406         return 1;
407 }
408
409 int bus_open_system_systemd(sd_bus **_bus) {
410         _cleanup_bus_unref_ sd_bus *bus = NULL;
411         int r;
412
413         assert(_bus);
414
415         if (geteuid() != 0)
416                 return sd_bus_open_system(_bus);
417
418         /* If we are root, then let's talk directly to the system
419          * instance, instead of going via the bus */
420
421         r = sd_bus_new(&bus);
422         if (r < 0)
423                 return r;
424
425         r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
426         if (r < 0)
427                 return r;
428
429         r = sd_bus_start(bus);
430         if (r < 0)
431                 return r;
432
433         r = bus_check_peercred(bus);
434         if (r < 0)
435                 return r;
436
437         *_bus = bus;
438         bus = NULL;
439
440         return 0;
441 }
442
443 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
444         char type;
445         const char *contents;
446         int r;
447
448         assert(name);
449         assert(property);
450
451         r = sd_bus_message_peek_type(property, &type, &contents);
452         if (r < 0)
453                 return r;
454
455         switch (type) {
456
457         case SD_BUS_TYPE_STRING: {
458                 const char *s;
459
460                 r = sd_bus_message_read_basic(property, type, &s);
461                 if (r < 0)
462                         return r;
463
464                 if (all || !isempty(s))
465                         printf("%s=%s\n", name, s);
466
467                 return 1;
468         }
469
470         case SD_BUS_TYPE_BOOLEAN: {
471                 bool b;
472
473                 r = sd_bus_message_read_basic(property, type, &b);
474                 if (r < 0)
475                         return r;
476
477                 printf("%s=%s\n", name, yes_no(b));
478
479                 return 1;
480         }
481
482         case SD_BUS_TYPE_UINT64: {
483                 uint64_t u;
484
485                 r = sd_bus_message_read_basic(property, type, &u);
486                 if (r < 0)
487                         return r;
488
489                 /* Yes, heuristics! But we can change this check
490                  * should it turn out to not be sufficient */
491
492                 if (endswith(name, "Timestamp")) {
493                         char timestamp[FORMAT_TIMESTAMP_MAX], *t;
494
495                         t = format_timestamp(timestamp, sizeof(timestamp), u);
496                         if (t || all)
497                                 printf("%s=%s\n", name, strempty(t));
498
499                 } else if (strstr(name, "USec")) {
500                         char timespan[FORMAT_TIMESPAN_MAX];
501
502                         printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
503                 } else
504                         printf("%s=%llu\n", name, (unsigned long long) u);
505
506                 return 1;
507         }
508
509         case SD_BUS_TYPE_UINT32: {
510                 uint32_t u;
511
512                 r = sd_bus_message_read_basic(property, type, &u);
513                 if (r < 0)
514                         return r;
515
516                 if (strstr(name, "UMask") || strstr(name, "Mode"))
517                         printf("%s=%04o\n", name, u);
518                 else
519                         printf("%s=%u\n", name, (unsigned) u);
520
521                 return 1;
522         }
523
524         case SD_BUS_TYPE_INT32: {
525                 int32_t i;
526
527                 r = sd_bus_message_read_basic(property, type, &i);
528                 if (r < 0)
529                         return r;
530
531                 printf("%s=%i\n", name, (int) i);
532                 return 1;
533         }
534
535         case SD_BUS_TYPE_DOUBLE: {
536                 double d;
537
538                 r = sd_bus_message_read_basic(property, type, &d);
539                 if (r < 0)
540                         return r;
541
542                 printf("%s=%g\n", name, d);
543                 return 1;
544         }
545
546         case SD_BUS_TYPE_ARRAY:
547                 if (streq(contents, "s")) {
548                         bool space = false;
549                         char tp;
550                         const char *cnt;
551
552                         r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
553                         if (r < 0)
554                                 return r;
555
556                         r = sd_bus_message_peek_type(property, &tp, &cnt);
557                         if (r < 0)
558                                 return r;
559
560                         if (all || cnt) {
561                                 const char *str;
562
563                                 printf("%s=", name);
564
565                                 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) >= 0) {
566                                         printf("%s%s", space ? " " : "", str);
567
568                                         space = true;
569                                 }
570                                 if (r < 0)
571                                         return r;
572
573                                 puts("");
574                         }
575
576                         r = sd_bus_message_exit_container(property);
577                         if (r < 0)
578                                 return r;
579
580                         return 1;
581
582                 } else if (streq(contents, "y")) {
583                         const uint8_t *u;
584                         size_t n;
585
586                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
587                         if (r < 0)
588                                 return r;
589
590                         if (all || n > 0) {
591                                 unsigned int i;
592
593                                 printf("%s=", name);
594
595                                 for (i = 0; i < n; i++)
596                                         printf("%02x", u[i]);
597
598                                 puts("");
599                         }
600
601                         return 1;
602
603                 } else if (streq(contents, "u")) {
604                         uint32_t *u;
605                         size_t n;
606
607                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
608                         if (r < 0)
609                                 return r;
610
611                         if (all || n > 0) {
612                                 unsigned int i;
613
614                                 printf("%s=", name);
615
616                                 for (i = 0; i < n; i++)
617                                         printf("%08x", u[i]);
618
619                                 puts("");
620                         }
621
622                         return 1;
623                 }
624
625                 break;
626         }
627
628         return 0;
629 }
630
631 int bus_print_all_properties(sd_bus *bus, const char *path, char **filter, bool all) {
632         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
633         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
634         int r;
635
636         assert(bus);
637         assert(path);
638
639         r = sd_bus_call_method(bus,
640                         "org.freedesktop.machine1",
641                         path,
642                         "org.freedesktop.DBus.Properties",
643                         "GetAll",
644                         &error,
645                         &reply,
646                         "s", "");
647         if (r < 0)
648                 return r;
649
650         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
651         if (r < 0)
652                 return r;
653
654         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
655                 const char *name;
656                 const char *contents;
657
658                 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
659                 if (r < 0)
660                         return r;
661
662                 if (!filter || strv_find(filter, name)) {
663                         r = sd_bus_message_peek_type(reply, NULL, &contents);
664                         if (r < 0)
665                                 return r;
666
667                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
668                         if (r < 0)
669                                 return r;
670
671                         r = bus_print_property(name, reply, all);
672                         if (r < 0)
673                                 return r;
674                         if (r == 0 && all)
675                                 printf("%s=[unprintable]\n", name);
676
677                         r = sd_bus_message_exit_container(reply);
678                         if (r < 0)
679                                 return r;
680                 } else {
681                         r = sd_bus_message_skip(reply, "v");
682                         if (r < 0)
683                                 return r;
684                 }
685
686                 r = sd_bus_message_exit_container(reply);
687                 if (r < 0)
688                         return r;
689         }
690         if (r < 0)
691                 return r;
692
693         r = sd_bus_message_exit_container(reply);
694         if (r < 0)
695                 return r;
696
697         return 0;
698 }
699
700 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
701         sd_id128_t *p = userdata;
702         const void *v;
703         size_t n;
704         int r;
705
706         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
707         if (r < 0)
708                 return r;
709
710         if (n == 0)
711                 *p = SD_ID128_NULL;
712         else if (n == 16)
713                 memcpy((*p).bytes, v, n);
714         else
715                 return -EINVAL;
716
717         return 0;
718 }
719
720 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
721         char type;
722         int r;
723
724         r = sd_bus_message_peek_type(m, &type, NULL);
725         if (r < 0)
726                 return r;
727
728         switch (type) {
729         case SD_BUS_TYPE_STRING: {
730                 const char *s;
731                 char *str;
732                 char **p = userdata;
733
734                 r = sd_bus_message_read_basic(m, type, &s);
735                 if (r < 0)
736                         break;
737
738                 if (isempty(s))
739                         break;
740
741                 str = strdup(s);
742                 if (!str) {
743                         r = -ENOMEM;
744                         break;
745                 }
746                 free(*p);
747                 *p = str;
748
749                 break;
750         }
751
752         case SD_BUS_TYPE_ARRAY: {
753                _cleanup_strv_free_ char **l = NULL;
754                char ***p = userdata;
755
756                 r = bus_message_read_strv_extend(m, &l);
757                 if (r < 0)
758                         break;
759
760                 strv_free(*p);
761                 *p = l;
762                 l = NULL;
763
764                 break;
765         }
766
767         case SD_BUS_TYPE_BOOLEAN: {
768                 unsigned b;
769                 bool *p = userdata;
770
771                 r = sd_bus_message_read_basic(m, type, &b);
772                 if (r < 0)
773                         break;
774
775                 *p = b;
776
777                 break;
778         }
779
780         case SD_BUS_TYPE_UINT32: {
781                 uint64_t u;
782                 uint32_t *p = userdata;
783
784                 r = sd_bus_message_read_basic(m, type, &u);
785                 if (r < 0)
786                         break;
787
788                 *p = u;
789
790                 break;
791         }
792
793         case SD_BUS_TYPE_UINT64: {
794                 uint64_t t;
795                 uint64_t *p = userdata;
796
797                 r = sd_bus_message_read_basic(m, type, &t);
798                 if (r < 0)
799                         break;
800
801                 *p = t;
802
803                 break;
804         }
805
806         default:
807                 break;
808         }
809
810         return r;
811 }
812
813 int bus_map_all_properties(sd_bus *bus,
814                            const char *destination,
815                            const char *path,
816                            const struct bus_properties_map *map,
817                            void *userdata) {
818         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
819         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
820         int r;
821
822         assert(bus);
823         assert(destination);
824         assert(path);
825         assert(map);
826
827         r = sd_bus_call_method( bus,
828                         destination,
829                         path,
830                         "org.freedesktop.DBus.Properties",
831                         "GetAll",
832                         &error,
833                         &m,
834                         "s", "");
835         if (r < 0)
836                 return r;
837
838         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
839         if (r < 0)
840                 return r;
841
842         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
843                 const struct bus_properties_map *prop;
844                 const char *member;
845                 const char *contents;
846                 void *v;
847                 unsigned i;
848
849                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
850                 if (r < 0)
851                         return r;
852
853                 for (i = 0, prop = NULL; map[i].member; i++)
854                         if (streq(map[i].member, member)) {
855                                 prop = &map[i];
856                                 break;
857                         }
858
859                 if (prop) {
860                         r = sd_bus_message_peek_type(m, NULL, &contents);
861                         if (r < 0)
862                                 return r;
863
864                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
865                         if (r < 0)
866                                 return r;
867
868                         v = (uint8_t *)userdata + prop->offset;
869                                 if (map[i].set)
870                                 r = prop->set(bus, member, m, &error, v);
871                         else
872                                 r = map_basic(bus, member, m, &error, v);
873
874                         r = sd_bus_message_exit_container(m);
875                         if (r < 0)
876                                 return r;
877                 } else {
878                         r = sd_bus_message_skip(m, "v");
879                         if (r < 0)
880                                 return -r;
881                 }
882
883                 r = sd_bus_message_exit_container(m);
884                 if (r < 0)
885                         return r;
886         }
887
888         return r;
889 }
890
891 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
892         int r;
893
894         assert(transport >= 0);
895         assert(transport < _BUS_TRANSPORT_MAX);
896         assert(bus);
897
898         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
899         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
900
901         switch (transport) {
902
903         case BUS_TRANSPORT_LOCAL:
904                 if (user)
905                         r = sd_bus_open_user(bus);
906                 else
907                         r = sd_bus_open_system(bus);
908
909                 break;
910
911         case BUS_TRANSPORT_REMOTE:
912                 r = sd_bus_open_system_remote(host, bus);
913                 break;
914
915         case BUS_TRANSPORT_CONTAINER:
916                 r = sd_bus_open_system_container(host, bus);
917                 break;
918
919         default:
920                 assert_not_reached("Hmm, unknown transport type.");
921         }
922
923         return r;
924 }
925
926 int bus_property_get_bool(
927                 sd_bus *bus,
928                 const char *path,
929                 const char *interface,
930                 const char *property,
931                 sd_bus_message *reply,
932                 sd_bus_error *error,
933                 void *userdata) {
934
935         int b = *(bool*) userdata;
936
937         return sd_bus_message_append_basic(reply, 'b', &b);
938 }
939
940 int bus_property_get_uid(
941                 sd_bus *bus,
942                 const char *path,
943                 const char *interface,
944                 const char *property,
945                 sd_bus_message *reply,
946                 sd_bus_error *error,
947                 void *userdata) {
948
949         assert_cc(sizeof(uint32_t) == sizeof(uid_t));
950         assert_cc(sizeof(uint32_t) == sizeof(gid_t));
951         assert_cc(sizeof(uint32_t) == sizeof(pid_t));
952
953         return sd_bus_message_append_basic(reply, 'u', userdata);
954 }