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