chiark / gitweb /
libsystemd-bus: use assert_return
[elogind.git] / src / libsystemd-bus / bus-message.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 <errno.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25
26 #include "util.h"
27 #include "utf8.h"
28 #include "strv.h"
29 #include "time-util.h"
30 #include "cgroup-util.h"
31
32 #include "sd-bus.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
35 #include "bus-type.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
38
39 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
40
41 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
42
43         if (p == NULL)
44                 return NULL;
45
46         if (old_base == new_base)
47                 return (void*) p;
48
49         if ((uint8_t*) p < (uint8_t*) old_base)
50                 return (void*) p;
51
52         if ((uint8_t*) p >= (uint8_t*) old_base + sz)
53                 return (void*) p;
54
55         return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
56 }
57
58 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
59         assert(m);
60         assert(part);
61
62         if (part->memfd >= 0) {
63                 /* If we can reuse the memfd, try that. For that it
64                  * can't be sealed yet. */
65
66                 if (!part->sealed)
67                         bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
68                 else {
69                         if (part->mapped > 0)
70                                 assert_se(munmap(part->data, part->mapped) == 0);
71
72                         close_nointr_nofail(part->memfd);
73                 }
74
75         } else if (part->munmap_this)
76                 munmap(part->data, part->mapped);
77         else if (part->free_this)
78                 free(part->data);
79
80         if (part != &m->body)
81                 free(part);
82 }
83
84 static void message_reset_parts(sd_bus_message *m) {
85         struct bus_body_part *part;
86
87         assert(m);
88
89         part = &m->body;
90         while (m->n_body_parts > 0) {
91                 struct bus_body_part *next = part->next;
92                 message_free_part(m, part);
93                 part = next;
94                 m->n_body_parts--;
95         }
96
97         m->body_end = NULL;
98
99         m->cached_rindex_part = NULL;
100         m->cached_rindex_part_begin = 0;
101 }
102
103 static void message_reset_containers(sd_bus_message *m) {
104         unsigned i;
105
106         assert(m);
107
108         for (i = 0; i < m->n_containers; i++) {
109                 free(m->containers[i].signature);
110                 free(m->containers[i].offsets);
111         }
112
113         free(m->containers);
114         m->containers = NULL;
115
116         m->n_containers = 0;
117         m->root_container.index = 0;
118 }
119
120 static void message_free(sd_bus_message *m) {
121         assert(m);
122
123         if (m->free_header)
124                 free(m->header);
125
126         message_reset_parts(m);
127
128         if (m->free_kdbus)
129                 free(m->kdbus);
130
131         if (m->release_kdbus) {
132                 uint64_t off;
133
134                 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135                 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
136         }
137
138         if (m->bus)
139                 sd_bus_unref(m->bus);
140
141         if (m->free_fds) {
142                 close_many(m->fds, m->n_fds);
143                 free(m->fds);
144         }
145
146         if (m->iovec != m->iovec_fixed)
147                 free(m->iovec);
148
149         message_reset_containers(m);
150         free(m->root_container.signature);
151         free(m->root_container.offsets);
152
153         free(m->peeked_signature);
154
155         bus_creds_done(&m->creds);
156         free(m);
157 }
158
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
160         void *op, *np;
161         size_t old_size, new_size, start;
162
163         assert(m);
164         assert_return(!m->poisoned, NULL);
165
166         old_size = sizeof(struct bus_header) + m->header->fields_size;
167         start = ALIGN_TO(old_size, align);
168         new_size = start + sz;
169
170         if (old_size == new_size)
171                 return (uint8_t*) m->header + old_size;
172
173         if (new_size > (size_t) ((uint32_t) -1))
174                 goto poison;
175
176         if (m->free_header) {
177                 np = realloc(m->header, ALIGN8(new_size));
178                 if (!np)
179                         goto poison;
180         } else {
181                 /* Initially, the header is allocated as part of of
182                  * the sd_bus_message itself, let's replace it by
183                  * dynamic data */
184
185                 np = malloc(ALIGN8(new_size));
186                 if (!np)
187                         goto poison;
188
189                 memcpy(np, m->header, sizeof(struct bus_header));
190         }
191
192         /* Zero out padding */
193         if (start > old_size)
194                 memset((uint8_t*) np + old_size, 0, start - old_size);
195
196         op = m->header;
197         m->header = np;
198         m->header->fields_size = new_size - sizeof(struct bus_header);
199
200         /* Adjust quick access pointers */
201         m->path = adjust_pointer(m->path, op, old_size, m->header);
202         m->interface = adjust_pointer(m->interface, op, old_size, m->header);
203         m->member = adjust_pointer(m->member, op, old_size, m->header);
204         m->destination = adjust_pointer(m->destination, op, old_size, m->header);
205         m->sender = adjust_pointer(m->sender, op, old_size, m->header);
206         m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
207
208         m->free_header = true;
209
210         if (add_offset) {
211                 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
212                         goto poison;
213
214                 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
215         }
216
217         return (uint8_t*) np + start;
218
219 poison:
220         m->poisoned = true;
221         return NULL;
222 }
223
224 static int message_append_field_string(
225                 sd_bus_message *m,
226                 uint8_t h,
227                 char type,
228                 const char *s,
229                 const char **ret) {
230
231         size_t l;
232         uint8_t *p;
233
234         assert(m);
235
236         /* dbus1 doesn't allow strings over 32bit, let's enforce this
237          * globally, to not risk convertability */
238         l = strlen(s);
239         if (l > (size_t) (uint32_t) -1)
240                 return -EINVAL;
241
242         /* Signature "(yv)" where the variant contains "s" */
243
244         if (BUS_MESSAGE_IS_GVARIANT(m)) {
245
246                 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
247                 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
248                 if (!p)
249                         return -ENOMEM;
250
251                 p[0] = h;
252                 memset(p+1, 0, 7);
253                 memcpy(p+8, s, l);
254                 p[8+l] = 0;
255                 p[8+l+1] = 0;
256                 p[8+l+2] = type;
257
258                 if (ret)
259                         *ret = (char*) p + 8;
260
261         } else {
262                 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
263                 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
264                 if (!p)
265                         return -ENOMEM;
266
267                 p[0] = h;
268                 p[1] = 1;
269                 p[2] = type;
270                 p[3] = 0;
271
272                 ((uint32_t*) p)[1] = l;
273                 memcpy(p + 8, s, l + 1);
274
275                 if (ret)
276                         *ret = (char*) p + 8;
277         }
278
279         return 0;
280 }
281
282 static int message_append_field_signature(
283                 sd_bus_message *m,
284                 uint8_t h,
285                 const char *s,
286                 const char **ret) {
287
288         size_t l;
289         uint8_t *p;
290
291         assert(m);
292
293         /* dbus1 doesn't allow signatures over 32bit, let's enforce
294          * this globally, to not risk convertability */
295         l = strlen(s);
296         if (l > 255)
297                 return -EINVAL;
298
299         /* Signature "(yv)" where the variant contains "g" */
300
301         if (BUS_MESSAGE_IS_GVARIANT(m))
302                 /* For gvariant the serialization is the same as for normal strings */
303                 return message_append_field_string(m, h, 'g', s, ret);
304         else {
305                 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
306                 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
307                 if (!p)
308                         return -ENOMEM;
309
310                 p[0] = h;
311                 p[1] = 1;
312                 p[2] = SD_BUS_TYPE_SIGNATURE;
313                 p[3] = 0;
314                 p[4] = l;
315                 memcpy(p + 5, s, l + 1);
316
317                 if (ret)
318                         *ret = (const char*) p + 5;
319         }
320
321         return 0;
322 }
323
324 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
325         uint8_t *p;
326
327         assert(m);
328
329         if (BUS_MESSAGE_IS_GVARIANT(m)) {
330                 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
331
332                 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
333                 if (!p)
334                         return -ENOMEM;
335
336                 p[0] = h;
337                 memset(p+1, 0, 7);
338                 *((uint32_t*) (p + 8)) = x;
339                 p[12] = 0;
340                 p[13] = 'u';
341         } else {
342                 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
343                 p = message_extend_fields(m, 8, 4 + 4, false);
344                 if (!p)
345                         return -ENOMEM;
346
347                 p[0] = h;
348                 p[1] = 1;
349                 p[2] = SD_BUS_TYPE_UINT32;
350                 p[3] = 0;
351
352                 ((uint32_t*) p)[1] = x;
353         }
354
355         return 0;
356 }
357
358 int bus_message_from_header(
359                 sd_bus *bus,
360                 void *buffer,
361                 size_t length,
362                 int *fds,
363                 unsigned n_fds,
364                 const struct ucred *ucred,
365                 const char *label,
366                 size_t extra,
367                 sd_bus_message **ret) {
368
369         sd_bus_message *m;
370         struct bus_header *h;
371         size_t a, label_sz;
372
373         assert(buffer || length <= 0);
374         assert(fds || n_fds <= 0);
375         assert(ret);
376
377         if (length < sizeof(struct bus_header))
378                 return -EBADMSG;
379
380         h = buffer;
381         if (h->version != 1 &&
382             h->version != 2)
383                 return -EBADMSG;
384
385         if (h->serial == 0)
386                 return -EBADMSG;
387
388         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
389                 return -EBADMSG;
390
391         if (h->endian != BUS_LITTLE_ENDIAN &&
392             h->endian != BUS_BIG_ENDIAN)
393                 return -EBADMSG;
394
395         a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
396
397         if (label) {
398                 label_sz = strlen(label);
399                 a += label_sz + 1;
400         }
401
402         m = malloc0(a);
403         if (!m)
404                 return -ENOMEM;
405
406         m->n_ref = 1;
407         m->sealed = true;
408         m->header = h;
409         m->fds = fds;
410         m->n_fds = n_fds;
411
412         if (ucred) {
413                 m->creds.uid = ucred->uid;
414                 m->creds.pid = ucred->pid;
415                 m->creds.gid = ucred->gid;
416                 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
417         }
418
419         if (label) {
420                 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
421                 memcpy(m->creds.label, label, label_sz + 1);
422
423                 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
424         }
425
426         if (bus)
427                 m->bus = sd_bus_ref(bus);
428
429         *ret = m;
430         return 0;
431 }
432
433 int bus_message_from_malloc(
434                 sd_bus *bus,
435                 void *buffer,
436                 size_t length,
437                 int *fds,
438                 unsigned n_fds,
439                 const struct ucred *ucred,
440                 const char *label,
441                 sd_bus_message **ret) {
442
443         sd_bus_message *m;
444         size_t sz;
445         int r;
446
447         r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
448         if (r < 0)
449                 return r;
450
451         if (length != BUS_MESSAGE_SIZE(m)) {
452                 r = -EBADMSG;
453                 goto fail;
454         }
455
456         sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
457         if (sz > 0) {
458                 m->n_body_parts = 1;
459                 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
460                 m->body.size = sz;
461                 m->body.sealed = true;
462                 m->body.memfd = -1;
463         }
464
465         m->n_iovec = 1;
466         m->iovec = m->iovec_fixed;
467         m->iovec[0].iov_base = buffer;
468         m->iovec[0].iov_len = length;
469
470         r = bus_message_parse_fields(m);
471         if (r < 0)
472                 goto fail;
473
474         /* We take possession of the memory and fds now */
475         m->free_header = true;
476         m->free_fds = true;
477
478         *ret = m;
479         return 0;
480
481 fail:
482         message_free(m);
483         return r;
484 }
485
486 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
487         sd_bus_message *m;
488
489         m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
490         if (!m)
491                 return NULL;
492
493         m->n_ref = 1;
494         m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
495         m->header->endian = BUS_NATIVE_ENDIAN;
496         m->header->type = type;
497         m->header->version = bus ? bus->message_version : 1;
498         m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
499         m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
500
501         if (bus)
502                 m->bus = sd_bus_ref(bus);
503
504         return m;
505 }
506
507 _public_ int sd_bus_message_new_signal(
508                 sd_bus *bus,
509                 const char *path,
510                 const char *interface,
511                 const char *member,
512                 sd_bus_message **m) {
513
514         sd_bus_message *t;
515         int r;
516
517         assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
518         assert_return(object_path_is_valid(path), -EINVAL);
519         assert_return(interface_name_is_valid(interface), -EINVAL);
520         assert_return(member_name_is_valid(member), -EINVAL);
521         assert_return(m, -EINVAL);
522
523         t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
524         if (!t)
525                 return -ENOMEM;
526
527         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
528
529         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
530         if (r < 0)
531                 goto fail;
532         r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
533         if (r < 0)
534                 goto fail;
535         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
536         if (r < 0)
537                 goto fail;
538
539         *m = t;
540         return 0;
541
542 fail:
543         sd_bus_message_unref(t);
544         return r;
545 }
546
547 _public_ int sd_bus_message_new_method_call(
548                 sd_bus *bus,
549                 const char *destination,
550                 const char *path,
551                 const char *interface,
552                 const char *member,
553                 sd_bus_message **m) {
554
555         sd_bus_message *t;
556         int r;
557
558         assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
559         assert_return(!destination || service_name_is_valid(destination), -EINVAL);
560         assert_return(object_path_is_valid(path), -EINVAL);
561         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
562         assert_return(member_name_is_valid(member), -EINVAL);
563         assert_return(m, -EINVAL);
564
565         t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
566         if (!t)
567                 return -ENOMEM;
568
569         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
570         if (r < 0)
571                 goto fail;
572         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
573         if (r < 0)
574                 goto fail;
575
576         if (interface) {
577                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
578                 if (r < 0)
579                         goto fail;
580         }
581
582         if (destination) {
583                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
584                 if (r < 0)
585                         goto fail;
586         }
587
588         *m = t;
589         return 0;
590
591 fail:
592         message_free(t);
593         return r;
594 }
595
596 static int message_new_reply(
597                 sd_bus_message *call,
598                 uint8_t type,
599                 sd_bus_message **m) {
600
601         sd_bus_message *t;
602         int r;
603
604         assert_return(call, -EINVAL);
605         assert_return(call->sealed, -EPERM);
606         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
607         assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
608         assert_return(m, -EINVAL);
609
610         t = message_new(call->bus, type);
611         if (!t)
612                 return -ENOMEM;
613
614         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
615         t->reply_serial = BUS_MESSAGE_SERIAL(call);
616
617         r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
618         if (r < 0)
619                 goto fail;
620
621         if (call->sender) {
622                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
623                 if (r < 0)
624                         goto fail;
625         }
626
627         t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
628         t->enforced_reply_signature = call->enforced_reply_signature;
629
630         *m = t;
631         return 0;
632
633 fail:
634         message_free(t);
635         return r;
636 }
637
638 _public_ int sd_bus_message_new_method_return(
639                 sd_bus_message *call,
640                 sd_bus_message **m) {
641
642         return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
643 }
644
645 _public_ int sd_bus_message_new_method_error(
646                 sd_bus_message *call,
647                 const sd_bus_error *e,
648                 sd_bus_message **m) {
649
650         sd_bus_message *t;
651         int r;
652
653         assert_return(sd_bus_error_is_set(e), -EINVAL);
654         assert_return(m, -EINVAL);
655
656         r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
657         if (r < 0)
658                 return r;
659
660         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
661         if (r < 0)
662                 goto fail;
663
664         if (e->message) {
665                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
666                 if (r < 0)
667                         goto fail;
668         }
669
670         t->error._need_free = -1;
671
672         *m = t;
673         return 0;
674
675 fail:
676         message_free(t);
677         return r;
678 }
679
680 _public_ int sd_bus_message_new_method_errorf(
681                 sd_bus_message *call,
682                 sd_bus_message **m,
683                 const char *name,
684                 const char *format,
685                 ...) {
686
687         _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
688         va_list ap;
689
690         assert_return(name, -EINVAL);
691         assert_return(m, -EINVAL);
692
693         va_start(ap, format);
694         bus_error_setfv(&error, name, format, ap);
695         va_end(ap);
696
697         return sd_bus_message_new_method_error(call, &error, m);
698 }
699
700 _public_ int sd_bus_message_new_method_errno(
701                 sd_bus_message *call,
702                 int error,
703                 const sd_bus_error *p,
704                 sd_bus_message **m) {
705
706         _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
707
708         if (sd_bus_error_is_set(p))
709                 return sd_bus_message_new_method_error(call, p, m);
710
711         sd_bus_error_set_errno(&berror, error);
712
713         return sd_bus_message_new_method_error(call, &berror, m);
714 }
715
716 _public_ int sd_bus_message_new_method_errnof(
717                 sd_bus_message *call,
718                 sd_bus_message **m,
719                 int error,
720                 const char *format,
721                 ...) {
722
723         _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
724         va_list ap;
725
726         va_start(ap, format);
727         bus_error_set_errnofv(&berror, error, format, ap);
728         va_end(ap);
729
730         return sd_bus_message_new_method_error(call, &berror, m);
731 }
732
733 int bus_message_new_synthetic_error(
734                 sd_bus *bus,
735                 uint64_t serial,
736                 const sd_bus_error *e,
737                 sd_bus_message **m) {
738
739         sd_bus_message *t;
740         int r;
741
742         assert(sd_bus_error_is_set(e));
743         assert(m);
744
745         t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
746         if (!t)
747                 return -ENOMEM;
748
749         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
750         t->reply_serial = serial;
751
752         r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
753         if (r < 0)
754                 goto fail;
755
756         if (bus && bus->unique_name) {
757                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
758                 if (r < 0)
759                         goto fail;
760         }
761
762         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
763         if (r < 0)
764                 goto fail;
765
766         if (e->message) {
767                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
768                 if (r < 0)
769                         goto fail;
770         }
771
772         t->error._need_free = -1;
773
774         *m = t;
775         return 0;
776
777 fail:
778         message_free(t);
779         return r;
780 }
781
782 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
783         assert_return(m, NULL);
784
785         assert(m->n_ref > 0);
786         m->n_ref++;
787
788         return m;
789 }
790
791 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
792         assert_return(m, NULL);
793
794         assert(m->n_ref > 0);
795         m->n_ref--;
796
797         if (m->n_ref <= 0)
798                 message_free(m);
799
800         return NULL;
801 }
802
803 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
804         assert_return(m, -EINVAL);
805         assert_return(type, -EINVAL);
806
807         *type = m->header->type;
808         return 0;
809 }
810
811 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
812         assert_return(m, -EINVAL);
813         assert_return(serial, -EINVAL);
814         assert_return(m->header->serial != 0, -ENOENT);
815
816         *serial = BUS_MESSAGE_SERIAL(m);
817         return 0;
818 }
819
820 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
821         assert_return(m, -EINVAL);
822         assert_return(serial, -EINVAL);
823         assert_return(m->reply_serial != 0, -ENOENT);
824
825         *serial = m->reply_serial;
826         return 0;
827 }
828
829 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
830         assert_return(m, -EINVAL);
831
832         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
833 }
834
835 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
836         assert_return(m, -EINVAL);
837
838         return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
839 }
840
841 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
842         assert_return(m, NULL);
843
844         return m->path;
845 }
846
847 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
848         assert_return(m, NULL);
849
850         return m->interface;
851 }
852
853 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
854         assert_return(m, NULL);
855
856         return m->member;
857 }
858
859 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
860         assert_return(m, NULL);
861
862         return m->destination;
863 }
864
865 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
866         assert_return(m, NULL);
867
868         return m->sender;
869 }
870
871 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
872         assert_return(m, NULL);
873         assert_return(sd_bus_error_is_set(&m->error), NULL);
874
875         return &m->error;
876 }
877
878 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
879         assert_return(m, -EINVAL);
880         assert_return(usec, -EINVAL);
881         assert_return(m->monotonic > 0, -ENODATA);
882
883         *usec = m->monotonic;
884         return 0;
885 }
886
887 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
888         assert_return(m, -EINVAL);
889         assert_return(usec, -EINVAL);
890         assert_return(m->realtime > 0, -ENODATA);
891
892         *usec = m->realtime;
893         return 0;
894 }
895
896 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
897         assert_return(m, NULL);
898
899         if (m->creds.mask == 0)
900                 return NULL;
901
902         return &m->creds;
903 }
904
905 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
906                                       const char *interface,
907                                       const char *member) {
908         assert_return(m, -EINVAL);
909
910         if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
911                 return 0;
912
913         if (interface && (!m->interface || !streq(m->interface, interface)))
914                 return 0;
915
916         if (member &&  (!m->member || !streq(m->member, member)))
917                 return 0;
918
919         return 1;
920 }
921
922 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
923                                            const char *interface,
924                                            const char *member) {
925         assert_return(m, -EINVAL);
926
927         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
928                 return 0;
929
930         if (interface && (!m->interface || !streq(m->interface, interface)))
931                 return 0;
932
933         if (member &&  (!m->member || !streq(m->member, member)))
934                 return 0;
935
936         return 1;
937 }
938
939 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
940         assert_return(m, -EINVAL);
941
942         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
943                 return 0;
944
945         if (name && (!m->error.name || !streq(m->error.name, name)))
946                 return 0;
947
948         return 1;
949 }
950
951 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
952         assert_return(m, -EINVAL);
953         assert_return(!m->sealed, -EPERM);
954         assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
955
956         if (b)
957                 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
958         else
959                 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
960
961         return 0;
962 }
963
964 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
965         assert_return(m, -EINVAL);
966         assert_return(!m->sealed, -EPERM);
967
968         if (b)
969                 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
970         else
971                 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
972
973         return 0;
974 }
975
976 static struct bus_container *message_get_container(sd_bus_message *m) {
977         assert(m);
978
979         if (m->n_containers == 0)
980                 return &m->root_container;
981
982         assert(m->containers);
983         return m->containers + m->n_containers - 1;
984 }
985
986 struct bus_body_part *message_append_part(sd_bus_message *m) {
987         struct bus_body_part *part;
988
989         assert(m);
990         assert_return(!m->poisoned, NULL);
991
992         if (m->n_body_parts <= 0) {
993                 part = &m->body;
994                 zero(*part);
995         } else {
996                 assert(m->body_end);
997
998                 part = new0(struct bus_body_part, 1);
999                 if (!part) {
1000                         m->poisoned = true;
1001                         return NULL;
1002                 }
1003
1004                 m->body_end->next = part;
1005         }
1006
1007         part->memfd = -1;
1008         m->body_end = part;
1009         m->n_body_parts ++;
1010
1011         return part;
1012 }
1013
1014 static void part_zero(struct bus_body_part *part, size_t sz) {
1015         assert(part);
1016         assert(sz > 0);
1017         assert(sz < 8);
1018
1019         /* All other fields can be left in their defaults */
1020         assert(!part->data);
1021         assert(part->memfd < 0);
1022
1023         part->size = sz;
1024         part->is_zero = true;
1025         part->sealed = true;
1026 }
1027
1028 static int part_make_space(
1029                 struct sd_bus_message *m,
1030                 struct bus_body_part *part,
1031                 size_t sz,
1032                 void **q) {
1033
1034         void *n;
1035         int r;
1036
1037         assert(m);
1038         assert(part);
1039         assert(!part->sealed);
1040
1041         if (m->poisoned)
1042                 return -ENOMEM;
1043
1044         if (!part->data && part->memfd < 0)
1045                 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1046
1047         if (part->memfd >= 0) {
1048                 uint64_t u = sz;
1049
1050                 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1051                 if (r < 0) {
1052                         m->poisoned = true;
1053                         return -errno;
1054                 }
1055
1056                 if (!part->data || sz > part->mapped) {
1057                         size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1058
1059                         if (part->mapped <= 0)
1060                                 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1061                         else
1062                                 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1063
1064                         if (n == MAP_FAILED) {
1065                                 m->poisoned = true;
1066                                 return -errno;
1067                         }
1068
1069                         part->mapped = psz;
1070                         part->data = n;
1071                 }
1072
1073                 part->munmap_this = true;
1074         } else {
1075                 n = realloc(part->data, MAX(sz, 1u));
1076                 if (!n) {
1077                         m->poisoned = true;
1078                         return -ENOMEM;
1079                 }
1080
1081                 part->data = n;
1082                 part->free_this = true;
1083         }
1084
1085         if (q)
1086                 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1087
1088         part->size = sz;
1089         return 0;
1090 }
1091
1092 static int message_add_offset(sd_bus_message *m, size_t offset) {
1093         struct bus_container *c;
1094
1095         assert(m);
1096         assert(BUS_MESSAGE_IS_GVARIANT(m));
1097
1098         /* Add offset to current container, unless this is the first
1099          * item in it, which will have the 0 offset, which we can
1100          * ignore. */
1101         c = message_get_container(m);
1102
1103         if (!c->need_offsets)
1104                 return 0;
1105
1106         if (!GREEDY_REALLOC(c->offsets, c->n_offsets_allocated, c->n_offsets + 1))
1107                 return -ENOMEM;
1108
1109         c->offsets[c->n_offsets++] = offset;
1110         return 0;
1111 }
1112
1113 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1114         struct bus_container *c;
1115
1116         assert(m);
1117
1118         if (expand <= 0)
1119                 return;
1120
1121         /* Update counters */
1122         for (c = m->containers; c < m->containers + m->n_containers; c++) {
1123
1124                 if (c->array_size)
1125                         *c->array_size += expand;
1126         }
1127 }
1128
1129 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1130         size_t start_body, end_body, padding, added;
1131         void *p;
1132         int r;
1133
1134         assert(m);
1135         assert(align > 0);
1136         assert(!m->sealed);
1137         assert_return(!m->poisoned, NULL);
1138
1139         start_body = ALIGN_TO((size_t) m->header->body_size, align);
1140         end_body = start_body + sz;
1141
1142         padding = start_body - m->header->body_size;
1143         added = padding + sz;
1144
1145         /* Check for 32bit overflows */
1146         if (end_body > (size_t) ((uint32_t) -1)) {
1147                 m->poisoned = true;
1148                 return NULL;
1149         }
1150
1151         if (added > 0) {
1152                 struct bus_body_part *part = NULL;
1153                 bool add_new_part;
1154
1155                 add_new_part =
1156                         m->n_body_parts <= 0 ||
1157                         m->body_end->sealed ||
1158                         padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1159
1160                 if (add_new_part) {
1161                         if (padding > 0) {
1162                                 part = message_append_part(m);
1163                                 if (!part)
1164                                         return NULL;
1165
1166                                 part_zero(part, padding);
1167                         }
1168
1169                         part = message_append_part(m);
1170                         if (!part)
1171                                 return NULL;
1172
1173                         r = part_make_space(m, part, sz, &p);
1174                         if (r < 0)
1175                                 return NULL;
1176                 } else {
1177                         struct bus_container *c;
1178                         void *op;
1179                         size_t os, start_part, end_part;
1180
1181                         part = m->body_end;
1182                         op = part->data;
1183                         os = part->size;
1184
1185                         start_part = ALIGN_TO(part->size, align);
1186                         end_part = start_part + sz;
1187
1188                         r = part_make_space(m, part, end_part, &p);
1189                         if (r < 0)
1190                                 return NULL;
1191
1192                         if (padding > 0) {
1193                                 memset(p, 0, padding);
1194                                 p = (uint8_t*) p + padding;
1195                         }
1196
1197                         /* Readjust pointers */
1198                         for (c = m->containers; c < m->containers + m->n_containers; c++)
1199                                 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1200
1201                         m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1202                 }
1203         } else
1204                 /* Return something that is not NULL and is aligned */
1205                 p = (uint8_t *) NULL + align;
1206
1207         m->header->body_size = end_body;
1208         message_extend_containers(m, added);
1209
1210         if (add_offset) {
1211                 r = message_add_offset(m, end_body);
1212                 if (r < 0) {
1213                         m->poisoned = true;
1214                         return NULL;
1215                 }
1216         }
1217
1218         return p;
1219 }
1220
1221 static int message_push_fd(sd_bus_message *m, int fd) {
1222         int *f, copy;
1223
1224         assert(m);
1225
1226         if (fd < 0)
1227                 return -EINVAL;
1228
1229         if (!m->allow_fds)
1230                 return -ENOTSUP;
1231
1232         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1233         if (copy < 0)
1234                 return -errno;
1235
1236         f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1237         if (!f) {
1238                 m->poisoned = true;
1239                 close_nointr_nofail(copy);
1240                 return -ENOMEM;
1241         }
1242
1243         m->fds = f;
1244         m->fds[m->n_fds] = copy;
1245         m->free_fds = true;
1246
1247         return copy;
1248 }
1249
1250 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1251         _cleanup_close_ int fd = -1;
1252         struct bus_container *c;
1253         ssize_t align, sz;
1254         void *a;
1255
1256         assert_return(m, -EINVAL);
1257         assert_return(!m->sealed, -EPERM);
1258         assert_return(bus_type_is_basic(type), -EINVAL);
1259         assert_return(!m->poisoned, -ESTALE);
1260
1261         c = message_get_container(m);
1262
1263         if (c->signature && c->signature[c->index]) {
1264                 /* Container signature is already set */
1265
1266                 if (c->signature[c->index] != type)
1267                         return -ENXIO;
1268         } else {
1269                 char *e;
1270
1271                 /* Maybe we can append to the signature? But only if this is the top-level container*/
1272                 if (c->enclosing != 0)
1273                         return -ENXIO;
1274
1275                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1276                 if (!e) {
1277                         m->poisoned = true;
1278                         return -ENOMEM;
1279                 }
1280         }
1281
1282         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1283                 uint8_t u8;
1284                 uint32_t u32;
1285
1286                 switch (type) {
1287
1288                 case SD_BUS_TYPE_SIGNATURE:
1289                 case SD_BUS_TYPE_STRING:
1290                         p = strempty(p);
1291
1292                         /* Fall through... */
1293                 case SD_BUS_TYPE_OBJECT_PATH:
1294                         if (!p)
1295                                 return -EINVAL;
1296
1297                         align = 1;
1298                         sz = strlen(p) + 1;
1299                         break;
1300
1301                 case SD_BUS_TYPE_BOOLEAN:
1302
1303                         u8 = p && *(int*) p;
1304                         p = &u8;
1305
1306                         align = sz = 1;
1307                         break;
1308
1309                 case SD_BUS_TYPE_UNIX_FD:
1310
1311                         if (!p)
1312                                 return -EINVAL;
1313
1314                         fd = message_push_fd(m, *(int*) p);
1315                         if (fd < 0)
1316                                 return fd;
1317
1318                         u32 = m->n_fds;
1319                         p = &u32;
1320
1321                         align = sz = 4;
1322                         break;
1323
1324                 default:
1325                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1326                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1327                         break;
1328                 }
1329
1330                 assert(align > 0);
1331                 assert(sz > 0);
1332
1333                 a = message_extend_body(m, align, sz, true);
1334                 if (!a)
1335                         return -ENOMEM;
1336
1337                 memcpy(a, p, sz);
1338
1339                 if (stored)
1340                         *stored = (const uint8_t*) a;
1341
1342         } else {
1343                 uint32_t u32;
1344
1345                 switch (type) {
1346
1347                 case SD_BUS_TYPE_STRING:
1348                         /* To make things easy we'll serialize a NULL string
1349                          * into the empty string */
1350                         p = strempty(p);
1351
1352                         /* Fall through... */
1353                 case SD_BUS_TYPE_OBJECT_PATH:
1354
1355                         if (!p)
1356                                 return -EINVAL;
1357
1358                         align = 4;
1359                         sz = 4 + strlen(p) + 1;
1360                         break;
1361
1362                 case SD_BUS_TYPE_SIGNATURE:
1363
1364                         p = strempty(p);
1365
1366                         align = 1;
1367                         sz = 1 + strlen(p) + 1;
1368                         break;
1369
1370                 case SD_BUS_TYPE_BOOLEAN:
1371
1372                         u32 = p && *(int*) p;
1373                         p = &u32;
1374
1375                         align = sz = 4;
1376                         break;
1377
1378                 case SD_BUS_TYPE_UNIX_FD:
1379
1380                         if (!p)
1381                                 return -EINVAL;
1382
1383                         fd = message_push_fd(m, *(int*) p);
1384                         if (fd < 0)
1385                                 return fd;
1386
1387                         u32 = m->n_fds;
1388                         p = &u32;
1389
1390                         align = sz = 4;
1391                         break;
1392
1393                 default:
1394                         align = bus_type_get_alignment(type);
1395                         sz = bus_type_get_size(type);
1396                         break;
1397                 }
1398
1399                 assert(align > 0);
1400                 assert(sz > 0);
1401
1402                 a = message_extend_body(m, align, sz, false);
1403                 if (!a)
1404                         return -ENOMEM;
1405
1406                 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1407                         *(uint32_t*) a = sz - 5;
1408                         memcpy((uint8_t*) a + 4, p, sz - 4);
1409
1410                         if (stored)
1411                                 *stored = (const uint8_t*) a + 4;
1412
1413                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1414                         *(uint8_t*) a = sz - 1;
1415                         memcpy((uint8_t*) a + 1, p, sz - 1);
1416
1417                         if (stored)
1418                                 *stored = (const uint8_t*) a + 1;
1419                 } else {
1420                         memcpy(a, p, sz);
1421
1422                         if (stored)
1423                                 *stored = a;
1424                 }
1425         }
1426
1427         if (type == SD_BUS_TYPE_UNIX_FD)
1428                 m->n_fds ++;
1429
1430         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1431                 c->index++;
1432
1433         fd = -1;
1434         return 0;
1435 }
1436
1437 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1438         return message_append_basic(m, type, p, NULL);
1439 }
1440
1441 _public_ int sd_bus_message_append_string_space(
1442                 sd_bus_message *m,
1443                 size_t size,
1444                 char **s) {
1445
1446         struct bus_container *c;
1447         void *a;
1448
1449         assert_return(m, -EINVAL);
1450         assert_return(s, -EINVAL);
1451         assert_return(!m->sealed, -EPERM);
1452         assert_return(!m->poisoned, -ESTALE);
1453
1454         c = message_get_container(m);
1455
1456         if (c->signature && c->signature[c->index]) {
1457                 /* Container signature is already set */
1458
1459                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1460                         return -ENXIO;
1461         } else {
1462                 char *e;
1463
1464                 /* Maybe we can append to the signature? But only if this is the top-level container*/
1465                 if (c->enclosing != 0)
1466                         return -ENXIO;
1467
1468                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1469                 if (!e) {
1470                         m->poisoned = true;
1471                         return -ENOMEM;
1472                 }
1473         }
1474
1475         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1476                 a = message_extend_body(m, 1, size + 1, true);
1477                 if (!a)
1478                         return -ENOMEM;
1479
1480                 *s = a;
1481         } else {
1482                 a = message_extend_body(m, 4, 4 + size + 1, false);
1483                 if (!a)
1484                         return -ENOMEM;
1485
1486                 *(uint32_t*) a = size;
1487                 *s = (char*) a + 4;
1488         }
1489
1490         (*s)[size] = 0;
1491
1492         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1493                 c->index++;
1494
1495         return 0;
1496 }
1497
1498 _public_ int sd_bus_message_append_string_iovec(
1499                 sd_bus_message *m,
1500                 const struct iovec *iov,
1501                 unsigned n) {
1502
1503         size_t size;
1504         unsigned i;
1505         char *p;
1506         int r;
1507
1508         assert_return(m, -EINVAL);
1509         assert_return(!m->sealed, -EPERM);
1510         assert_return(iov || n == 0, -EINVAL);
1511         assert_return(!m->poisoned, -ESTALE);
1512
1513         size = IOVEC_TOTAL_SIZE(iov, n);
1514
1515         r = sd_bus_message_append_string_space(m, size, &p);
1516         if (r < 0)
1517                 return r;
1518
1519         for (i = 0; i < n; i++) {
1520
1521                 if (iov[i].iov_base)
1522                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
1523                 else
1524                         memset(p, ' ', iov[i].iov_len);
1525
1526                 p += iov[i].iov_len;
1527         }
1528
1529         return 0;
1530 }
1531
1532 static int bus_message_open_array(
1533                 sd_bus_message *m,
1534                 struct bus_container *c,
1535                 const char *contents,
1536                 uint32_t **array_size,
1537                 size_t *begin,
1538                 bool *need_offsets) {
1539
1540         unsigned nindex;
1541         int alignment, r;
1542
1543         assert(m);
1544         assert(c);
1545         assert(contents);
1546         assert(array_size);
1547         assert(begin);
1548         assert(need_offsets);
1549
1550         if (!signature_is_single(contents, true))
1551                 return -EINVAL;
1552
1553         if (c->signature && c->signature[c->index]) {
1554
1555                 /* Verify the existing signature */
1556
1557                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1558                         return -ENXIO;
1559
1560                 if (!startswith(c->signature + c->index + 1, contents))
1561                         return -ENXIO;
1562
1563                 nindex = c->index + 1 + strlen(contents);
1564         } else {
1565                 char *e;
1566
1567                 if (c->enclosing != 0)
1568                         return -ENXIO;
1569
1570                 /* Extend the existing signature */
1571
1572                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1573                 if (!e) {
1574                         m->poisoned = true;
1575                         return -ENOMEM;
1576                 }
1577
1578                 nindex = e - c->signature;
1579         }
1580
1581         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1582                 alignment = bus_gvariant_get_alignment(contents);
1583                 if (alignment < 0)
1584                         return alignment;
1585
1586                 /* Add alignment padding and add to offset list */
1587                 if (!message_extend_body(m, alignment, 0, false))
1588                         return -ENOMEM;
1589
1590                 r = bus_gvariant_is_fixed_size(contents);
1591                 if (r < 0)
1592                         return r;
1593
1594                 *begin = m->header->body_size;
1595                 *need_offsets = r == 0;
1596         } else {
1597                 void *a, *op;
1598                 size_t os;
1599                 struct bus_body_part *o;
1600
1601                 alignment = bus_type_get_alignment(contents[0]);
1602                 if (alignment < 0)
1603                         return alignment;
1604
1605                 a = message_extend_body(m, 4, 4, false);
1606                 if (!a)
1607                         return -ENOMEM;
1608
1609                 o = m->body_end;
1610                 op = m->body_end->data;
1611                 os = m->body_end->size;
1612
1613                 /* Add alignment between size and first element */
1614                 if (!message_extend_body(m, alignment, 0, false))
1615                         return -ENOMEM;
1616
1617                 /* location of array size might have changed so let's readjust a */
1618                 if (o == m->body_end)
1619                         a = adjust_pointer(a, op, os, m->body_end->data);
1620
1621                 *(uint32_t*) a = 0;
1622                 *array_size = a;
1623         }
1624
1625         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1626                 c->index = nindex;
1627
1628         return 0;
1629 }
1630
1631 static int bus_message_open_variant(
1632                 sd_bus_message *m,
1633                 struct bus_container *c,
1634                 const char *contents) {
1635
1636         assert(m);
1637         assert(c);
1638         assert(contents);
1639
1640         if (!signature_is_single(contents, false))
1641                 return -EINVAL;
1642
1643         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1644                 return -EINVAL;
1645
1646         if (c->signature && c->signature[c->index]) {
1647
1648                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1649                         return -ENXIO;
1650
1651         } else {
1652                 char *e;
1653
1654                 if (c->enclosing != 0)
1655                         return -ENXIO;
1656
1657                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1658                 if (!e) {
1659                         m->poisoned = true;
1660                         return -ENOMEM;
1661                 }
1662         }
1663
1664         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1665                 /* Variants are always aligned to 8 */
1666
1667                 if (!message_extend_body(m, 8, 0, false))
1668                         return -ENOMEM;
1669
1670         } else {
1671                 size_t l;
1672                 void *a;
1673
1674                 l = strlen(contents);
1675                 a = message_extend_body(m, 1, 1 + l + 1, false);
1676                 if (!a)
1677                         return -ENOMEM;
1678
1679                 *(uint8_t*) a = l;
1680                 memcpy((uint8_t*) a + 1, contents, l + 1);
1681         }
1682
1683         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1684                 c->index++;
1685
1686         return 0;
1687 }
1688
1689 static int bus_message_open_struct(
1690                 sd_bus_message *m,
1691                 struct bus_container *c,
1692                 const char *contents,
1693                 size_t *begin,
1694                 bool *need_offsets) {
1695
1696         size_t nindex;
1697         int r;
1698
1699         assert(m);
1700         assert(c);
1701         assert(contents);
1702         assert(begin);
1703         assert(need_offsets);
1704
1705         if (!signature_is_valid(contents, false))
1706                 return -EINVAL;
1707
1708         if (c->signature && c->signature[c->index]) {
1709                 size_t l;
1710
1711                 l = strlen(contents);
1712
1713                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1714                     !startswith(c->signature + c->index + 1, contents) ||
1715                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1716                         return -ENXIO;
1717
1718                 nindex = c->index + 1 + l + 1;
1719         } else {
1720                 char *e;
1721
1722                 if (c->enclosing != 0)
1723                         return -ENXIO;
1724
1725                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1726                 if (!e) {
1727                         m->poisoned = true;
1728                         return -ENOMEM;
1729                 }
1730
1731                 nindex = e - c->signature;
1732         }
1733
1734         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1735                 int alignment;
1736
1737                 alignment = bus_gvariant_get_alignment(contents);
1738                 if (alignment < 0)
1739                         return alignment;
1740
1741                 if (!message_extend_body(m, alignment, 0, false))
1742                         return -ENOMEM;
1743
1744                 r = bus_gvariant_is_fixed_size(contents);
1745                 if (r < 0)
1746                         return r;
1747
1748                 *begin = m->header->body_size;
1749                 *need_offsets = r == 0;
1750         } else {
1751                 /* Align contents to 8 byte boundary */
1752                 if (!message_extend_body(m, 8, 0, false))
1753                         return -ENOMEM;
1754         }
1755
1756         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1757                 c->index = nindex;
1758
1759         return 0;
1760 }
1761
1762 static int bus_message_open_dict_entry(
1763                 sd_bus_message *m,
1764                 struct bus_container *c,
1765                 const char *contents,
1766                 size_t *begin,
1767                 bool *need_offsets) {
1768
1769         int r;
1770
1771         assert(m);
1772         assert(c);
1773         assert(contents);
1774         assert(begin);
1775         assert(need_offsets);
1776
1777         if (!signature_is_pair(contents))
1778                 return -EINVAL;
1779
1780         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1781                 return -ENXIO;
1782
1783         if (c->signature && c->signature[c->index]) {
1784                 size_t l;
1785
1786                 l = strlen(contents);
1787
1788                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1789                     !startswith(c->signature + c->index + 1, contents) ||
1790                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1791                         return -ENXIO;
1792         } else
1793                 return -ENXIO;
1794
1795         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1796                 int alignment;
1797
1798                 alignment = bus_gvariant_get_alignment(contents);
1799                 if (alignment < 0)
1800                         return alignment;
1801
1802                 if (!message_extend_body(m, alignment, 0, false))
1803                         return -ENOMEM;
1804
1805                 r = bus_gvariant_is_fixed_size(contents);
1806                 if (r < 0)
1807                         return r;
1808
1809                 *begin = m->header->body_size;
1810                 *need_offsets = r == 0;
1811         } else {
1812                 /* Align contents to 8 byte boundary */
1813                 if (!message_extend_body(m, 8, 0, false))
1814                         return -ENOMEM;
1815         }
1816
1817         return 0;
1818 }
1819
1820 _public_ int sd_bus_message_open_container(
1821                 sd_bus_message *m,
1822                 char type,
1823                 const char *contents) {
1824
1825         struct bus_container *c, *w;
1826         uint32_t *array_size = NULL;
1827         char *signature;
1828         size_t before, begin;
1829         bool need_offsets = false;
1830         int r;
1831
1832         assert_return(m, -EINVAL);
1833         assert_return(!m->sealed, -EPERM);
1834         assert_return(contents, -EINVAL);
1835         assert_return(!m->poisoned, -ESTALE);
1836
1837         /* Make sure we have space for one more container */
1838         w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1839         if (!w) {
1840                 m->poisoned = true;
1841                 return -ENOMEM;
1842         }
1843
1844         m->containers = w;
1845
1846         c = message_get_container(m);
1847
1848         signature = strdup(contents);
1849         if (!signature) {
1850                 m->poisoned = true;
1851                 return -ENOMEM;
1852         }
1853
1854         /* Save old index in the parent container, in case we have to
1855          * abort this container */
1856         c->saved_index = c->index;
1857         before = m->header->body_size;
1858
1859         if (type == SD_BUS_TYPE_ARRAY)
1860                 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1861         else if (type == SD_BUS_TYPE_VARIANT)
1862                 r = bus_message_open_variant(m, c, contents);
1863         else if (type == SD_BUS_TYPE_STRUCT)
1864                 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1865         else if (type == SD_BUS_TYPE_DICT_ENTRY)
1866                 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1867         else
1868                 r = -EINVAL;
1869
1870         if (r < 0) {
1871                 free(signature);
1872                 return r;
1873         }
1874
1875         /* OK, let's fill it in */
1876         w += m->n_containers++;
1877         w->enclosing = type;
1878         w->signature = signature;
1879         w->index = 0;
1880         w->array_size = array_size;
1881         w->before = before;
1882         w->begin = begin;
1883         w->n_offsets = w->n_offsets_allocated = 0;
1884         w->offsets = NULL;
1885         w->need_offsets = need_offsets;
1886
1887         return 0;
1888 }
1889
1890 static size_t determine_word_size(size_t sz, size_t extra) {
1891         if (sz + extra <= 0xFF)
1892                 return 1;
1893         else if (sz + extra*2 <= 0xFFFF)
1894                 return 2;
1895         else if (sz + extra*4 <= 0xFFFFFFFF)
1896                 return 4;
1897         else
1898                 return 8;
1899 }
1900
1901 static size_t read_word_le(void *p, size_t sz) {
1902         union {
1903                 uint16_t u16;
1904                 uint32_t u32;
1905                 uint64_t u64;
1906         } x;
1907
1908         assert(p);
1909
1910         if (sz == 1)
1911                 return *(uint8_t*) p;
1912
1913         memcpy(&x, p, sz);
1914
1915         if (sz == 2)
1916                 return le16toh(x.u16);
1917         else if (sz == 4)
1918                 return le32toh(x.u32);
1919         else if (sz == 4)
1920                 return le64toh(x.u64);
1921
1922         assert_not_reached("unknown word width");
1923 }
1924
1925 static void write_word_le(void *p, size_t sz, size_t value) {
1926         union {
1927                 uint16_t u16;
1928                 uint32_t u32;
1929                 uint64_t u64;
1930         } x;
1931
1932         assert(p);
1933         assert(sz == 8 || (value < (1ULL << (sz*8))));
1934
1935         if (sz == 1) {
1936                 *(uint8_t*) p = value;
1937                 return;
1938         } else if (sz == 2)
1939                 x.u16 = htole16((uint16_t) value);
1940         else if (sz == 4)
1941                 x.u32 = htole32((uint32_t) value);
1942         else if (sz == 8)
1943                 x.u64 = htole64((uint64_t) value);
1944         else
1945                 assert_not_reached("unknown word width");
1946
1947         memcpy(p, &x, sz);
1948 }
1949
1950 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1951
1952         assert(m);
1953         assert(c);
1954
1955         if (!BUS_MESSAGE_IS_GVARIANT(m))
1956                 return 0;
1957
1958         if (c->need_offsets) {
1959                 size_t payload, sz, i;
1960                 uint8_t *a;
1961
1962                 /* Variable-width arrays */
1963
1964                 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1965                 sz = determine_word_size(payload, c->n_offsets);
1966
1967                 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1968                 if (!a)
1969                         return -ENOMEM;
1970
1971                 for (i = 0; i < c->n_offsets; i++)
1972                         write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1973         } else {
1974                 void *a;
1975
1976                 /* Fixed-width or empty arrays */
1977
1978                 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1979                 if (!a)
1980                         return -ENOMEM;
1981         }
1982
1983         return 0;
1984 }
1985
1986 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
1987         uint8_t *a;
1988         size_t l;
1989
1990         assert(m);
1991         assert(c);
1992
1993         if (!BUS_MESSAGE_IS_GVARIANT(m))
1994                 return 0;
1995
1996         l = strlen(c->signature);
1997
1998         a = message_extend_body(m, 1, 1 + l, true);
1999         if (!a)
2000                 return -ENOMEM;
2001
2002         a[0] = 0;
2003         memcpy(a+1, c->signature, l);
2004
2005         return 0;
2006 }
2007
2008 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2009         size_t n_variable = 0;
2010         unsigned i = 0;
2011         const char *p;
2012         uint8_t *a;
2013         int r;
2014
2015         assert(m);
2016         assert(c);
2017
2018         if (!BUS_MESSAGE_IS_GVARIANT(m))
2019                 return 0;
2020
2021         p = strempty(c->signature);
2022         while (*p != 0) {
2023                 size_t n;
2024
2025                 r = signature_element_length(p, &n);
2026                 if (r < 0)
2027                         return r;
2028                 else {
2029                         char t[n+1];
2030
2031                         memcpy(t, p, n);
2032                         t[n] = 0;
2033
2034                         r = bus_gvariant_is_fixed_size(t);
2035                         if (r < 0)
2036                                 return r;
2037                 }
2038
2039                 assert(i <= c->n_offsets);
2040
2041                 /* We need to add an offset for each item that has a
2042                  * variable size and that is not the last one in the
2043                  * list */
2044                 if (r == 0 && p[n] != 0)
2045                         n_variable++;
2046
2047                 i++;
2048                 p += n;
2049         }
2050
2051         assert(i == c->n_offsets);
2052
2053         if (n_variable <= 0) {
2054                 a = message_extend_body(m, 1, 0, add_offset);
2055                 if (!a)
2056                         return -ENOMEM;
2057         } else {
2058                 size_t sz;
2059                 unsigned j;
2060
2061                 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2062
2063                 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2064
2065                 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2066                 if (!a)
2067                         return -ENOMEM;
2068
2069                 p = strempty(c->signature);
2070                 for (i = 0, j = 0; i < c->n_offsets; i++) {
2071                         unsigned k;
2072                         size_t n;
2073
2074                         r = signature_element_length(p, &n);
2075                         if (r < 0)
2076                                 return r;
2077                         else {
2078                                 char t[n+1];
2079
2080                                 memcpy(t, p, n);
2081                                 t[n] = 0;
2082
2083                                 p += n;
2084
2085                                 r = bus_gvariant_is_fixed_size(t);
2086                                 if (r < 0)
2087                                         return r;
2088                                 if (r > 0 || p[0] == 0)
2089                                         continue;
2090                         }
2091
2092                         k = n_variable - 1 - j;
2093
2094                         write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2095
2096                         j++;
2097                 }
2098         }
2099
2100         return 0;
2101 }
2102
2103 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2104         struct bus_container *c;
2105         int r;
2106
2107         assert_return(m, -EINVAL);
2108         assert_return(!m->sealed, -EPERM);
2109         assert_return(m->n_containers > 0, -EINVAL);
2110         assert_return(!m->poisoned, -ESTALE);
2111
2112         c = message_get_container(m);
2113
2114         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2115                 if (c->signature && c->signature[c->index] != 0)
2116                         return -EINVAL;
2117
2118         m->n_containers--;
2119
2120         if (c->enclosing == SD_BUS_TYPE_ARRAY)
2121                 r = bus_message_close_array(m, c);
2122         else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2123                 r = bus_message_close_variant(m, c);
2124         else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2125                 r = bus_message_close_struct(m, c, true);
2126         else
2127                 assert_not_reached("Unknown container type");
2128
2129         free(c->signature);
2130         free(c->offsets);
2131
2132         return r;
2133 }
2134
2135 typedef struct {
2136         const char *types;
2137         unsigned n_struct;
2138         unsigned n_array;
2139 } TypeStack;
2140
2141 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2142         assert(stack);
2143         assert(max > 0);
2144
2145         if (*i >= max)
2146                 return -EINVAL;
2147
2148         stack[*i].types = types;
2149         stack[*i].n_struct = n_struct;
2150         stack[*i].n_array = n_array;
2151         (*i)++;
2152
2153         return 0;
2154 }
2155
2156 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2157         assert(stack);
2158         assert(max > 0);
2159         assert(types);
2160         assert(n_struct);
2161         assert(n_array);
2162
2163         if (*i <= 0)
2164                 return 0;
2165
2166         (*i)--;
2167         *types = stack[*i].types;
2168         *n_struct = stack[*i].n_struct;
2169         *n_array = stack[*i].n_array;
2170
2171         return 1;
2172 }
2173
2174 int bus_message_append_ap(
2175                 sd_bus_message *m,
2176                 const char *types,
2177                 va_list ap) {
2178
2179         unsigned n_array, n_struct;
2180         TypeStack stack[BUS_CONTAINER_DEPTH];
2181         unsigned stack_ptr = 0;
2182         int r;
2183
2184         assert(m);
2185
2186         if (!types)
2187                 return 0;
2188
2189         n_array = (unsigned) -1;
2190         n_struct = strlen(types);
2191
2192         for (;;) {
2193                 const char *t;
2194
2195                 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2196                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2197                         if (r < 0)
2198                                 return r;
2199                         if (r == 0)
2200                                 break;
2201
2202                         r = sd_bus_message_close_container(m);
2203                         if (r < 0)
2204                                 return r;
2205
2206                         continue;
2207                 }
2208
2209                 t = types;
2210                 if (n_array != (unsigned) -1)
2211                         n_array --;
2212                 else {
2213                         types ++;
2214                         n_struct--;
2215                 }
2216
2217                 switch (*t) {
2218
2219                 case SD_BUS_TYPE_BYTE: {
2220                         uint8_t x;
2221
2222                         x = (uint8_t) va_arg(ap, int);
2223                         r = sd_bus_message_append_basic(m, *t, &x);
2224                         break;
2225                 }
2226
2227                 case SD_BUS_TYPE_BOOLEAN:
2228                 case SD_BUS_TYPE_INT32:
2229                 case SD_BUS_TYPE_UINT32:
2230                 case SD_BUS_TYPE_UNIX_FD: {
2231                         uint32_t x;
2232
2233                         /* We assume a boolean is the same as int32_t */
2234                         assert_cc(sizeof(int32_t) == sizeof(int));
2235
2236                         x = va_arg(ap, uint32_t);
2237                         r = sd_bus_message_append_basic(m, *t, &x);
2238                         break;
2239                 }
2240
2241                 case SD_BUS_TYPE_INT16:
2242                 case SD_BUS_TYPE_UINT16: {
2243                         uint16_t x;
2244
2245                         x = (uint16_t) va_arg(ap, int);
2246                         r = sd_bus_message_append_basic(m, *t, &x);
2247                         break;
2248                 }
2249
2250                 case SD_BUS_TYPE_INT64:
2251                 case SD_BUS_TYPE_UINT64:
2252                 case SD_BUS_TYPE_DOUBLE: {
2253                         uint64_t x;
2254
2255                         x = va_arg(ap, uint64_t);
2256                         r = sd_bus_message_append_basic(m, *t, &x);
2257                         break;
2258                 }
2259
2260                 case SD_BUS_TYPE_STRING:
2261                 case SD_BUS_TYPE_OBJECT_PATH:
2262                 case SD_BUS_TYPE_SIGNATURE: {
2263                         const char *x;
2264
2265                         x = va_arg(ap, const char*);
2266                         r = sd_bus_message_append_basic(m, *t, x);
2267                         break;
2268                 }
2269
2270                 case SD_BUS_TYPE_ARRAY: {
2271                         size_t k;
2272
2273                         r = signature_element_length(t + 1, &k);
2274                         if (r < 0)
2275                                 return r;
2276
2277                         {
2278                                 char s[k + 1];
2279                                 memcpy(s, t + 1, k);
2280                                 s[k] = 0;
2281
2282                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2283                                 if (r < 0)
2284                                         return r;
2285                         }
2286
2287                         if (n_array == (unsigned) -1) {
2288                                 types += k;
2289                                 n_struct -= k;
2290                         }
2291
2292                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2293                         if (r < 0)
2294                                 return r;
2295
2296                         types = t + 1;
2297                         n_struct = k;
2298                         n_array = va_arg(ap, unsigned);
2299
2300                         break;
2301                 }
2302
2303                 case SD_BUS_TYPE_VARIANT: {
2304                         const char *s;
2305
2306                         s = va_arg(ap, const char*);
2307                         if (!s)
2308                                 return -EINVAL;
2309
2310                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2311                         if (r < 0)
2312                                 return r;
2313
2314                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2315                         if (r < 0)
2316                                 return r;
2317
2318                         types = s;
2319                         n_struct = strlen(s);
2320                         n_array = (unsigned) -1;
2321
2322                         break;
2323                 }
2324
2325                 case SD_BUS_TYPE_STRUCT_BEGIN:
2326                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2327                         size_t k;
2328
2329                         r = signature_element_length(t, &k);
2330                         if (r < 0)
2331                                 return r;
2332
2333                         {
2334                                 char s[k - 1];
2335
2336                                 memcpy(s, t + 1, k - 2);
2337                                 s[k - 2] = 0;
2338
2339                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2340                                 if (r < 0)
2341                                         return r;
2342                         }
2343
2344                         if (n_array == (unsigned) -1) {
2345                                 types += k - 1;
2346                                 n_struct -= k - 1;
2347                         }
2348
2349                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2350                         if (r < 0)
2351                                 return r;
2352
2353                         types = t + 1;
2354                         n_struct = k - 2;
2355                         n_array = (unsigned) -1;
2356
2357                         break;
2358                 }
2359
2360                 default:
2361                         r = -EINVAL;
2362                 }
2363
2364                 if (r < 0)
2365                         return r;
2366         }
2367
2368         return 1;
2369 }
2370
2371 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2372         va_list ap;
2373         int r;
2374
2375         assert_return(m, -EINVAL);
2376         assert_return(types, -EINVAL);
2377         assert_return(!m->sealed, -EPERM);
2378         assert_return(!m->poisoned, -ESTALE);
2379
2380         va_start(ap, types);
2381         r = bus_message_append_ap(m, types, ap);
2382         va_end(ap);
2383
2384         return r;
2385 }
2386
2387 _public_ int sd_bus_message_append_array_space(
2388                 sd_bus_message *m,
2389                 char type,
2390                 size_t size,
2391                 void **ptr) {
2392
2393         ssize_t align, sz;
2394         void *a;
2395         int r;
2396
2397         assert_return(m, -EINVAL);
2398         assert_return(!m->sealed, -EPERM);
2399         assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2400         assert_return(ptr || size == 0, -EINVAL);
2401         assert_return(!m->poisoned, -ESTALE);
2402
2403         /* alignment and size of the trivial types (except bool) is
2404          * identical for gvariant and dbus1 marshalling */
2405         align = bus_type_get_alignment(type);
2406         sz = bus_type_get_size(type);
2407
2408         assert_se(align > 0);
2409         assert_se(sz > 0);
2410
2411         if (size % sz != 0)
2412                 return -EINVAL;
2413
2414         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2415         if (r < 0)
2416                 return r;
2417
2418         a = message_extend_body(m, align, size, false);
2419         if (!a)
2420                 return -ENOMEM;
2421
2422         r = sd_bus_message_close_container(m);
2423         if (r < 0)
2424                 return r;
2425
2426         *ptr = a;
2427         return 0;
2428 }
2429
2430 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2431                                          char type,
2432                                          const void *ptr,
2433                                          size_t size) {
2434         int r;
2435         void *p;
2436
2437         assert_return(m, -EINVAL);
2438         assert_return(!m->sealed, -EPERM);
2439         assert_return(bus_type_is_trivial(type), -EINVAL);
2440         assert_return(ptr || size == 0, -EINVAL);
2441         assert_return(!m->poisoned, -ESTALE);
2442
2443         r = sd_bus_message_append_array_space(m, type, size, &p);
2444         if (r < 0)
2445                 return r;
2446
2447         if (size > 0)
2448                 memcpy(p, ptr, size);
2449
2450         return 0;
2451 }
2452
2453 _public_ int sd_bus_message_append_array_iovec(
2454                 sd_bus_message *m,
2455                 char type,
2456                 const struct iovec *iov,
2457                 unsigned n) {
2458
2459         size_t size;
2460         unsigned i;
2461         void *p;
2462         int r;
2463
2464         assert_return(m, -EINVAL);
2465         assert_return(!m->sealed, -EPERM);
2466         assert_return(bus_type_is_trivial(type), -EINVAL);
2467         assert_return(iov || n == 0, -EINVAL);
2468         assert_return(!m->poisoned, -ESTALE);
2469
2470         size = IOVEC_TOTAL_SIZE(iov, n);
2471
2472         r = sd_bus_message_append_array_space(m, type, size, &p);
2473         if (r < 0)
2474                 return r;
2475
2476         for (i = 0; i < n; i++) {
2477
2478                 if (iov[i].iov_base)
2479                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
2480                 else
2481                         memset(p, 0, iov[i].iov_len);
2482
2483                 p = (uint8_t*) p + iov[i].iov_len;
2484         }
2485
2486         return 0;
2487 }
2488
2489 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2490                                                char type,
2491                                                sd_memfd *memfd) {
2492         _cleanup_close_ int copy_fd = -1;
2493         struct bus_body_part *part;
2494         ssize_t align, sz;
2495         uint64_t size;
2496         void *a;
2497         int r;
2498
2499         if (!m)
2500                 return -EINVAL;
2501         if (!memfd)
2502                 return -EINVAL;
2503         if (m->sealed)
2504                 return -EPERM;
2505         if (!bus_type_is_trivial(type))
2506                 return -EINVAL;
2507         if (m->poisoned)
2508                 return -ESTALE;
2509
2510         r = sd_memfd_set_sealed(memfd, true);
2511         if (r < 0)
2512                 return r;
2513
2514         copy_fd = sd_memfd_dup_fd(memfd);
2515         if (copy_fd < 0)
2516                 return copy_fd;
2517
2518         r = sd_memfd_get_size(memfd, &size);
2519         if (r < 0)
2520                 return r;
2521
2522         align = bus_type_get_alignment(type);
2523         sz = bus_type_get_size(type);
2524
2525         assert_se(align > 0);
2526         assert_se(sz > 0);
2527
2528         if (size % sz != 0)
2529                 return -EINVAL;
2530
2531         if (size > (uint64_t) (uint32_t) -1)
2532                 return -EINVAL;
2533
2534         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2535         if (r < 0)
2536                 return r;
2537
2538         a = message_extend_body(m, align, 0, false);
2539         if (!a)
2540                 return -ENOMEM;
2541
2542         part = message_append_part(m);
2543         if (!part)
2544                 return -ENOMEM;
2545
2546         part->memfd = copy_fd;
2547         part->sealed = true;
2548         part->size = size;
2549         copy_fd = -1;
2550
2551         m->header->body_size += size;
2552         message_extend_containers(m, size);
2553
2554         return sd_bus_message_close_container(m);
2555 }
2556
2557 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2558         _cleanup_close_ int copy_fd = -1;
2559         struct bus_body_part *part;
2560         struct bus_container *c;
2561         uint64_t size;
2562         void *a;
2563         int r;
2564
2565         assert_return(m, -EINVAL);
2566         assert_return(memfd, -EINVAL);
2567         assert_return(!m->sealed, -EPERM);
2568         assert_return(!m->poisoned, -ESTALE);
2569
2570         r = sd_memfd_set_sealed(memfd, true);
2571         if (r < 0)
2572                 return r;
2573
2574         copy_fd = sd_memfd_dup_fd(memfd);
2575         if (copy_fd < 0)
2576                 return copy_fd;
2577
2578         r = sd_memfd_get_size(memfd, &size);
2579         if (r < 0)
2580                 return r;
2581
2582         /* We require this to be NUL terminated */
2583         if (size == 0)
2584                 return -EINVAL;
2585
2586         if (size > (uint64_t) (uint32_t) -1)
2587                 return -EINVAL;
2588
2589         c = message_get_container(m);
2590         if (c->signature && c->signature[c->index]) {
2591                 /* Container signature is already set */
2592
2593                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2594                         return -ENXIO;
2595         } else {
2596                 char *e;
2597
2598                 /* Maybe we can append to the signature? But only if this is the top-level container*/
2599                 if (c->enclosing != 0)
2600                         return -ENXIO;
2601
2602                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2603                 if (!e) {
2604                         m->poisoned = true;
2605                         return -ENOMEM;
2606                 }
2607         }
2608
2609         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2610                 a = message_extend_body(m, 4, 4, false);
2611                 if (!a)
2612                         return -ENOMEM;
2613
2614                 *(uint32_t*) a = size - 1;
2615         }
2616
2617         part = message_append_part(m);
2618         if (!part)
2619                 return -ENOMEM;
2620
2621         part->memfd = copy_fd;
2622         part->sealed = true;
2623         part->size = size;
2624         copy_fd = -1;
2625
2626         m->header->body_size += size;
2627         message_extend_containers(m, size);
2628
2629         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2630                 r = message_add_offset(m, m->header->body_size);
2631                 if (r < 0) {
2632                         m->poisoned = true;
2633                         return -ENOMEM;
2634                 }
2635         }
2636
2637         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2638                 c->index++;
2639
2640         return 0;
2641 }
2642
2643 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2644         char **i;
2645         int r;
2646
2647         assert_return(m, -EINVAL);
2648         assert_return(!m->sealed, -EPERM);
2649         assert_return(!m->poisoned, -ESTALE);
2650
2651         r = sd_bus_message_open_container(m, 'a', "s");
2652         if (r < 0)
2653                 return r;
2654
2655         STRV_FOREACH(i, l) {
2656                 r = sd_bus_message_append_basic(m, 's', *i);
2657                 if (r < 0)
2658                         return r;
2659         }
2660
2661         return sd_bus_message_close_container(m);
2662 }
2663
2664 static int bus_message_close_header(sd_bus_message *m) {
2665         uint8_t *a;
2666         size_t sz, i;
2667
2668         assert(m);
2669
2670         if (!BUS_MESSAGE_IS_GVARIANT(m))
2671                 return 0;
2672
2673         if (m->n_header_offsets < 1)
2674                 return 0;
2675
2676         assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2677
2678         sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2679
2680         a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2681         if (!a)
2682                 return -ENOMEM;
2683
2684         for (i = 0; i < m->n_header_offsets; i++)
2685                 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2686
2687         return 0;
2688 }
2689
2690 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2691         struct bus_body_part *part;
2692         size_t l, a;
2693         unsigned i;
2694         int r;
2695
2696         assert(m);
2697
2698         if (m->sealed)
2699                 return -EPERM;
2700
2701         if (m->n_containers > 0)
2702                 return -EBADMSG;
2703
2704         if (m->poisoned)
2705                 return -ESTALE;
2706
2707         /* In vtables the return signature of method calls is listed,
2708          * let's check if they match if this is a response */
2709         if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2710             m->enforced_reply_signature &&
2711             !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2712                 return -ENOMSG;
2713
2714         /* If gvariant marshalling is used we need to close the body structure */
2715         r = bus_message_close_struct(m, &m->root_container, false);
2716         if (r < 0)
2717                 return r;
2718
2719         /* If there's a non-trivial signature set, then add it in here */
2720         if (!isempty(m->root_container.signature)) {
2721                 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2722                 if (r < 0)
2723                         return r;
2724         }
2725
2726         if (m->n_fds > 0) {
2727                 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2728                 if (r < 0)
2729                         return r;
2730         }
2731
2732         r = bus_message_close_header(m);
2733         if (r < 0)
2734                 return r;
2735
2736         m->header->serial = serial;
2737
2738         /* Add padding at the end of the fields part, since we know
2739          * the body needs to start at an 8 byte alignment. We made
2740          * sure we allocated enough space for this, so all we need to
2741          * do here is to zero it out. */
2742         l = BUS_MESSAGE_FIELDS_SIZE(m);
2743         a = ALIGN8(l) - l;
2744         if (a > 0)
2745                 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2746
2747         /* If this is something we can send as memfd, then let's seal
2748         the memfd now. Note that we can send memfds as payload only
2749         for directed messages, and not for broadcasts. */
2750         if (m->destination && m->bus && m->bus->use_memfd) {
2751                 MESSAGE_FOREACH_PART(part, i, m)
2752                         if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2753                                 bus_body_part_unmap(part);
2754
2755                                 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2756                                         part->sealed = true;
2757                         }
2758         }
2759
2760         m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2761         m->root_container.index = 0;
2762         m->root_container.offset_index = 0;
2763         m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2764
2765         m->sealed = true;
2766
2767         return 0;
2768 }
2769
2770 int bus_body_part_map(struct bus_body_part *part) {
2771         void *p;
2772         size_t psz;
2773
2774         assert_se(part);
2775
2776         if (part->data)
2777                 return 0;
2778
2779         if (part->size <= 0)
2780                 return 0;
2781
2782         /* For smaller zero parts (as used for padding) we don't need to map anything... */
2783         if (part->memfd < 0 && part->is_zero && part->size < 8) {
2784                 static const uint8_t zeroes[7] = { };
2785                 part->data = (void*) zeroes;
2786                 return 0;
2787         }
2788
2789         psz = PAGE_ALIGN(part->size);
2790
2791         if (part->memfd >= 0)
2792                 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2793         else if (part->is_zero)
2794                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2795         else
2796                 return -EINVAL;
2797
2798         if (p == MAP_FAILED)
2799                 return -errno;
2800
2801         part->mapped = psz;
2802         part->data = p;
2803         part->munmap_this = true;
2804
2805         return 0;
2806 }
2807
2808 void bus_body_part_unmap(struct bus_body_part *part) {
2809
2810         assert_se(part);
2811
2812         if (part->memfd < 0)
2813                 return;
2814
2815         if (!part->data)
2816                 return;
2817
2818         if (!part->munmap_this)
2819                 return;
2820
2821         assert_se(munmap(part->data, part->mapped) == 0);
2822
2823         part->data = NULL;
2824         part->mapped = 0;
2825         part->munmap_this = false;
2826
2827         return;
2828 }
2829
2830 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2831         size_t k, start, end;
2832
2833         assert(rindex);
2834         assert(align > 0);
2835
2836         start = ALIGN_TO((size_t) *rindex, align);
2837         end = start + nbytes;
2838
2839         if (end > sz)
2840                 return -EBADMSG;
2841
2842         /* Verify that padding is 0 */
2843         for (k = *rindex; k < start; k++)
2844                 if (((const uint8_t*) p)[k] != 0)
2845                         return -EBADMSG;
2846
2847         if (r)
2848                 *r = (uint8_t*) p + start;
2849
2850         *rindex = end;
2851
2852         return 1;
2853 }
2854
2855 static bool message_end_of_signature(sd_bus_message *m) {
2856         struct bus_container *c;
2857
2858         assert(m);
2859
2860         c = message_get_container(m);
2861         return !c->signature || c->signature[c->index] == 0;
2862 }
2863
2864 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2865         struct bus_container *c;
2866
2867         assert(m);
2868
2869         c = message_get_container(m);
2870         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2871                 return false;
2872
2873         if (BUS_MESSAGE_IS_GVARIANT(m))
2874                 return index >= c->end;
2875         else {
2876                 assert(c->array_size);
2877                 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2878         }
2879 }
2880
2881 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2882         assert_return(m, -EINVAL);
2883         assert_return(m->sealed, -EPERM);
2884
2885         if (complete && m->n_containers > 0)
2886                 return false;
2887
2888         if (message_end_of_signature(m))
2889                 return true;
2890
2891         if (message_end_of_array(m, m->rindex))
2892                 return true;
2893
2894         return false;
2895 }
2896
2897 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2898         struct bus_body_part *part;
2899         size_t begin;
2900         int r;
2901
2902         assert(m);
2903
2904         if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2905                 part = m->cached_rindex_part;
2906                 begin = m->cached_rindex_part_begin;
2907         } else {
2908                 part = &m->body;
2909                 begin = 0;
2910         }
2911
2912         while (part) {
2913                 if (index < begin)
2914                         return NULL;
2915
2916                 if (index + sz <= begin + part->size) {
2917
2918                         r = bus_body_part_map(part);
2919                         if (r < 0)
2920                                 return NULL;
2921
2922                         if (p)
2923                                 *p = (uint8_t*) part->data + index - begin;
2924
2925                         m->cached_rindex_part = part;
2926                         m->cached_rindex_part_begin = begin;
2927
2928                         return part;
2929                 }
2930
2931                 begin += part->size;
2932                 part = part->next;
2933         }
2934
2935         return NULL;
2936 }
2937
2938 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2939         int r;
2940
2941         assert(m);
2942         assert(c);
2943         assert(rindex);
2944
2945         if (!BUS_MESSAGE_IS_GVARIANT(m))
2946                 return 0;
2947
2948         if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2949                 int sz;
2950
2951                 sz = bus_gvariant_get_size(c->signature);
2952                 if (sz < 0) {
2953                         int alignment;
2954
2955                         if (c->offset_index+1 >= c->n_offsets)
2956                                 goto end;
2957
2958                         /* Variable-size array */
2959
2960                         alignment = bus_gvariant_get_alignment(c->signature);
2961                         assert(alignment > 0);
2962
2963                         *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2964                         c->item_size = c->offsets[c->offset_index+1] - *rindex;
2965                 } else {
2966
2967                         if (c->offset_index+1 >= (c->end-c->begin)/sz)
2968                                 goto end;
2969
2970                         /* Fixed-size array */
2971                         *rindex = c->begin + (c->offset_index+1) * sz;
2972                         c->item_size = sz;
2973                 }
2974
2975                 c->offset_index++;
2976
2977         } else if (c->enclosing == 0 ||
2978                    c->enclosing == SD_BUS_TYPE_STRUCT ||
2979                    c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2980
2981                 int alignment;
2982                 size_t n, j;
2983
2984                 if (c->offset_index+1 >= c->n_offsets)
2985                         goto end;
2986
2987                 r = signature_element_length(c->signature + c->index, &n);
2988                 if (r < 0)
2989                         return r;
2990
2991                 r = signature_element_length(c->signature + c->index + n, &j);
2992                 if (r < 0)
2993                         return r;
2994                 else {
2995                         char t[j+1];
2996                         memcpy(t, c->signature + c->index + n, j);
2997                         t[j] = 0;
2998
2999                         alignment = bus_gvariant_get_alignment(t);
3000                 }
3001
3002                 assert(alignment > 0);
3003
3004                 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3005                 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3006
3007                 c->offset_index++;
3008
3009         } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3010                 goto end;
3011         else
3012                 assert_not_reached("Unknown container type");
3013
3014         return 0;
3015
3016 end:
3017         /* Reached the end */
3018         *rindex = c->end;
3019         c->item_size = 0;
3020         return 0;
3021 }
3022
3023
3024 static int message_peek_body(
3025                 sd_bus_message *m,
3026                 size_t *rindex,
3027                 size_t align,
3028                 size_t nbytes,
3029                 void **ret) {
3030
3031         size_t k, start, end, padding;
3032         struct bus_body_part *part;
3033         uint8_t *q;
3034
3035         assert(m);
3036         assert(rindex);
3037         assert(align > 0);
3038
3039         start = ALIGN_TO((size_t) *rindex, align);
3040         padding = start - *rindex;
3041         end = start + nbytes;
3042
3043         if (end > BUS_MESSAGE_BODY_SIZE(m))
3044                 return -EBADMSG;
3045
3046         part = find_part(m, *rindex, padding, (void**) &q);
3047         if (!part)
3048                 return -EBADMSG;
3049
3050         if (q) {
3051                 /* Verify padding */
3052                 for (k = 0; k < padding; k++)
3053                         if (q[k] != 0)
3054                                 return -EBADMSG;
3055         }
3056
3057         part = find_part(m, start, nbytes, (void**) &q);
3058         if (!part || (nbytes > 0 && !q))
3059                 return -EBADMSG;
3060
3061         *rindex = end;
3062
3063         if (ret)
3064                 *ret = q;
3065
3066         return 0;
3067 }
3068
3069 static bool validate_nul(const char *s, size_t l) {
3070
3071         /* Check for NUL chars in the string */
3072         if (memchr(s, 0, l))
3073                 return false;
3074
3075         /* Check for NUL termination */
3076         if (s[l] != 0)
3077                 return false;
3078
3079         return true;
3080 }
3081
3082 static bool validate_string(const char *s, size_t l) {
3083
3084         if (!validate_nul(s, l))
3085                 return false;
3086
3087         /* Check if valid UTF8 */
3088         if (!utf8_is_valid(s))
3089                 return false;
3090
3091         return true;
3092 }
3093
3094 static bool validate_signature(const char *s, size_t l) {
3095
3096         if (!validate_nul(s, l))
3097                 return false;
3098
3099         /* Check if valid signature */
3100         if (!signature_is_valid(s, true))
3101                 return false;
3102
3103         return true;
3104 }
3105
3106 static bool validate_object_path(const char *s, size_t l) {
3107
3108         if (!validate_nul(s, l))
3109                 return false;
3110
3111         if (!object_path_is_valid(s))
3112                 return false;
3113
3114         return true;
3115 }
3116
3117 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3118         struct bus_container *c;
3119         size_t rindex;
3120         void *q;
3121         int r;
3122
3123         assert_return(m, -EINVAL);
3124         assert_return(m->sealed, -EPERM);
3125         assert_return(bus_type_is_basic(type), -EINVAL);
3126
3127         if (message_end_of_signature(m))
3128                 return -ENXIO;
3129
3130         if (message_end_of_array(m, m->rindex))
3131                 return 0;
3132
3133         c = message_get_container(m);
3134         if (c->signature[c->index] != type)
3135                 return -ENXIO;
3136
3137         rindex = m->rindex;
3138
3139         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3140
3141                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3142                         bool ok;
3143
3144                         r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3145                         if (r < 0)
3146                                 return r;
3147
3148                         if (type == SD_BUS_TYPE_STRING)
3149                                 ok = validate_string(q, c->item_size-1);
3150                         else if (type == SD_BUS_TYPE_OBJECT_PATH)
3151                                 ok = validate_object_path(q, c->item_size-1);
3152                         else
3153                                 ok = validate_signature(q, c->item_size-1);
3154
3155                         if (!ok)
3156                                 return -EBADMSG;
3157
3158                         if (p)
3159                                 *(const char**) p = q;
3160                 } else {
3161                         int sz, align;
3162
3163                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3164                         assert(sz > 0);
3165                         if ((size_t) sz != c->item_size)
3166                                 return -EBADMSG;
3167
3168                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3169                         assert(align > 0);
3170
3171                         r = message_peek_body(m, &rindex, align, c->item_size, &q);
3172                         if (r < 0)
3173                                 return r;
3174
3175                         switch (type) {
3176
3177                         case SD_BUS_TYPE_BYTE:
3178                                 if (p)
3179                                         *(uint8_t*) p = *(uint8_t*) q;
3180                                 break;
3181
3182                         case SD_BUS_TYPE_BOOLEAN:
3183                                 if (p)
3184                                         *(int*) p = !!*(uint8_t*) q;
3185                                 break;
3186
3187                         case SD_BUS_TYPE_INT16:
3188                         case SD_BUS_TYPE_UINT16:
3189                                 if (p)
3190                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3191                                 break;
3192
3193                         case SD_BUS_TYPE_INT32:
3194                         case SD_BUS_TYPE_UINT32:
3195                                 if (p)
3196                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3197                                 break;
3198
3199                         case SD_BUS_TYPE_INT64:
3200                         case SD_BUS_TYPE_UINT64:
3201                         case SD_BUS_TYPE_DOUBLE:
3202                                 if (p)
3203                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3204                                 break;
3205
3206                         case SD_BUS_TYPE_UNIX_FD: {
3207                                 uint32_t j;
3208
3209                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3210                                 if (j >= m->n_fds)
3211                                         return -EBADMSG;
3212
3213                                 if (p)
3214                                         *(int*) p = m->fds[j];
3215
3216                                 break;
3217                         }
3218
3219                         default:
3220                                 assert_not_reached("unexpected type");
3221                         }
3222                 }
3223
3224                 r = container_next_item(m, c, &rindex);
3225                 if (r < 0)
3226   &nb