chiark / gitweb /
bus-message: avoid -Wnull-pointer-arithmetic warning on new clang
[elogind.git] / src / libelogind / sd-bus / bus-message.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2013 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/mman.h>
24
25 #include "sd-bus.h"
26
27 #include "alloc-util.h"
28 #include "bus-gvariant.h"
29 #include "bus-internal.h"
30 #include "bus-message.h"
31 #include "bus-signature.h"
32 #include "bus-type.h"
33 #include "bus-util.h"
34 #include "fd-util.h"
35 #include "io-util.h"
36 #include "memfd-util.h"
37 #include "string-util.h"
38 #include "strv.h"
39 #include "time-util.h"
40 #include "utf8.h"
41 #include "util.h"
42
43 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
44
45 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
46
47         if (p == NULL)
48                 return NULL;
49
50         if (old_base == new_base)
51                 return (void*) p;
52
53         if ((uint8_t*) p < (uint8_t*) old_base)
54                 return (void*) p;
55
56         if ((uint8_t*) p >= (uint8_t*) old_base + sz)
57                 return (void*) p;
58
59         return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
60 }
61
62 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
63         assert(m);
64         assert(part);
65
66         if (part->memfd >= 0)
67                 close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
68         else if (part->munmap_this)
69                 munmap(part->mmap_begin, part->mapped);
70         else if (part->free_this)
71                 free(part->data);
72
73         if (part != &m->body)
74                 free(part);
75 }
76
77 static void message_reset_parts(sd_bus_message *m) {
78         struct bus_body_part *part;
79
80         assert(m);
81
82         part = &m->body;
83         while (m->n_body_parts > 0) {
84                 struct bus_body_part *next = part->next;
85                 message_free_part(m, part);
86                 part = next;
87                 m->n_body_parts--;
88         }
89
90         m->body_end = NULL;
91
92         m->cached_rindex_part = NULL;
93         m->cached_rindex_part_begin = 0;
94 }
95
96 static void message_reset_containers(sd_bus_message *m) {
97         unsigned i;
98
99         assert(m);
100
101         for (i = 0; i < m->n_containers; i++) {
102                 free(m->containers[i].signature);
103                 free(m->containers[i].offsets);
104         }
105
106         m->containers = mfree(m->containers);
107
108         m->n_containers = m->containers_allocated = 0;
109         m->root_container.index = 0;
110 }
111
112 static void message_free(sd_bus_message *m) {
113         assert(m);
114
115         if (m->free_header)
116                 free(m->header);
117
118         message_reset_parts(m);
119
120         sd_bus_unref(m->bus);
121
122         if (m->free_fds) {
123                 close_many(m->fds, m->n_fds);
124                 free(m->fds);
125         }
126
127         if (m->iovec != m->iovec_fixed)
128                 free(m->iovec);
129
130         message_reset_containers(m);
131         free(m->root_container.signature);
132         free(m->root_container.offsets);
133
134         free(m->root_container.peeked_signature);
135
136         bus_creds_done(&m->creds);
137         free(m);
138 }
139
140 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
141         void *op, *np;
142         size_t old_size, new_size, start;
143
144         assert(m);
145
146         if (m->poisoned)
147                 return NULL;
148
149         old_size = sizeof(struct bus_header) + m->fields_size;
150         start = ALIGN_TO(old_size, align);
151         new_size = start + sz;
152
153         if (new_size < start ||
154             new_size > (size_t) ((uint32_t) -1))
155                 goto poison;
156
157         if (old_size == new_size)
158                 return (uint8_t*) m->header + old_size;
159
160         if (m->free_header) {
161                 np = realloc(m->header, ALIGN8(new_size));
162                 if (!np)
163                         goto poison;
164         } else {
165                 /* Initially, the header is allocated as part of
166                  * the sd_bus_message itself, let's replace it by
167                  * dynamic data */
168
169                 np = malloc(ALIGN8(new_size));
170                 if (!np)
171                         goto poison;
172
173                 memcpy(np, m->header, sizeof(struct bus_header));
174         }
175
176         /* Zero out padding */
177         if (start > old_size)
178                 memzero((uint8_t*) np + old_size, start - old_size);
179
180         op = m->header;
181         m->header = np;
182         m->fields_size = new_size - sizeof(struct bus_header);
183
184         /* Adjust quick access pointers */
185         m->path = adjust_pointer(m->path, op, old_size, m->header);
186         m->interface = adjust_pointer(m->interface, op, old_size, m->header);
187         m->member = adjust_pointer(m->member, op, old_size, m->header);
188         m->destination = adjust_pointer(m->destination, op, old_size, m->header);
189         m->sender = adjust_pointer(m->sender, op, old_size, m->header);
190         m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
191
192         m->free_header = true;
193
194         if (add_offset) {
195                 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
196                         goto poison;
197
198                 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
199         }
200
201         return (uint8_t*) np + start;
202
203 poison:
204         m->poisoned = true;
205         return NULL;
206 }
207
208 static int message_append_field_string(
209                 sd_bus_message *m,
210                 uint64_t h,
211                 char type,
212                 const char *s,
213                 const char **ret) {
214
215         size_t l;
216         uint8_t *p;
217
218         assert(m);
219
220         /* dbus1 only allows 8bit header field ids */
221         if (h > 0xFF)
222                 return -EINVAL;
223
224         /* dbus1 doesn't allow strings over 32bit, let's enforce this
225          * globally, to not risk convertability */
226         l = strlen(s);
227         if (l > (size_t) (uint32_t) -1)
228                 return -EINVAL;
229
230         /* Signature "(yv)" where the variant contains "s" */
231
232         if (BUS_MESSAGE_IS_GVARIANT(m)) {
233
234                 /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
235                 p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
236                 if (!p)
237                         return -ENOMEM;
238
239                 *((uint64_t*) p) = h;
240                 memcpy(p+8, s, l);
241                 p[8+l] = 0;
242                 p[8+l+1] = 0;
243                 p[8+l+2] = type;
244
245                 if (ret)
246                         *ret = (char*) p + 8;
247
248         } else {
249                 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
250                 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
251                 if (!p)
252                         return -ENOMEM;
253
254                 p[0] = (uint8_t) h;
255                 p[1] = 1;
256                 p[2] = type;
257                 p[3] = 0;
258
259                 ((uint32_t*) p)[1] = l;
260                 memcpy(p + 8, s, l + 1);
261
262                 if (ret)
263                         *ret = (char*) p + 8;
264         }
265
266         return 0;
267 }
268
269 static int message_append_field_signature(
270                 sd_bus_message *m,
271                 uint64_t h,
272                 const char *s,
273                 const char **ret) {
274
275         size_t l;
276         uint8_t *p;
277
278         assert(m);
279
280         /* dbus1 only allows 8bit header field ids */
281         if (h > 0xFF)
282                 return -EINVAL;
283
284         /* dbus1 doesn't allow signatures over 8bit, let's enforce
285          * this globally, to not risk convertability */
286         l = strlen(s);
287         if (l > 255)
288                 return -EINVAL;
289
290         /* Signature "(yv)" where the variant contains "g" */
291
292         if (BUS_MESSAGE_IS_GVARIANT(m))
293                 /* For gvariant the serialization is the same as for normal strings */
294                 return message_append_field_string(m, h, 'g', s, ret);
295         else {
296                 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
297                 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
298                 if (!p)
299                         return -ENOMEM;
300
301                 p[0] = (uint8_t) h;
302                 p[1] = 1;
303                 p[2] = SD_BUS_TYPE_SIGNATURE;
304                 p[3] = 0;
305                 p[4] = l;
306                 memcpy(p + 5, s, l + 1);
307
308                 if (ret)
309                         *ret = (const char*) p + 5;
310         }
311
312         return 0;
313 }
314
315 static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
316         uint8_t *p;
317
318         assert(m);
319
320         /* dbus1 only allows 8bit header field ids */
321         if (h > 0xFF)
322                 return -EINVAL;
323
324         if (BUS_MESSAGE_IS_GVARIANT(m)) {
325                 /* (field id 64bit + ((value + NUL + signature string 'u') */
326
327                 p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
328                 if (!p)
329                         return -ENOMEM;
330
331                 *((uint64_t*) p) = h;
332                 *((uint32_t*) (p + 8)) = x;
333                 p[12] = 0;
334                 p[13] = 'u';
335         } else {
336                 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
337                 p = message_extend_fields(m, 8, 4 + 4, false);
338                 if (!p)
339                         return -ENOMEM;
340
341                 p[0] = (uint8_t) h;
342                 p[1] = 1;
343                 p[2] = 'u';
344                 p[3] = 0;
345
346                 ((uint32_t*) p)[1] = x;
347         }
348
349         return 0;
350 }
351
352 static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
353         uint8_t *p;
354
355         assert(m);
356
357         /* dbus1 only allows 8bit header field ids */
358         if (h > 0xFF)
359                 return -EINVAL;
360
361         if (BUS_MESSAGE_IS_GVARIANT(m)) {
362                 /* (field id 64bit + ((value + NUL + signature string 't') */
363
364                 p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
365                 if (!p)
366                         return -ENOMEM;
367
368                 *((uint64_t*) p) = h;
369                 *((uint64_t*) (p + 8)) = x;
370                 p[16] = 0;
371                 p[17] = 't';
372         } else {
373                 /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
374                 p = message_extend_fields(m, 8, 4 + 4 + 8, false);
375                 if (!p)
376                         return -ENOMEM;
377
378                 p[0] = (uint8_t) h;
379                 p[1] = 1;
380                 p[2] = 't';
381                 p[3] = 0;
382                 p[4] = 0;
383                 p[5] = 0;
384                 p[6] = 0;
385                 p[7] = 0;
386
387                 ((uint64_t*) p)[1] = x;
388         }
389
390         return 0;
391 }
392
393 static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
394         assert(m);
395
396         if (BUS_MESSAGE_IS_GVARIANT(m))
397                 return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
398         else {
399                 /* 64bit cookies are not supported on dbus1 */
400                 if (cookie > 0xffffffffUL)
401                         return -EOPNOTSUPP;
402
403                 return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
404         }
405 }
406
407 int bus_message_from_header(
408                 sd_bus *bus,
409                 void *header,
410                 size_t header_accessible,
411                 void *footer,
412                 size_t footer_accessible,
413                 size_t message_size,
414                 int *fds,
415                 unsigned n_fds,
416                 const char *label,
417                 size_t extra,
418                 sd_bus_message **ret) {
419
420         _cleanup_free_ sd_bus_message *m = NULL;
421         struct bus_header *h;
422         size_t a, label_sz;
423
424         assert(bus);
425         assert(header || header_accessible <= 0);
426         assert(footer || footer_accessible <= 0);
427         assert(fds || n_fds <= 0);
428         assert(ret);
429
430         if (header_accessible < sizeof(struct bus_header))
431                 return -EBADMSG;
432
433         if (header_accessible > message_size)
434                 return -EBADMSG;
435         if (footer_accessible > message_size)
436                 return -EBADMSG;
437
438         h = header;
439         if (!IN_SET(h->version, 1, 2))
440                 return -EBADMSG;
441
442         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
443                 return -EBADMSG;
444
445         if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
446                 return -EBADMSG;
447
448         /* Note that we are happy with unknown flags in the flags header! */
449
450         a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
451
452         if (label) {
453                 label_sz = strlen(label);
454                 a += label_sz + 1;
455         }
456
457         m = malloc0(a);
458         if (!m)
459                 return -ENOMEM;
460
461         m->n_ref = 1;
462         m->sealed = true;
463         m->header = header;
464         m->header_accessible = header_accessible;
465         m->footer = footer;
466         m->footer_accessible = footer_accessible;
467
468         if (BUS_MESSAGE_IS_GVARIANT(m)) {
469                 size_t ws;
470
471                 if (h->dbus2.cookie == 0)
472                         return -EBADMSG;
473
474                 /* dbus2 derives the sizes from the message size and
475                 the offset table at the end, since it is formatted as
476                 gvariant "yyyyuta{tv}v". Since the message itself is a
477                 structure with precisely to variable sized entries,
478                 there's only one offset in the table, which marks the
479                 end of the fields array. */
480
481                 ws = bus_gvariant_determine_word_size(message_size, 0);
482                 if (footer_accessible < ws)
483                         return -EBADMSG;
484
485                 m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
486                 if (ALIGN8(m->fields_size) > message_size - ws)
487                         return -EBADMSG;
488                 if (m->fields_size < sizeof(struct bus_header))
489                         return -EBADMSG;
490
491                 m->fields_size -= sizeof(struct bus_header);
492                 m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
493         } else {
494                 if (h->dbus1.serial == 0)
495                         return -EBADMSG;
496
497                 /* dbus1 has the sizes in the header */
498                 m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
499                 m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
500
501                 if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
502                         return -EBADMSG;
503         }
504
505         m->fds = fds;
506         m->n_fds = n_fds;
507
508         if (label) {
509                 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
510                 memcpy(m->creds.label, label, label_sz + 1);
511
512                 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
513         }
514
515         m->bus = sd_bus_ref(bus);
516         *ret = m;
517         m = NULL;
518
519         return 0;
520 }
521
522 int bus_message_from_malloc(
523                 sd_bus *bus,
524                 void *buffer,
525                 size_t length,
526                 int *fds,
527                 unsigned n_fds,
528                 const char *label,
529                 sd_bus_message **ret) {
530
531         sd_bus_message *m;
532         size_t sz;
533         int r;
534
535         r = bus_message_from_header(
536                         bus,
537                         buffer, length, /* in this case the initial bytes and the final bytes are the same */
538                         buffer, length,
539                         length,
540                         fds, n_fds,
541                         label,
542                         0, &m);
543         if (r < 0)
544                 return r;
545
546         sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
547         if (sz > 0) {
548                 m->n_body_parts = 1;
549                 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
550                 m->body.size = sz;
551                 m->body.sealed = true;
552                 m->body.memfd = -1;
553         }
554
555         m->n_iovec = 1;
556         m->iovec = m->iovec_fixed;
557         m->iovec[0].iov_base = buffer;
558         m->iovec[0].iov_len = length;
559
560         r = bus_message_parse_fields(m);
561         if (r < 0)
562                 goto fail;
563
564         /* We take possession of the memory and fds now */
565         m->free_header = true;
566         m->free_fds = true;
567
568         *ret = m;
569         return 0;
570
571 fail:
572         message_free(m);
573         return r;
574 }
575
576 _public_ int sd_bus_message_new(
577                 sd_bus *bus,
578                 sd_bus_message **m,
579                 uint8_t type) {
580
581         sd_bus_message *t;
582
583         assert_return(bus, -ENOTCONN);
584         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
585         assert_return(m, -EINVAL);
586         assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
587
588         t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
589         if (!t)
590                 return -ENOMEM;
591
592         t->n_ref = 1;
593         t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message)));
594         t->header->endian = BUS_NATIVE_ENDIAN;
595         t->header->type = type;
596         t->header->version = bus->message_version;
597         t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING);
598         t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t);
599         t->bus = sd_bus_ref(bus);
600
601         if (bus->allow_interactive_authorization)
602                 t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
603
604         *m = t;
605         return 0;
606 }
607
608 _public_ int sd_bus_message_new_signal(
609                 sd_bus *bus,
610                 sd_bus_message **m,
611                 const char *path,
612                 const char *interface,
613                 const char *member) {
614
615         sd_bus_message *t;
616         int r;
617
618         assert_return(bus, -ENOTCONN);
619         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
620         assert_return(object_path_is_valid(path), -EINVAL);
621         assert_return(interface_name_is_valid(interface), -EINVAL);
622         assert_return(member_name_is_valid(member), -EINVAL);
623         assert_return(m, -EINVAL);
624
625         r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL);
626         if (r < 0)
627                 return -ENOMEM;
628
629         assert(t);
630
631         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
632
633         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
634         if (r < 0)
635                 goto fail;
636         r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
637         if (r < 0)
638                 goto fail;
639         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
640         if (r < 0)
641                 goto fail;
642
643         *m = t;
644         return 0;
645
646 fail:
647         sd_bus_message_unref(t);
648         return r;
649 }
650
651 _public_ int sd_bus_message_new_method_call(
652                 sd_bus *bus,
653                 sd_bus_message **m,
654                 const char *destination,
655                 const char *path,
656                 const char *interface,
657                 const char *member) {
658
659         sd_bus_message *t;
660         int r;
661
662         assert_return(bus, -ENOTCONN);
663         assert_return(bus->state != BUS_UNSET, -ENOTCONN);
664         assert_return(!destination || service_name_is_valid(destination), -EINVAL);
665         assert_return(object_path_is_valid(path), -EINVAL);
666         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
667         assert_return(member_name_is_valid(member), -EINVAL);
668         assert_return(m, -EINVAL);
669
670         r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL);
671         if (r < 0)
672                 return -ENOMEM;
673
674         assert(t);
675
676         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
677         if (r < 0)
678                 goto fail;
679         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
680         if (r < 0)
681                 goto fail;
682
683         if (interface) {
684                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
685                 if (r < 0)
686                         goto fail;
687         }
688
689         if (destination) {
690                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
691                 if (r < 0)
692                         goto fail;
693         }
694
695         *m = t;
696         return 0;
697
698 fail:
699         message_free(t);
700         return r;
701 }
702
703 static int message_new_reply(
704                 sd_bus_message *call,
705                 uint8_t type,
706                 sd_bus_message **m) {
707
708         sd_bus_message *t;
709         uint64_t cookie;
710         int r;
711
712         assert_return(call, -EINVAL);
713         assert_return(call->sealed, -EPERM);
714         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
715         assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
716         assert_return(m, -EINVAL);
717
718         cookie = BUS_MESSAGE_COOKIE(call);
719         if (cookie == 0)
720                 return -EOPNOTSUPP;
721
722         r = sd_bus_message_new(call->bus, &t, type);
723         if (r < 0)
724                 return -ENOMEM;
725
726         assert(t);
727
728         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
729         t->reply_cookie = cookie;
730         r = message_append_reply_cookie(t, t->reply_cookie);
731         if (r < 0)
732                 goto fail;
733
734         if (call->sender) {
735                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
736                 if (r < 0)
737                         goto fail;
738         }
739
740         t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
741         t->enforced_reply_signature = call->enforced_reply_signature;
742
743         *m = t;
744         return 0;
745
746 fail:
747         message_free(t);
748         return r;
749 }
750
751 _public_ int sd_bus_message_new_method_return(
752                 sd_bus_message *call,
753                 sd_bus_message **m) {
754
755         return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
756 }
757
758 _public_ int sd_bus_message_new_method_error(
759                 sd_bus_message *call,
760                 sd_bus_message **m,
761                 const sd_bus_error *e) {
762
763         sd_bus_message *t;
764         int r;
765
766         assert_return(sd_bus_error_is_set(e), -EINVAL);
767         assert_return(m, -EINVAL);
768
769         r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
770         if (r < 0)
771                 return r;
772
773         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
774         if (r < 0)
775                 goto fail;
776
777         if (e->message) {
778                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
779                 if (r < 0)
780                         goto fail;
781         }
782
783         t->error._need_free = -1;
784
785         *m = t;
786         return 0;
787
788 fail:
789         message_free(t);
790         return r;
791 }
792
793 _public_ int sd_bus_message_new_method_errorf(
794                 sd_bus_message *call,
795                 sd_bus_message **m,
796                 const char *name,
797                 const char *format,
798                 ...) {
799
800         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
801         va_list ap;
802
803         assert_return(name, -EINVAL);
804         assert_return(m, -EINVAL);
805
806         va_start(ap, format);
807         bus_error_setfv(&error, name, format, ap);
808         va_end(ap);
809
810         return sd_bus_message_new_method_error(call, m, &error);
811 }
812
813 _public_ int sd_bus_message_new_method_errno(
814                 sd_bus_message *call,
815                 sd_bus_message **m,
816                 int error,
817                 const sd_bus_error *p) {
818
819         _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
820
821         if (sd_bus_error_is_set(p))
822                 return sd_bus_message_new_method_error(call, m, p);
823
824         sd_bus_error_set_errno(&berror, error);
825
826         return sd_bus_message_new_method_error(call, m, &berror);
827 }
828
829 _public_ int sd_bus_message_new_method_errnof(
830                 sd_bus_message *call,
831                 sd_bus_message **m,
832                 int error,
833                 const char *format,
834                 ...) {
835
836         _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
837         va_list ap;
838
839         va_start(ap, format);
840         sd_bus_error_set_errnofv(&berror, error, format, ap);
841         va_end(ap);
842
843         return sd_bus_message_new_method_error(call, m, &berror);
844 }
845
846 void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
847         assert(bus);
848         assert(m);
849
850         m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
851         m->creds.well_known_names_local = true;
852         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
853 }
854
855 void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
856         assert(bus);
857         assert(m);
858
859         m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
860         m->creds.well_known_names_driver = true;
861         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
862 }
863
864 int bus_message_new_synthetic_error(
865                 sd_bus *bus,
866                 uint64_t cookie,
867                 const sd_bus_error *e,
868                 sd_bus_message **m) {
869
870         sd_bus_message *t;
871         int r;
872
873         assert(bus);
874         assert(sd_bus_error_is_set(e));
875         assert(m);
876
877         r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR);
878         if (r < 0)
879                 return -ENOMEM;
880
881         assert(t);
882
883         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
884         t->reply_cookie = cookie;
885
886         r = message_append_reply_cookie(t, t->reply_cookie);
887         if (r < 0)
888                 goto fail;
889
890         if (bus && bus->unique_name) {
891                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
892                 if (r < 0)
893                         goto fail;
894         }
895
896         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
897         if (r < 0)
898                 goto fail;
899
900         if (e->message) {
901                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
902                 if (r < 0)
903                         goto fail;
904         }
905
906         t->error._need_free = -1;
907
908         bus_message_set_sender_driver(bus, t);
909
910         *m = t;
911         return 0;
912
913 fail:
914         message_free(t);
915         return r;
916 }
917
918 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
919
920         if (!m)
921                 return NULL;
922
923         assert(m->n_ref > 0);
924         m->n_ref++;
925
926         return m;
927 }
928
929 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
930
931         if (!m)
932                 return NULL;
933
934         assert(m->n_ref > 0);
935         m->n_ref--;
936
937         if (m->n_ref > 0)
938                 return NULL;
939
940         message_free(m);
941         return NULL;
942 }
943
944 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
945         assert_return(m, -EINVAL);
946         assert_return(type, -EINVAL);
947
948         *type = m->header->type;
949         return 0;
950 }
951
952 _public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
953         uint64_t c;
954
955         assert_return(m, -EINVAL);
956         assert_return(cookie, -EINVAL);
957
958         c = BUS_MESSAGE_COOKIE(m);
959         if (c == 0)
960                 return -ENODATA;
961
962         *cookie = BUS_MESSAGE_COOKIE(m);
963         return 0;
964 }
965
966 _public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
967         assert_return(m, -EINVAL);
968         assert_return(cookie, -EINVAL);
969
970         if (m->reply_cookie == 0)
971                 return -ENODATA;
972
973         *cookie = m->reply_cookie;
974         return 0;
975 }
976
977 _public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
978         assert_return(m, -EINVAL);
979
980         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
981                 !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
982 }
983
984 _public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
985         assert_return(m, -EINVAL);
986
987         return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
988 }
989
990 _public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
991         assert_return(m, -EINVAL);
992
993         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
994                 (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
995 }
996
997 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
998         assert_return(m, NULL);
999
1000         return m->path;
1001 }
1002
1003 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
1004         assert_return(m, NULL);
1005
1006         return m->interface;
1007 }
1008
1009 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
1010         assert_return(m, NULL);
1011
1012         return m->member;
1013 }
1014
1015 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
1016         assert_return(m, NULL);
1017
1018         return m->destination;
1019 }
1020
1021 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
1022         assert_return(m, NULL);
1023
1024         return m->sender;
1025 }
1026
1027 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
1028         assert_return(m, NULL);
1029
1030         if (!sd_bus_error_is_set(&m->error))
1031                 return NULL;
1032
1033         return &m->error;
1034 }
1035
1036 _public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
1037         assert_return(m, -EINVAL);
1038         assert_return(usec, -EINVAL);
1039
1040         if (m->monotonic <= 0)
1041                 return -ENODATA;
1042
1043         *usec = m->monotonic;
1044         return 0;
1045 }
1046
1047 _public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
1048         assert_return(m, -EINVAL);
1049         assert_return(usec, -EINVAL);
1050
1051         if (m->realtime <= 0)
1052                 return -ENODATA;
1053
1054         *usec = m->realtime;
1055         return 0;
1056 }
1057
1058 _public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
1059         assert_return(m, -EINVAL);
1060         assert_return(seqnum, -EINVAL);
1061
1062         if (m->seqnum <= 0)
1063                 return -ENODATA;
1064
1065         *seqnum = m->seqnum;
1066         return 0;
1067 }
1068
1069 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
1070         assert_return(m, NULL);
1071
1072         if (m->creds.mask == 0)
1073                 return NULL;
1074
1075         return &m->creds;
1076 }
1077
1078 _public_ int sd_bus_message_is_signal(
1079                 sd_bus_message *m,
1080                 const char *interface,
1081                 const char *member) {
1082
1083         assert_return(m, -EINVAL);
1084
1085         if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
1086                 return 0;
1087
1088         if (interface && (!m->interface || !streq(m->interface, interface)))
1089                 return 0;
1090
1091         if (member &&  (!m->member || !streq(m->member, member)))
1092                 return 0;
1093
1094         return 1;
1095 }
1096
1097 _public_ int sd_bus_message_is_method_call(
1098                 sd_bus_message *m,
1099                 const char *interface,
1100                 const char *member) {
1101
1102         assert_return(m, -EINVAL);
1103
1104         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
1105                 return 0;
1106
1107         if (interface && (!m->interface || !streq(m->interface, interface)))
1108                 return 0;
1109
1110         if (member &&  (!m->member || !streq(m->member, member)))
1111                 return 0;
1112
1113         return 1;
1114 }
1115
1116 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
1117         assert_return(m, -EINVAL);
1118
1119         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
1120                 return 0;
1121
1122         if (name && (!m->error.name || !streq(m->error.name, name)))
1123                 return 0;
1124
1125         return 1;
1126 }
1127
1128 _public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
1129         assert_return(m, -EINVAL);
1130         assert_return(!m->sealed, -EPERM);
1131         assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
1132
1133         SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
1134
1135         return 0;
1136 }
1137
1138 _public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
1139         assert_return(m, -EINVAL);
1140         assert_return(!m->sealed, -EPERM);
1141
1142         SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
1143
1144         return 0;
1145 }
1146
1147 _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
1148         assert_return(m, -EINVAL);
1149         assert_return(!m->sealed, -EPERM);
1150
1151         SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
1152
1153         return 0;
1154 }
1155
1156 static struct bus_container *message_get_container(sd_bus_message *m) {
1157         assert(m);
1158
1159         if (m->n_containers == 0)
1160                 return &m->root_container;
1161
1162         assert(m->containers);
1163         return m->containers + m->n_containers - 1;
1164 }
1165
1166 struct bus_body_part *message_append_part(sd_bus_message *m) {
1167         struct bus_body_part *part;
1168
1169         assert(m);
1170
1171         if (m->poisoned)
1172                 return NULL;
1173
1174         if (m->n_body_parts <= 0) {
1175                 part = &m->body;
1176                 zero(*part);
1177         } else {
1178                 assert(m->body_end);
1179
1180                 part = new0(struct bus_body_part, 1);
1181                 if (!part) {
1182                         m->poisoned = true;
1183                         return NULL;
1184                 }
1185
1186                 m->body_end->next = part;
1187         }
1188
1189         part->memfd = -1;
1190         m->body_end = part;
1191         m->n_body_parts++;
1192
1193         return part;
1194 }
1195
1196 static void part_zero(struct bus_body_part *part, size_t sz) {
1197         assert(part);
1198         assert(sz > 0);
1199         assert(sz < 8);
1200
1201         /* All other fields can be left in their defaults */
1202         assert(!part->data);
1203         assert(part->memfd < 0);
1204
1205         part->size = sz;
1206         part->is_zero = true;
1207         part->sealed = true;
1208 }
1209
1210 static int part_make_space(
1211                 struct sd_bus_message *m,
1212                 struct bus_body_part *part,
1213                 size_t sz,
1214                 void **q) {
1215
1216         void *n;
1217
1218         assert(m);
1219         assert(part);
1220         assert(!part->sealed);
1221
1222         if (m->poisoned)
1223                 return -ENOMEM;
1224
1225         if (part->allocated == 0 || sz > part->allocated) {
1226                 size_t new_allocated;
1227
1228                 new_allocated = sz > 0 ? 2 * sz : 64;
1229                 n = realloc(part->data, new_allocated);
1230                 if (!n) {
1231                         m->poisoned = true;
1232                         return -ENOMEM;
1233                 }
1234
1235                 part->data = n;
1236                 part->allocated = new_allocated;
1237                 part->free_this = true;
1238         }
1239
1240         if (q)
1241                 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1242
1243         part->size = sz;
1244         return 0;
1245 }
1246
1247 static int message_add_offset(sd_bus_message *m, size_t offset) {
1248         struct bus_container *c;
1249
1250         assert(m);
1251         assert(BUS_MESSAGE_IS_GVARIANT(m));
1252
1253         /* Add offset to current container, unless this is the first
1254          * item in it, which will have the 0 offset, which we can
1255          * ignore. */
1256         c = message_get_container(m);
1257
1258         if (!c->need_offsets)
1259                 return 0;
1260
1261         if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
1262                 return -ENOMEM;
1263
1264         c->offsets[c->n_offsets++] = offset;
1265         return 0;
1266 }
1267
1268 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1269         struct bus_container *c;
1270
1271         assert(m);
1272
1273         if (expand <= 0)
1274                 return;
1275
1276         /* Update counters */
1277         for (c = m->containers; c < m->containers + m->n_containers; c++) {
1278
1279                 if (c->array_size)
1280                         *c->array_size += expand;
1281         }
1282 }
1283
1284 static void *message_extend_body(
1285                 sd_bus_message *m,
1286                 size_t align,
1287                 size_t sz,
1288                 bool add_offset,
1289                 bool force_inline) {
1290
1291         size_t start_body, end_body, padding, added;
1292         void *p;
1293         int r;
1294
1295         assert(m);
1296         assert(align > 0);
1297         assert(!m->sealed);
1298
1299         if (m->poisoned)
1300                 return NULL;
1301
1302         start_body = ALIGN_TO((size_t) m->body_size, align);
1303         end_body = start_body + sz;
1304
1305         padding = start_body - m->body_size;
1306         added = padding + sz;
1307
1308         /* Check for 32bit overflows */
1309         if (end_body > (size_t) ((uint32_t) -1) ||
1310             end_body < start_body) {
1311                 m->poisoned = true;
1312                 return NULL;
1313         }
1314
1315         if (added > 0) {
1316                 struct bus_body_part *part = NULL;
1317                 bool add_new_part;
1318
1319                 add_new_part =
1320                         m->n_body_parts <= 0 ||
1321                         m->body_end->sealed ||
1322                         (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
1323                         (force_inline && m->body_end->size > MEMFD_MIN_SIZE);
1324                         /* If this must be an inlined extension, let's create a new part if
1325                          * the previous part is large enough to be inlined. */
1326
1327                 if (add_new_part) {
1328                         if (padding > 0) {
1329                                 part = message_append_part(m);
1330                                 if (!part)
1331                                         return NULL;
1332
1333                                 part_zero(part, padding);
1334                         }
1335
1336                         part = message_append_part(m);
1337                         if (!part)
1338                                 return NULL;
1339
1340                         r = part_make_space(m, part, sz, &p);
1341                         if (r < 0)
1342                                 return NULL;
1343                 } else {
1344                         struct bus_container *c;
1345                         void *op;
1346                         size_t os, start_part, end_part;
1347
1348                         part = m->body_end;
1349                         op = part->data;
1350                         os = part->size;
1351
1352                         start_part = ALIGN_TO(part->size, align);
1353                         end_part = start_part + sz;
1354
1355                         r = part_make_space(m, part, end_part, &p);
1356                         if (r < 0)
1357                                 return NULL;
1358
1359                         if (padding > 0) {
1360                                 memzero(p, padding);
1361                                 p = (uint8_t*) p + padding;
1362                         }
1363
1364                         /* Readjust pointers */
1365                         for (c = m->containers; c < m->containers + m->n_containers; c++)
1366                                 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1367
1368                         m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1369                 }
1370         } else
1371                 /* Return something that is not NULL and is aligned */
1372                 p = (uint8_t*) align;
1373
1374         m->body_size = end_body;
1375         message_extend_containers(m, added);
1376
1377         if (add_offset) {
1378                 r = message_add_offset(m, end_body);
1379                 if (r < 0) {
1380                         m->poisoned = true;
1381                         return NULL;
1382                 }
1383         }
1384
1385         return p;
1386 }
1387
1388 static int message_push_fd(sd_bus_message *m, int fd) {
1389         int *f, copy;
1390
1391         assert(m);
1392
1393         if (fd < 0)
1394                 return -EINVAL;
1395
1396         if (!m->allow_fds)
1397                 return -EOPNOTSUPP;
1398
1399         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1400         if (copy < 0)
1401                 return -errno;
1402
1403         f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1404         if (!f) {
1405                 m->poisoned = true;
1406                 safe_close(copy);
1407                 return -ENOMEM;
1408         }
1409
1410         m->fds = f;
1411         m->fds[m->n_fds] = copy;
1412         m->free_fds = true;
1413
1414         return copy;
1415 }
1416
1417 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1418         _cleanup_close_ int fd = -1;
1419         struct bus_container *c;
1420         ssize_t align, sz;
1421         void *a;
1422
1423         assert_return(m, -EINVAL);
1424         assert_return(!m->sealed, -EPERM);
1425         assert_return(bus_type_is_basic(type), -EINVAL);
1426         assert_return(!m->poisoned, -ESTALE);
1427
1428         c = message_get_container(m);
1429
1430         if (c->signature && c->signature[c->index]) {
1431                 /* Container signature is already set */
1432
1433                 if (c->signature[c->index] != type)
1434                         return -ENXIO;
1435         } else {
1436                 char *e;
1437
1438                 /* Maybe we can append to the signature? But only if this is the top-level container */
1439                 if (c->enclosing != 0)
1440                         return -ENXIO;
1441
1442                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1443                 if (!e) {
1444                         m->poisoned = true;
1445                         return -ENOMEM;
1446                 }
1447         }
1448
1449         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1450                 uint8_t u8;
1451                 uint32_t u32;
1452
1453                 switch (type) {
1454
1455                 case SD_BUS_TYPE_SIGNATURE:
1456                 case SD_BUS_TYPE_STRING:
1457                         p = strempty(p);
1458
1459                         _fallthrough_;
1460                 case SD_BUS_TYPE_OBJECT_PATH:
1461                         if (!p)
1462                                 return -EINVAL;
1463
1464                         align = 1;
1465                         sz = strlen(p) + 1;
1466                         break;
1467
1468                 case SD_BUS_TYPE_BOOLEAN:
1469
1470                         u8 = p && *(int*) p;
1471                         p = &u8;
1472
1473                         align = sz = 1;
1474                         break;
1475
1476                 case SD_BUS_TYPE_UNIX_FD:
1477
1478                         if (!p)
1479                                 return -EINVAL;
1480
1481                         fd = message_push_fd(m, *(int*) p);
1482                         if (fd < 0)
1483                                 return fd;
1484
1485                         u32 = m->n_fds;
1486                         p = &u32;
1487
1488                         align = sz = 4;
1489                         break;
1490
1491                 default:
1492                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1493                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1494                         break;
1495                 }
1496
1497                 assert(align > 0);
1498                 assert(sz > 0);
1499
1500                 a = message_extend_body(m, align, sz, true, false);
1501                 if (!a)
1502                         return -ENOMEM;
1503
1504                 memcpy(a, p, sz);
1505
1506                 if (stored)
1507                         *stored = (const uint8_t*) a;
1508
1509         } else {
1510                 uint32_t u32;
1511
1512                 switch (type) {
1513
1514                 case SD_BUS_TYPE_STRING:
1515                         /* To make things easy we'll serialize a NULL string
1516                          * into the empty string */
1517                         p = strempty(p);
1518
1519                         _fallthrough_;
1520                 case SD_BUS_TYPE_OBJECT_PATH:
1521
1522                         if (!p)
1523                                 return -EINVAL;
1524
1525                         align = 4;
1526                         sz = 4 + strlen(p) + 1;
1527                         break;
1528
1529                 case SD_BUS_TYPE_SIGNATURE:
1530
1531                         p = strempty(p);
1532
1533                         align = 1;
1534                         sz = 1 + strlen(p) + 1;
1535                         break;
1536
1537                 case SD_BUS_TYPE_BOOLEAN:
1538
1539                         u32 = p && *(int*) p;
1540                         p = &u32;
1541
1542                         align = sz = 4;
1543                         break;
1544
1545                 case SD_BUS_TYPE_UNIX_FD:
1546
1547                         if (!p)
1548                                 return -EINVAL;
1549
1550                         fd = message_push_fd(m, *(int*) p);
1551                         if (fd < 0)
1552                                 return fd;
1553
1554                         u32 = m->n_fds;
1555                         p = &u32;
1556
1557                         align = sz = 4;
1558                         break;
1559
1560                 default:
1561                         align = bus_type_get_alignment(type);
1562                         sz = bus_type_get_size(type);
1563                         break;
1564                 }
1565
1566                 assert(align > 0);
1567                 assert(sz > 0);
1568
1569                 a = message_extend_body(m, align, sz, false, false);
1570                 if (!a)
1571                         return -ENOMEM;
1572
1573                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
1574                         *(uint32_t*) a = sz - 5;
1575                         memcpy((uint8_t*) a + 4, p, sz - 4);
1576
1577                         if (stored)
1578                                 *stored = (const uint8_t*) a + 4;
1579
1580                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1581                         *(uint8_t*) a = sz - 2;
1582                         memcpy((uint8_t*) a + 1, p, sz - 1);
1583
1584                         if (stored)
1585                                 *stored = (const uint8_t*) a + 1;
1586                 } else {
1587                         memcpy(a, p, sz);
1588
1589                         if (stored)
1590                                 *stored = a;
1591                 }
1592         }
1593
1594         if (type == SD_BUS_TYPE_UNIX_FD)
1595                 m->n_fds++;
1596
1597         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1598                 c->index++;
1599
1600         fd = -1;
1601         return 0;
1602 }
1603
1604 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1605         return message_append_basic(m, type, p, NULL);
1606 }
1607
1608 _public_ int sd_bus_message_append_string_space(
1609                 sd_bus_message *m,
1610                 size_t size,
1611                 char **s) {
1612
1613         struct bus_container *c;
1614         void *a;
1615
1616         assert_return(m, -EINVAL);
1617         assert_return(s, -EINVAL);
1618         assert_return(!m->sealed, -EPERM);
1619         assert_return(!m->poisoned, -ESTALE);
1620
1621         c = message_get_container(m);
1622
1623         if (c->signature && c->signature[c->index]) {
1624                 /* Container signature is already set */
1625
1626                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1627                         return -ENXIO;
1628         } else {
1629                 char *e;
1630
1631                 /* Maybe we can append to the signature? But only if this is the top-level container */
1632                 if (c->enclosing != 0)
1633                         return -ENXIO;
1634
1635                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1636                 if (!e) {
1637                         m->poisoned = true;
1638                         return -ENOMEM;
1639                 }
1640         }
1641
1642         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1643                 a = message_extend_body(m, 1, size + 1, true, false);
1644                 if (!a)
1645                         return -ENOMEM;
1646
1647                 *s = a;
1648         } else {
1649                 a = message_extend_body(m, 4, 4 + size + 1, false, false);
1650                 if (!a)
1651                         return -ENOMEM;
1652
1653                 *(uint32_t*) a = size;
1654                 *s = (char*) a + 4;
1655         }
1656
1657         (*s)[size] = 0;
1658
1659         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1660                 c->index++;
1661
1662         return 0;
1663 }
1664
1665 _public_ int sd_bus_message_append_string_iovec(
1666                 sd_bus_message *m,
1667                 const struct iovec *iov,
1668                 unsigned n) {
1669
1670         size_t size;
1671         unsigned i;
1672         char *p;
1673         int r;
1674
1675         assert_return(m, -EINVAL);
1676         assert_return(!m->sealed, -EPERM);
1677         assert_return(iov || n == 0, -EINVAL);
1678         assert_return(!m->poisoned, -ESTALE);
1679
1680         size = IOVEC_TOTAL_SIZE(iov, n);
1681
1682         r = sd_bus_message_append_string_space(m, size, &p);
1683         if (r < 0)
1684                 return r;
1685
1686         for (i = 0; i < n; i++) {
1687
1688                 if (iov[i].iov_base)
1689                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
1690                 else
1691                         memset(p, ' ', iov[i].iov_len);
1692
1693                 p += iov[i].iov_len;
1694         }
1695
1696         return 0;
1697 }
1698
1699 static int bus_message_open_array(
1700                 sd_bus_message *m,
1701                 struct bus_container *c,
1702                 const char *contents,
1703                 uint32_t **array_size,
1704                 size_t *begin,
1705                 bool *need_offsets) {
1706
1707         unsigned nindex;
1708         int alignment, r;
1709
1710         assert(m);
1711         assert(c);
1712         assert(contents);
1713         assert(array_size);
1714         assert(begin);
1715         assert(need_offsets);
1716
1717         if (!signature_is_single(contents, true))
1718                 return -EINVAL;
1719
1720         if (c->signature && c->signature[c->index]) {
1721
1722                 /* Verify the existing signature */
1723
1724                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1725                         return -ENXIO;
1726
1727                 if (!startswith(c->signature + c->index + 1, contents))
1728                         return -ENXIO;
1729
1730                 nindex = c->index + 1 + strlen(contents);
1731         } else {
1732                 char *e;
1733
1734                 if (c->enclosing != 0)
1735                         return -ENXIO;
1736
1737                 /* Extend the existing signature */
1738
1739                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1740                 if (!e) {
1741                         m->poisoned = true;
1742                         return -ENOMEM;
1743                 }
1744
1745                 nindex = e - c->signature;
1746         }
1747
1748         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1749                 alignment = bus_gvariant_get_alignment(contents);
1750                 if (alignment < 0)
1751                         return alignment;
1752
1753                 /* Add alignment padding and add to offset list */
1754                 if (!message_extend_body(m, alignment, 0, false, false))
1755                         return -ENOMEM;
1756
1757                 r = bus_gvariant_is_fixed_size(contents);
1758                 if (r < 0)
1759                         return r;
1760
1761                 *begin = m->body_size;
1762                 *need_offsets = r == 0;
1763         } else {
1764                 void *a, *op;
1765                 size_t os;
1766                 struct bus_body_part *o;
1767
1768                 alignment = bus_type_get_alignment(contents[0]);
1769                 if (alignment < 0)
1770                         return alignment;
1771
1772                 a = message_extend_body(m, 4, 4, false, false);
1773                 if (!a)
1774                         return -ENOMEM;
1775
1776                 o = m->body_end;
1777                 op = m->body_end->data;
1778                 os = m->body_end->size;
1779
1780                 /* Add alignment between size and first element */
1781                 if (!message_extend_body(m, alignment, 0, false, false))
1782                         return -ENOMEM;
1783
1784                 /* location of array size might have changed so let's readjust a */
1785                 if (o == m->body_end)
1786                         a = adjust_pointer(a, op, os, m->body_end->data);
1787
1788                 *(uint32_t*) a = 0;
1789                 *array_size = a;
1790         }
1791
1792         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1793                 c->index = nindex;
1794
1795         return 0;
1796 }
1797
1798 static int bus_message_open_variant(
1799                 sd_bus_message *m,
1800                 struct bus_container *c,
1801                 const char *contents) {
1802
1803         assert(m);
1804         assert(c);
1805         assert(contents);
1806
1807         if (!signature_is_single(contents, false))
1808                 return -EINVAL;
1809
1810         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1811                 return -EINVAL;
1812
1813         if (c->signature && c->signature[c->index]) {
1814
1815                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1816                         return -ENXIO;
1817
1818         } else {
1819                 char *e;
1820
1821                 if (c->enclosing != 0)
1822                         return -ENXIO;
1823
1824                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1825                 if (!e) {
1826                         m->poisoned = true;
1827                         return -ENOMEM;
1828                 }
1829         }
1830
1831         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1832                 /* Variants are always aligned to 8 */
1833
1834                 if (!message_extend_body(m, 8, 0, false, false))
1835                         return -ENOMEM;
1836
1837         } else {
1838                 size_t l;
1839                 void *a;
1840
1841                 l = strlen(contents);
1842                 a = message_extend_body(m, 1, 1 + l + 1, false, false);
1843                 if (!a)
1844                         return -ENOMEM;
1845
1846                 *(uint8_t*) a = l;
1847                 memcpy((uint8_t*) a + 1, contents, l + 1);
1848         }
1849
1850         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1851                 c->index++;
1852
1853         return 0;
1854 }
1855
1856 static int bus_message_open_struct(
1857                 sd_bus_message *m,
1858                 struct bus_container *c,
1859                 const char *contents,
1860                 size_t *begin,
1861                 bool *need_offsets) {
1862
1863         size_t nindex;
1864         int r;
1865
1866         assert(m);
1867         assert(c);
1868         assert(contents);
1869         assert(begin);
1870         assert(need_offsets);
1871
1872         if (!signature_is_valid(contents, false))
1873                 return -EINVAL;
1874
1875         if (c->signature && c->signature[c->index]) {
1876                 size_t l;
1877
1878                 l = strlen(contents);
1879
1880                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1881                     !startswith(c->signature + c->index + 1, contents) ||
1882                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1883                         return -ENXIO;
1884
1885                 nindex = c->index + 1 + l + 1;
1886         } else {
1887                 char *e;
1888
1889                 if (c->enclosing != 0)
1890                         return -ENXIO;
1891
1892                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1893                 if (!e) {
1894                         m->poisoned = true;
1895                         return -ENOMEM;
1896                 }
1897
1898                 nindex = e - c->signature;
1899         }
1900
1901         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1902                 int alignment;
1903
1904                 alignment = bus_gvariant_get_alignment(contents);
1905                 if (alignment < 0)
1906                         return alignment;
1907
1908                 if (!message_extend_body(m, alignment, 0, false, false))
1909                         return -ENOMEM;
1910
1911                 r = bus_gvariant_is_fixed_size(contents);
1912                 if (r < 0)
1913                         return r;
1914
1915                 *begin = m->body_size;
1916                 *need_offsets = r == 0;
1917         } else {
1918                 /* Align contents to 8 byte boundary */
1919                 if (!message_extend_body(m, 8, 0, false, false))
1920                         return -ENOMEM;
1921         }
1922
1923         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1924                 c->index = nindex;
1925
1926         return 0;
1927 }
1928
1929 static int bus_message_open_dict_entry(
1930                 sd_bus_message *m,
1931                 struct bus_container *c,
1932                 const char *contents,
1933                 size_t *begin,
1934                 bool *need_offsets) {
1935
1936         int r;
1937
1938         assert(m);
1939         assert(c);
1940         assert(contents);
1941         assert(begin);
1942         assert(need_offsets);
1943
1944         if (!signature_is_pair(contents))
1945                 return -EINVAL;
1946
1947         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1948                 return -ENXIO;
1949
1950         if (c->signature && c->signature[c->index]) {
1951                 size_t l;
1952
1953                 l = strlen(contents);
1954
1955                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1956                     !startswith(c->signature + c->index + 1, contents) ||
1957                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1958                         return -ENXIO;
1959         } else
1960                 return -ENXIO;
1961
1962         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1963                 int alignment;
1964
1965                 alignment = bus_gvariant_get_alignment(contents);
1966                 if (alignment < 0)
1967                         return alignment;
1968
1969                 if (!message_extend_body(m, alignment, 0, false, false))
1970                         return -ENOMEM;
1971
1972                 r = bus_gvariant_is_fixed_size(contents);
1973                 if (r < 0)
1974                         return r;
1975
1976                 *begin = m->body_size;
1977                 *need_offsets = r == 0;
1978         } else {
1979                 /* Align contents to 8 byte boundary */
1980                 if (!message_extend_body(m, 8, 0, false, false))
1981                         return -ENOMEM;
1982         }
1983
1984         return 0;
1985 }
1986
1987 _public_ int sd_bus_message_open_container(
1988                 sd_bus_message *m,
1989                 char type,
1990                 const char *contents) {
1991
1992         struct bus_container *c, *w;
1993         uint32_t *array_size = NULL;
1994         char *signature;
1995         size_t before, begin = 0;
1996         bool need_offsets = false;
1997         int r;
1998
1999         assert_return(m, -EINVAL);
2000         assert_return(!m->sealed, -EPERM);
2001         assert_return(contents, -EINVAL);
2002         assert_return(!m->poisoned, -ESTALE);
2003
2004         /* Make sure we have space for one more container */
2005         if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
2006                 m->poisoned = true;
2007                 return -ENOMEM;
2008         }
2009
2010         c = message_get_container(m);
2011
2012         signature = strdup(contents);
2013         if (!signature) {
2014                 m->poisoned = true;
2015                 return -ENOMEM;
2016         }
2017
2018         /* Save old index in the parent container, in case we have to
2019          * abort this container */
2020         c->saved_index = c->index;
2021         before = m->body_size;
2022
2023         if (type == SD_BUS_TYPE_ARRAY)
2024                 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
2025         else if (type == SD_BUS_TYPE_VARIANT)
2026                 r = bus_message_open_variant(m, c, contents);
2027         else if (type == SD_BUS_TYPE_STRUCT)
2028                 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
2029         else if (type == SD_BUS_TYPE_DICT_ENTRY)
2030                 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
2031         else
2032                 r = -EINVAL;
2033
2034         if (r < 0) {
2035                 free(signature);
2036                 return r;
2037         }
2038
2039         /* OK, let's fill it in */
2040         w = m->containers + m->n_containers++;
2041         w->enclosing = type;
2042         w->signature = signature;
2043         w->index = 0;
2044         w->array_size = array_size;
2045         w->before = before;
2046         w->begin = begin;
2047         w->n_offsets = w->offsets_allocated = 0;
2048         w->offsets = NULL;
2049         w->need_offsets = need_offsets;
2050
2051         return 0;
2052 }
2053
2054 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
2055
2056         assert(m);
2057         assert(c);
2058
2059         if (!BUS_MESSAGE_IS_GVARIANT(m))
2060                 return 0;
2061
2062         if (c->need_offsets) {
2063                 size_t payload, sz, i;
2064                 uint8_t *a;
2065
2066                 /* Variable-width arrays */
2067
2068                 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
2069                 sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
2070
2071                 a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
2072                 if (!a)
2073                         return -ENOMEM;
2074
2075                 for (i = 0; i < c->n_offsets; i++)
2076                         bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
2077         } else {
2078                 void *a;
2079
2080                 /* Fixed-width or empty arrays */
2081
2082                 a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
2083                 if (!a)
2084                         return -ENOMEM;
2085         }
2086
2087         return 0;
2088 }
2089
2090 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
2091         uint8_t *a;
2092         size_t l;
2093
2094         assert(m);
2095         assert(c);
2096         assert(c->signature);
2097
2098         if (!BUS_MESSAGE_IS_GVARIANT(m))
2099                 return 0;
2100
2101         l = strlen(c->signature);
2102
2103         a = message_extend_body(m, 1, 1 + l, true, false);
2104         if (!a)
2105                 return -ENOMEM;
2106
2107         a[0] = 0;
2108         memcpy(a+1, c->signature, l);
2109
2110         return 0;
2111 }
2112
2113 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2114         bool fixed_size = true;
2115         size_t n_variable = 0;
2116         unsigned i = 0;
2117         const char *p;
2118         uint8_t *a;
2119         int r;
2120
2121         assert(m);
2122         assert(c);
2123
2124         if (!BUS_MESSAGE_IS_GVARIANT(m))
2125                 return 0;
2126
2127         p = strempty(c->signature);
2128         while (*p != 0) {
2129                 size_t n;
2130
2131                 r = signature_element_length(p, &n);
2132                 if (r < 0)
2133                         return r;
2134                 else {
2135                         char t[n+1];
2136
2137                         memcpy(t, p, n);
2138                         t[n] = 0;
2139
2140                         r = bus_gvariant_is_fixed_size(t);
2141                         if (r < 0)
2142                                 return r;
2143                 }
2144
2145                 assert(!c->need_offsets || i <= c->n_offsets);
2146
2147                 /* We need to add an offset for each item that has a
2148                  * variable size and that is not the last one in the
2149                  * list */
2150                 if (r == 0)
2151                         fixed_size = false;
2152                 if (r == 0 && p[n] != 0)
2153                         n_variable++;
2154
2155                 i++;
2156                 p += n;
2157         }
2158
2159         assert(!c->need_offsets || i == c->n_offsets);
2160         assert(c->need_offsets || n_variable == 0);
2161
2162         if (isempty(c->signature)) {
2163                 /* The unary type is encoded as fixed 1 byte padding */
2164                 a = message_extend_body(m, 1, 1, add_offset, false);
2165                 if (!a)
2166                         return -ENOMEM;
2167
2168                 *a = 0;
2169         } else if (n_variable <= 0) {
2170                 int alignment = 1;
2171
2172                 /* Structures with fixed-size members only have to be
2173                  * fixed-size themselves. But gvariant requires all fixed-size
2174                  * elements to be sized a multiple of their alignment. Hence,
2175                  * we must *always* add final padding after the last member so
2176                  * the overall size of the structure is properly aligned. */
2177                 if (fixed_size)
2178                         alignment = bus_gvariant_get_alignment(strempty(c->signature));
2179
2180                 assert(alignment > 0);
2181
2182                 a = message_extend_body(m, alignment, 0, add_offset, false);
2183                 if (!a)
2184                         return -ENOMEM;
2185         } else {
2186                 size_t sz;
2187                 unsigned j;
2188
2189                 assert(c->offsets[c->n_offsets-1] == m->body_size);
2190
2191                 sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
2192
2193                 a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
2194                 if (!a)
2195                         return -ENOMEM;
2196
2197                 p = strempty(c->signature);
2198                 for (i = 0, j = 0; i < c->n_offsets; i++) {
2199                         unsigned k;
2200                         size_t n;
2201
2202                         r = signature_element_length(p, &n);
2203                         if (r < 0)
2204                                 return r;
2205                         else {
2206                                 char t[n+1];
2207
2208                                 memcpy(t, p, n);
2209                                 t[n] = 0;
2210
2211                                 p += n;
2212
2213                                 r = bus_gvariant_is_fixed_size(t);
2214                                 if (r < 0)
2215                                         return r;
2216                                 if (r > 0 || p[0] == 0)
2217                                         continue;
2218                         }
2219
2220                         k = n_variable - 1 - j;
2221
2222                         bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2223
2224                         j++;
2225                 }
2226         }
2227
2228         return 0;
2229 }
2230
2231 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2232         struct bus_container *c;
2233         int r;
2234
2235         assert_return(m, -EINVAL);
2236         assert_return(!m->sealed, -EPERM);
2237         assert_return(m->n_containers > 0, -EINVAL);
2238         assert_return(!m->poisoned, -ESTALE);
2239
2240         c = message_get_container(m);
2241
2242         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2243                 if (c->signature && c->signature[c->index] != 0)
2244                         return -EINVAL;
2245
2246         m->n_containers--;
2247
2248         if (c->enclosing == SD_BUS_TYPE_ARRAY)
2249                 r = bus_message_close_array(m, c);
2250         else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2251                 r = bus_message_close_variant(m, c);
2252         else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY))
2253                 r = bus_message_close_struct(m, c, true);
2254         else
2255                 assert_not_reached("Unknown container type");
2256
2257         free(c->signature);
2258         free(c->offsets);
2259
2260         return r;
2261 }
2262
2263 typedef struct {
2264         const char *types;
2265         unsigned n_struct;
2266         unsigned n_array;
2267 } TypeStack;
2268
2269 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2270         assert(stack);
2271         assert(max > 0);
2272
2273         if (*i >= max)
2274                 return -EINVAL;
2275
2276         stack[*i].types = types;
2277         stack[*i].n_struct = n_struct;
2278         stack[*i].n_array = n_array;
2279         (*i)++;
2280
2281         return 0;
2282 }
2283
2284 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2285         assert(stack);
2286         assert(max > 0);
2287         assert(types);
2288         assert(n_struct);
2289         assert(n_array);
2290
2291         if (*i <= 0)
2292                 return 0;
2293
2294         (*i)--;
2295         *types = stack[*i].types;
2296         *n_struct = stack[*i].n_struct;
2297         *n_array = stack[*i].n_array;
2298
2299         return 1;
2300 }
2301
2302 _public_ int sd_bus_message_appendv(
2303                 sd_bus_message *m,
2304                 const char *types,
2305                 va_list ap) {
2306
2307         unsigned n_array, n_struct;
2308         TypeStack stack[BUS_CONTAINER_DEPTH];
2309         unsigned stack_ptr = 0;
2310         int r;
2311
2312         assert_return(m, -EINVAL);
2313         assert_return(types, -EINVAL);
2314         assert_return(!m->sealed, -EPERM);
2315         assert_return(!m->poisoned, -ESTALE);
2316
2317         n_array = (unsigned) -1;
2318         n_struct = strlen(types);
2319
2320         for (;;) {
2321                 const char *t;
2322
2323                 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2324                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2325                         if (r < 0)
2326                                 return r;
2327                         if (r == 0)
2328                                 break;
2329
2330                         r = sd_bus_message_close_container(m);
2331                         if (r < 0)
2332                                 return r;
2333
2334                         continue;
2335                 }
2336
2337                 t = types;
2338                 if (n_array != (unsigned) -1)
2339                         n_array--;
2340                 else {
2341                         types++;
2342                         n_struct--;
2343                 }
2344
2345                 switch (*t) {
2346
2347                 case SD_BUS_TYPE_BYTE: {
2348                         uint8_t x;
2349
2350                         x = (uint8_t) va_arg(ap, int);
2351                         r = sd_bus_message_append_basic(m, *t, &x);
2352                         break;
2353                 }
2354
2355                 case SD_BUS_TYPE_BOOLEAN:
2356                 case SD_BUS_TYPE_INT32:
2357                 case SD_BUS_TYPE_UINT32:
2358                 case SD_BUS_TYPE_UNIX_FD: {
2359                         uint32_t x;
2360
2361                         /* We assume a boolean is the same as int32_t */
2362                         assert_cc(sizeof(int32_t) == sizeof(int));
2363
2364                         x = va_arg(ap, uint32_t);
2365                         r = sd_bus_message_append_basic(m, *t, &x);
2366                         break;
2367                 }
2368
2369                 case SD_BUS_TYPE_INT16:
2370                 case SD_BUS_TYPE_UINT16: {
2371                         uint16_t x;
2372
2373                         x = (uint16_t) va_arg(ap, int);
2374                         r = sd_bus_message_append_basic(m, *t, &x);
2375                         break;
2376                 }
2377
2378                 case SD_BUS_TYPE_INT64:
2379                 case SD_BUS_TYPE_UINT64: {
2380                         uint64_t x;
2381
2382                         x = va_arg(ap, uint64_t);
2383                         r = sd_bus_message_append_basic(m, *t, &x);
2384                         break;
2385                 }
2386
2387                 case SD_BUS_TYPE_DOUBLE: {
2388                         double x;
2389
2390                         x = va_arg(ap, double);
2391                         r = sd_bus_message_append_basic(m, *t, &x);
2392                         break;
2393                 }
2394
2395                 case SD_BUS_TYPE_STRING:
2396                 case SD_BUS_TYPE_OBJECT_PATH:
2397                 case SD_BUS_TYPE_SIGNATURE: {
2398                         const char *x;
2399
2400                         x = va_arg(ap, const char*);
2401                         r = sd_bus_message_append_basic(m, *t, x);
2402                         break;
2403                 }
2404
2405                 case SD_BUS_TYPE_ARRAY: {
2406                         size_t k;
2407
2408                         r = signature_element_length(t + 1, &k);
2409                         if (r < 0)
2410                                 return r;
2411
2412                         {
2413                                 char s[k + 1];
2414                                 memcpy(s, t + 1, k);
2415                                 s[k] = 0;
2416
2417                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2418                                 if (r < 0)
2419                                         return r;
2420                         }
2421
2422                         if (n_array == (unsigned) -1) {
2423                                 types += k;
2424                                 n_struct -= k;
2425                         }
2426
2427                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2428                         if (r < 0)
2429                                 return r;
2430
2431                         types = t + 1;
2432                         n_struct = k;
2433                         n_array = va_arg(ap, unsigned);
2434
2435                         break;
2436                 }
2437
2438                 case SD_BUS_TYPE_VARIANT: {
2439                         const char *s;
2440
2441                         s = va_arg(ap, const char*);
2442                         if (!s)
2443                                 return -EINVAL;
2444
2445                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2446                         if (r < 0)
2447                                 return r;
2448
2449                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2450                         if (r < 0)
2451                                 return r;
2452
2453                         types = s;
2454                         n_struct = strlen(s);
2455                         n_array = (unsigned) -1;
2456
2457                         break;
2458                 }
2459
2460                 case SD_BUS_TYPE_STRUCT_BEGIN:
2461                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2462                         size_t k;
2463
2464                         r = signature_element_length(t, &k);
2465                         if (r < 0)
2466                                 return r;
2467
2468                         {
2469                                 char s[k - 1];
2470
2471                                 memcpy(s, t + 1, k - 2);
2472                                 s[k - 2] = 0;
2473
2474                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2475                                 if (r < 0)
2476                                         return r;
2477                         }
2478
2479                         if (n_array == (unsigned) -1) {
2480                                 types += k - 1;
2481                                 n_struct -= k - 1;
2482                         }
2483
2484                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2485                         if (r < 0)
2486                                 return r;
2487
2488                         types = t + 1;
2489                         n_struct = k - 2;
2490                         n_array = (unsigned) -1;
2491
2492                         break;
2493                 }
2494
2495                 default:
2496                         r = -EINVAL;
2497                 }
2498
2499                 if (r < 0)
2500                         return r;
2501         }
2502
2503         return 1;
2504 }
2505
2506 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2507         va_list ap;
2508         int r;
2509
2510         assert_return(m, -EINVAL);
2511         assert_return(types, -EINVAL);
2512         assert_return(!m->sealed, -EPERM);
2513         assert_return(!m->poisoned, -ESTALE);
2514
2515         va_start(ap, types);
2516         r = sd_bus_message_appendv(m, types, ap);
2517         va_end(ap);
2518
2519         return r;
2520 }
2521
2522 _public_ int sd_bus_message_append_array_space(
2523                 sd_bus_message *m,
2524                 char type,
2525                 size_t size,
2526                 void **ptr) {
2527
2528         ssize_t align, sz;
2529         void *a;
2530         int r;
2531
2532         assert_return(m, -EINVAL);
2533         assert_return(!m->sealed, -EPERM);
2534         assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2535         assert_return(ptr || size == 0, -EINVAL);
2536         assert_return(!m->poisoned, -ESTALE);
2537
2538         /* alignment and size of the trivial types (except bool) is
2539          * identical for gvariant and dbus1 marshalling */
2540         align = bus_type_get_alignment(type);
2541         sz = bus_type_get_size(type);
2542
2543         assert_se(align > 0);
2544         assert_se(sz > 0);
2545
2546         if (size % sz != 0)
2547                 return -EINVAL;
2548
2549         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2550         if (r < 0)
2551                 return r;
2552
2553         a = message_extend_body(m, align, size, false, false);
2554         if (!a)
2555                 return -ENOMEM;
2556
2557         r = sd_bus_message_close_container(m);
2558         if (r < 0)
2559                 return r;
2560
2561         *ptr = a;
2562         return 0;
2563 }
2564
2565 _public_ int sd_bus_message_append_array(
2566                 sd_bus_message *m,
2567                 char type,
2568                 const void *ptr,
2569                 size_t size) {
2570         int r;
2571         void *p;
2572
2573         assert_return(m, -EINVAL);
2574         assert_return(!m->sealed, -EPERM);
2575         assert_return(bus_type_is_trivial(type), -EINVAL);
2576         assert_return(ptr || size == 0, -EINVAL);
2577         assert_return(!m->poisoned, -ESTALE);
2578
2579         r = sd_bus_message_append_array_space(m, type, size, &p);
2580         if (r < 0)
2581                 return r;
2582
2583         memcpy_safe(p, ptr, size);
2584
2585         return 0;
2586 }
2587
2588 _public_ int sd_bus_message_append_array_iovec(
2589                 sd_bus_message *m,
2590                 char type,
2591                 const struct iovec *iov,
2592                 unsigned n) {
2593
2594         size_t size;
2595         unsigned i;
2596         void *p;
2597         int r;
2598
2599         assert_return(m, -EINVAL);
2600         assert_return(!m->sealed, -EPERM);
2601         assert_return(bus_type_is_trivial(type), -EINVAL);
2602         assert_return(iov || n == 0, -EINVAL);
2603         assert_return(!m->poisoned, -ESTALE);
2604
2605         size = IOVEC_TOTAL_SIZE(iov, n);
2606
2607         r = sd_bus_message_append_array_space(m, type, size, &p);
2608         if (r < 0)
2609                 return r;
2610
2611         for (i = 0; i < n; i++) {
2612
2613                 if (iov[i].iov_base)
2614                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
2615                 else
2616                         memzero(p, iov[i].iov_len);
2617
2618                 p = (uint8_t*) p + iov[i].iov_len;
2619         }
2620
2621         return 0;
2622 }
2623
2624 _public_ int sd_bus_message_append_array_memfd(
2625                 sd_bus_message *m,
2626                 char type,
2627                 int memfd,
2628                 uint64_t offset,
2629                 uint64_t size) {
2630
2631         _cleanup_close_ int copy_fd = -1;
2632         struct bus_body_part *part;
2633         ssize_t align, sz;
2634         uint64_t real_size;
2635         void *a;
2636         int r;
2637
2638         assert_return(m, -EINVAL);
2639         assert_return(memfd >= 0, -EBADF);
2640         assert_return(bus_type_is_trivial(type), -EINVAL);
2641         assert_return(size > 0, -EINVAL);
2642         assert_return(!m->sealed, -EPERM);
2643         assert_return(!m->poisoned, -ESTALE);
2644
2645         r = memfd_set_sealed(memfd);
2646         if (r < 0)
2647                 return r;
2648
2649         copy_fd = dup(memfd);
2650         if (copy_fd < 0)
2651                 return copy_fd;
2652
2653         r = memfd_get_size(memfd, &real_size);
2654         if (r < 0)
2655                 return r;
2656
2657         if (offset == 0 && size == (uint64_t) -1)
2658                 size = real_size;
2659         else if (offset + size > real_size)
2660                 return -EMSGSIZE;
2661
2662         align = bus_type_get_alignment(type);
2663         sz = bus_type_get_size(type);
2664
2665         assert_se(align > 0);
2666         assert_se(sz > 0);
2667
2668         if (offset % align != 0)
2669                 return -EINVAL;
2670
2671         if (size % sz != 0)
2672                 return -EINVAL;
2673
2674         if (size > (uint64_t) (uint32_t) -1)
2675                 return -EINVAL;
2676
2677         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2678         if (r < 0)
2679                 return r;
2680
2681         a = message_extend_body(m, align, 0, false, false);
2682         if (!a)
2683                 return -ENOMEM;
2684
2685         part = message_append_part(m);
2686         if (!part)
2687                 return -ENOMEM;
2688
2689         part->memfd = copy_fd;
2690         part->memfd_offset = offset;
2691         part->sealed = true;
2692         part->size = size;
2693         copy_fd = -1;
2694
2695         m->body_size += size;
2696         message_extend_containers(m, size);
2697
2698         return sd_bus_message_close_container(m);
2699 }
2700
2701 _public_ int sd_bus_message_append_string_memfd(
2702                 sd_bus_message *m,
2703                 int memfd,
2704                 uint64_t offset,
2705                 uint64_t size) {
2706
2707         _cleanup_close_ int copy_fd = -1;
2708         struct bus_body_part *part;
2709         struct bus_container *c;
2710         uint64_t real_size;
2711         void *a;
2712         int r;
2713
2714         assert_return(m, -EINVAL);
2715         assert_return(memfd >= 0, -EBADF);
2716         assert_return(size > 0, -EINVAL);
2717         assert_return(!m->sealed, -EPERM);
2718         assert_return(!m->poisoned, -ESTALE);
2719
2720         r = memfd_set_sealed(memfd);
2721         if (r < 0)
2722                 return r;
2723
2724         copy_fd = dup(memfd);
2725         if (copy_fd < 0)
2726                 return copy_fd;
2727
2728         r = memfd_get_size(memfd, &real_size);
2729         if (r < 0)
2730                 return r;
2731
2732         if (offset == 0 && size == (uint64_t) -1)
2733                 size = real_size;
2734         else if (offset + size > real_size)
2735                 return -EMSGSIZE;
2736
2737         /* We require this to be NUL terminated */
2738         if (size == 0)
2739                 return -EINVAL;
2740
2741         if (size > (uint64_t) (uint32_t) -1)
2742                 return -EINVAL;
2743
2744         c = message_get_container(m);
2745         if (c->signature && c->signature[c->index]) {
2746                 /* Container signature is already set */
2747
2748                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2749                         return -ENXIO;
2750         } else {
2751                 char *e;
2752
2753                 /* Maybe we can append to the signature? But only if this is the top-level container */
2754                 if (c->enclosing != 0)
2755                         return -ENXIO;
2756
2757                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2758                 if (!e) {
2759                         m->poisoned = true;
2760                         return -ENOMEM;
2761                 }
2762         }
2763
2764         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2765                 a = message_extend_body(m, 4, 4, false, false);
2766                 if (!a)
2767                         return -ENOMEM;
2768
2769                 *(uint32_t*) a = size - 1;
2770         }
2771
2772         part = message_append_part(m);
2773         if (!part)
2774                 return -ENOMEM;
2775
2776         part->memfd = copy_fd;
2777         part->memfd_offset = offset;
2778         part->sealed = true;
2779         part->size = size;
2780         copy_fd = -1;
2781
2782         m->body_size += size;
2783         message_extend_containers(m, size);
2784
2785         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2786                 r = message_add_offset(m, m->body_size);
2787                 if (r < 0) {
2788                         m->poisoned = true;
2789                         return -ENOMEM;
2790                 }
2791         }
2792
2793         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2794                 c->index++;
2795
2796         return 0;
2797 }
2798
2799 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2800         char **i;
2801         int r;
2802
2803         assert_return(m, -EINVAL);
2804         assert_return(!m->sealed, -EPERM);
2805         assert_return(!m->poisoned, -ESTALE);
2806
2807         r = sd_bus_message_open_container(m, 'a', "s");
2808         if (r < 0)
2809                 return r;
2810
2811         STRV_FOREACH(i, l) {
2812                 r = sd_bus_message_append_basic(m, 's', *i);
2813                 if (r < 0)
2814                         return r;
2815         }
2816
2817         return sd_bus_message_close_container(m);
2818 }
2819
2820 static int bus_message_close_header(sd_bus_message *m) {
2821
2822         assert(m);
2823
2824         /* The actual user data is finished now, we just complete the
2825            variant and struct now (at least on gvariant). Remember
2826            this position, so that during parsing we know where to
2827            put the outer container end. */
2828         m->user_body_size = m->body_size;
2829
2830         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2831                 const char *signature;
2832                 size_t sz, l;
2833                 void *d;
2834
2835                 /* Add offset table to end of fields array */
2836                 if (m->n_header_offsets >= 1) {
2837                         uint8_t *a;
2838                         unsigned i;
2839
2840                         assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
2841
2842                         sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
2843                         a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2844                         if (!a)
2845                                 return -ENOMEM;
2846
2847                         for (i = 0; i < m->n_header_offsets; i++)
2848                                 bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
2849                 }
2850
2851                 /* Add gvariant NUL byte plus signature to the end of
2852                  * the body, followed by the final offset pointing to
2853                  * the end of the fields array */
2854
2855                 signature = strempty(m->root_container.signature);
2856                 l = strlen(signature);
2857
2858                 sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
2859                 d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
2860                 if (!d)
2861                         return -ENOMEM;
2862
2863                 *(uint8_t*) d = 0;
2864                 *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
2865                 memcpy((uint8_t*) d + 2, signature, l);
2866                 *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
2867
2868                 bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
2869
2870                 m->footer = d;
2871                 m->footer_accessible = 1 + l + 2 + sz;
2872         } else {
2873                 m->header->dbus1.fields_size = m->fields_size;
2874                 m->header->dbus1.body_size = m->body_size;
2875         }
2876
2877         return 0;
2878 }
2879
2880 _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) {
2881         struct bus_body_part *part;
2882         size_t a;
2883         unsigned i;
2884         int r;
2885
2886         assert_return(m, -EINVAL);
2887
2888         if (m->sealed)
2889                 return -EPERM;
2890
2891         if (m->n_containers > 0)
2892                 return -EBADMSG;
2893
2894         if (m->poisoned)
2895                 return -ESTALE;
2896
2897         if (cookie > 0xffffffffULL &&
2898             !BUS_MESSAGE_IS_GVARIANT(m))
2899                 return -EOPNOTSUPP;
2900
2901         /* In vtables the return signature of method calls is listed,
2902          * let's check if they match if this is a response */
2903         if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2904             m->enforced_reply_signature &&
2905             !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2906                 return -ENOMSG;
2907
2908         /* If gvariant marshalling is used we need to close the body structure */
2909         r = bus_message_close_struct(m, &m->root_container, false);
2910         if (r < 0)
2911                 return r;
2912
2913         /* If there's a non-trivial signature set, then add it in
2914          * here, but only on dbus1 */
2915         if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
2916                 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2917                 if (r < 0)
2918                         return r;
2919         }
2920
2921         if (m->n_fds > 0) {
2922                 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2923                 if (r < 0)
2924                         return r;
2925         }
2926
2927         r = bus_message_close_header(m);
2928         if (r < 0)
2929                 return r;
2930
2931         if (BUS_MESSAGE_IS_GVARIANT(m))
2932                 m->header->dbus2.cookie = cookie;
2933         else
2934                 m->header->dbus1.serial = (uint32_t) cookie;
2935
2936         m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec;
2937
2938         /* Add padding at the end of the fields part, since we know
2939          * the body needs to start at an 8 byte alignment. We made
2940          * sure we allocated enough space for this, so all we need to
2941          * do here is to zero it out. */
2942         a = ALIGN8(m->fields_size) - m->fields_size;
2943         if (a > 0)
2944                 memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
2945
2946         /* If this is something we can send as memfd, then let's seal
2947         the memfd now. Note that we can send memfds as payload only
2948         for directed messages, and not for broadcasts. */
2949         if (m->destination && m->bus->use_memfd) {
2950                 MESSAGE_FOREACH_PART(part, i, m)
2951                         if (part->memfd >= 0 &&
2952                             !part->sealed &&
2953                             (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
2954                             part != m->body_end) { /* The last part may never be sent as memfd */
2955                                 uint64_t sz;
2956
2957                                 /* Try to seal it if that makes
2958                                  * sense. First, unmap our own map to
2959                                  * make sure we don't keep it busy. */
2960                                 bus_body_part_unmap(part);
2961
2962                                 /* Then, sync up real memfd size */
2963                                 sz = part->size;
2964                                 r = memfd_set_size(part->memfd, sz);
2965                                 if (r < 0)
2966                                         return r;
2967
2968                                 /* Finally, try to seal */
2969                                 if (memfd_set_sealed(part->memfd) >= 0)
2970                                         part->sealed = true;
2971                         }
2972         }
2973
2974         m->root_container.end = m->user_body_size;
2975         m->root_container.index = 0;
2976         m->root_container.offset_index = 0;
2977         m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2978
2979         m->sealed = true;
2980
2981         return 0;
2982 }
2983
2984 int bus_body_part_map(struct bus_body_part *part) {
2985         void *p;
2986         size_t psz, shift;
2987
2988         assert_se(part);
2989
2990         if (part->data)
2991                 return 0;
2992
2993         if (part->size <= 0)
2994                 return 0;
2995
2996         /* For smaller zero parts (as used for padding) we don't need to map anything... */
2997         if (part->memfd < 0 && part->is_zero && part->size < 8) {
2998                 static const uint8_t zeroes[7] = { };
2999                 part->data = (void*) zeroes;
3000                 return 0;
3001         }
3002
3003         shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
3004         psz = PAGE_ALIGN(part->size + shift);
3005
3006         if (part->memfd >= 0)
3007                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
3008         else if (part->is_zero)
3009                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
3010         else
3011                 return -EINVAL;
3012
3013         if (p == MAP_FAILED)
3014                 return -errno;
3015
3016         part->mapped = psz;
3017         part->mmap_begin = p;
3018         part->data = (uint8_t*) p + shift;
3019         part->munmap_this = true;
3020
3021         return 0;
3022 }
3023
3024 void bus_body_part_unmap(struct bus_body_part *part) {
3025
3026         assert_se(part);
3027
3028         if (part->memfd < 0)
3029                 return;
3030
3031         if (!part->mmap_begin)
3032                 return;
3033
3034         if (!part->munmap_this)
3035                 return;
3036
3037         assert_se(munmap(part->mmap_begin, part->mapped) == 0);
3038
3039         part->mmap_begin = NULL;
3040         part->data = NULL;
3041         part->mapped = 0;
3042         part->munmap_this = false;
3043
3044         return;
3045 }
3046
3047 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
3048         size_t k, start, end;
3049
3050         assert(rindex);
3051         assert(align > 0);
3052
3053         start = ALIGN_TO((size_t) *rindex, align);
3054         end = start + nbytes;
3055
3056         if (end > sz)
3057                 return -EBADMSG;
3058
3059         /* Verify that padding is 0 */
3060         for (k = *rindex; k < start; k++)
3061                 if (((const uint8_t*) p)[k] != 0)
3062                         return -EBADMSG;
3063
3064         if (r)
3065                 *r = (uint8_t*) p + start;
3066
3067         *rindex = end;
3068
3069         return 1;
3070 }
3071
3072 static bool message_end_of_signature(sd_bus_message *m) {
3073         struct bus_container *c;
3074
3075         assert(m);
3076
3077         c = message_get_container(m);
3078         return !c->signature || c->signature[c->index] == 0;
3079 }
3080
3081 static bool message_end_of_array(sd_bus_message *m, size_t index) {
3082         struct bus_container *c;
3083
3084         assert(m);
3085
3086         c = message_get_container(m);
3087         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3088                 return false;
3089
3090         if (BUS_MESSAGE_IS_GVARIANT(m))
3091                 return index >= c->end;
3092         else {
3093                 assert(c->array_size);
3094                 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
3095         }
3096 }
3097
3098 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
3099         assert_return(m, -EINVAL);
3100         assert_return(m->sealed, -EPERM);
3101
3102         if (complete && m->n_containers > 0)
3103                 return false;
3104
3105         if (message_end_of_signature(m))
3106                 return true;
3107
3108         if (message_end_of_array(m, m->rindex))
3109                 return true;
3110
3111         return false;
3112 }
3113
3114 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
3115         struct bus_body_part *part;
3116         size_t begin;
3117         int r;
3118
3119         assert(m);
3120
3121         if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
3122                 part = m->cached_rindex_part;
3123                 begin = m->cached_rindex_part_begin;
3124         } else {
3125                 part = &m->body;
3126                 begin = 0;
3127         }
3128
3129         while (part) {
3130                 if (index < begin)
3131                         return NULL;
3132
3133                 if (index + sz <= begin + part->size) {
3134
3135                         r = bus_body_part_map(part);
3136                         if (r < 0)
3137                                 return NULL;
3138
3139                         if (p)
3140                                 *p = (uint8_t*) part->data + index - begin;
3141
3142                         m->cached_rindex_part = part;
3143                         m->cached_rindex_part_begin = begin;
3144
3145                         return part;
3146                 }
3147
3148                 begin += part->size;
3149                 part = part->next;
3150         }
3151
3152         return NULL;
3153 }
3154
3155 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
3156         int r;
3157
3158         assert(m);
3159         assert(c);
3160         assert(rindex);
3161
3162         if (!BUS_MESSAGE_IS_GVARIANT(m))
3163                 return 0;
3164
3165         if (c->enclosing == SD_BUS_TYPE_ARRAY) {
3166                 int sz;
3167
3168                 sz = bus_gvariant_get_size(c->signature);
3169                 if (sz < 0) {
3170                         int alignment;
3171
3172                         if (c->offset_index+1 >= c->n_offsets)
3173                                 goto end;
3174
3175                         /* Variable-size array */
3176
3177                         alignment = bus_gvariant_get_alignment(c->signature);
3178                         assert(alignment > 0);
3179
3180                         *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3181                         c->item_size = c->offsets[c->offset_index+1] - *rindex;
3182                 } else {
3183
3184                         if (c->offset_index+1 >= (c->end-c->begin)/sz)
3185                                 goto end;
3186
3187                         /* Fixed-size array */
3188                         *rindex = c->begin + (c->offset_index+1) * sz;
3189                         c->item_size = sz;
3190                 }
3191
3192                 c->offset_index++;
3193
3194         } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
3195
3196                 int alignment;
3197                 size_t n, j;
3198
3199                 if (c->offset_index+1 >= c->n_offsets)
3200                         goto end;
3201
3202                 r = signature_element_length(c->signature + c->index, &n);
3203                 if (r < 0)
3204                         return r;
3205
3206                 r = signature_element_length(c->signature + c->index + n, &j);
3207                 if (r < 0)
3208                         return r;
3209                 else {
3210                         char t[j+1];
3211                         memcpy(t, c->signature + c->index + n, j);
3212                         t[j] = 0;
3213
3214                         alignment = bus_gvariant_get_alignment(t);
3215                 }
3216
3217                 assert(alignment > 0);
3218
3219                 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3220                 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3221
3222                 c->offset_index++;
3223
3224         } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3225                 goto end;
3226         else
3227                 assert_not_reached("Unknown container type");
3228
3229         return 0;
3230
3231 end:
3232         /* Reached the end */
3233         *rindex = c->end;
3234         c->item_size = 0;
3235         return 0;
3236 }
3237
3238
3239 static int message_peek_body(
3240                 sd_bus_message *m,
3241                 size_t *rindex,
3242                 size_t align,
3243                 size_t nbytes,
3244                 void **ret) {
3245
3246         size_t k, start, end, padding;
3247         struct bus_body_part *part;
3248         uint8_t *q;
3249
3250         assert(m);
3251         assert(rindex);
3252         assert(align > 0);
3253
3254         start = ALIGN_TO((size_t) *rindex, align);
3255         padding = start - *rindex;
3256         end = start + nbytes;
3257
3258         if (end > m->user_body_size)
3259                 return -EBADMSG;
3260
3261         part = find_part(m, *rindex, padding, (void**) &q);
3262         if (!part)
3263                 return -EBADMSG;
3264
3265         if (q) {
3266                 /* Verify padding */
3267                 for (k = 0; k < padding; k++)
3268                         if (q[k] != 0)
3269                                 return -EBADMSG;
3270         }
3271
3272         part = find_part(m, start, nbytes, (void**) &q);
3273         if (!part || (nbytes > 0 && !q))
3274                 return -EBADMSG;
3275
3276         *rindex = end;
3277
3278         if (ret)
3279                 *ret = q;
3280
3281         return 0;
3282 }
3283
3284 static bool validate_nul(const char *s, size_t l) {
3285
3286         /* Check for NUL chars in the string */
3287         if (memchr(s, 0, l))
3288                 return false;
3289
3290         /* Check for NUL termination */
3291         if (s[l] != 0)
3292                 return false;
3293
3294         return true;
3295 }
3296
3297 static bool validate_string(const char *s, size_t l) {
3298
3299         if (!validate_nul(s, l))
3300                 return false;
3301
3302         /* Check if valid UTF8 */
3303         if (!utf8_is_valid(s))
3304                 return false;
3305
3306         return true;
3307 }
3308
3309 static bool validate_signature(const char *s, size_t l) {
3310
3311         if (!validate_nul(s, l))
3312                 return false;
3313
3314         /* Check if valid signature */
3315         if (!signature_is_valid(s, true))
3316                 return false;
3317
3318         return true;
3319 }
3320
3321 static bool validate_object_path(const char *s, size_t l) {
3322
3323         if (!validate_nul(s, l))
3324                 return false;
3325
3326         if (!object_path_is_valid(s))
3327                 return false;
3328
3329         return true;
3330 }
3331
3332 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3333         struct bus_container *c;
3334         size_t rindex;
3335         void *q;
3336         int r;
3337
3338         assert_return(m, -EINVAL);
3339         assert_return(m->sealed, -EPERM);
3340         assert_return(bus_type_is_basic(type), -EINVAL);
3341
3342         if (message_end_of_signature(m))
3343                 return -ENXIO;
3344
3345         if (message_end_of_array(m, m->rindex))
3346                 return 0;
3347
3348         c = message_get_container(m);
3349         if (c->signature[c->index] != type)
3350                 return -ENXIO;
3351
3352         rindex = m->rindex;
3353
3354         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3355
3356                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3357                         bool ok;
3358
3359                         r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3360                         if (r < 0)
3361                                 return r;
3362
3363                         if (type == SD_BUS_TYPE_STRING)
3364                                 ok = validate_string(q, c->item_size-1);
3365                         else if (type == SD_BUS_TYPE_OBJECT_PATH)
3366                                 ok = validate_object_path(q, c->item_size-1);
3367                         else
3368                                 ok = validate_signature(q, c->item_size-1);
3369
3370                         if (!ok)
3371                                 return -EBADMSG;
3372
3373                         if (p)
3374                                 *(const char**) p = q;
3375                 } else {
3376                         int sz, align;
3377
3378                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3379                         assert(sz > 0);
3380                         if ((size_t) sz != c->item_size)
3381                                 return -EBADMSG;
3382
3383                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3384                         assert(align > 0);
3385
3386                         r = message_peek_body(m, &rindex, align, c->item_size, &q);
3387                         if (r < 0)
3388                                 return r;
3389
3390                         switch (type) {
3391
3392                         case SD_BUS_TYPE_BYTE:
3393                                 if (p)
3394                                         *(uint8_t*) p = *(uint8_t*) q;
3395                                 break;
3396
3397                         case SD_BUS_TYPE_BOOLEAN:
3398                                 if (p)
3399                                         *(int*) p = !!*(uint8_t*) q;
3400                                 break;
3401
3402                         case SD_BUS_TYPE_INT16:
3403                         case SD_BUS_TYPE_UINT16:
3404                                 if (p)
3405                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3406                                 break;
3407
3408                         case SD_BUS_TYPE_INT32:
3409                         case SD_BUS_TYPE_UINT32:
3410                                 if (p)
3411                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3412                                 break;
3413
3414                         case SD_BUS_TYPE_INT64:
3415                         case SD_BUS_TYPE_UINT64:
3416                         case SD_BUS_TYPE_DOUBLE:
3417                                 if (p)
3418                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3419                                 break;
3420
3421                         case SD_BUS_TYPE_UNIX_FD: {
3422                                 uint32_t j;
3423
3424                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3425                                 if (j >= m->n_fds)
3426                                         return -EBADMSG;
3427
3428                                 if (p)
3429                                         *(int*) p = m->fds[j];
3430
3431                                 break;
3432                         }
3433
3434                         default:
3435                                 assert_not_reached("unexpected type");
3436                         }
3437                 }
3438
3439                 r = container_next_item(m, c, &rindex);
3440                 if (r < 0)
3441                         return r;
3442         } else {
3443
3444                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3445                         uint32_t l;
3446                         bool ok;
3447
3448                         r = message_peek_body(m, &rindex, 4, 4, &q);
3449                         if (r < 0)
3450                                 return r;
3451
3452                         l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3453                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3454                         if (r < 0)
3455                                 return r;
3456
3457                         if (type == SD_BUS_TYPE_OBJECT_PATH)
3458                                 ok = validate_object_path(q, l);
3459                         else
3460                                 ok = validate_string(q, l);
3461                         if (!ok)
3462                                 return -EBADMSG;
3463
3464                         if (p)
3465                                 *(const char**) p = q;
3466
3467                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3468                         uint8_t l;
3469
3470                         r = message_peek_body(m, &rindex, 1, 1, &q);
3471                         if (r < 0)
3472                                 return r;
3473
3474                         l = *(uint8_t*) q;
3475                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3476                         if (r < 0)
3477                                 return r;
3478
3479                         if (!validate_signature(q, l))
3480                                 return -EBADMSG;
3481
3482                         if (p)
3483                                 *(const char**) p = q;
3484
3485                 } else {
3486                         ssize_t sz, align;
3487
3488                         align = bus_type_get_alignment(type);
3489                         assert(align > 0);
3490
3491                         sz = bus_type_get_size(type);
3492                         assert(sz > 0);
3493
3494                         r = message_peek_body(m, &rindex, align, sz, &q);
3495                         if (r < 0)
3496                                 return r;
3497
3498                         switch (type) {
3499
3500                         case SD_BUS_TYPE_BYTE:
3501                                 if (p)
3502                                         *(uint8_t*) p = *(uint8_t*) q;
3503                                 break;
3504
3505                         case SD_BUS_TYPE_BOOLEAN:
3506                                 if (p)
3507                                         *(int*) p = !!*(uint32_t*) q;
3508                                 break;
3509
3510                         case SD_BUS_TYPE_INT16:
3511                         case SD_BUS_TYPE_UINT16:
3512                                 if (p)
3513                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3514                                 break;
3515
3516                         case SD_BUS_TYPE_INT32:
3517                         case SD_BUS_TYPE_UINT32:
3518                                 if (p)
3519                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3520                                 break;
3521
3522                         case SD_BUS_TYPE_INT64:
3523                         case SD_BUS_TYPE_UINT64:
3524                         case SD_BUS_TYPE_DOUBLE:
3525                                 if (p)
3526                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3527                                 break;
3528
3529                         case SD_BUS_TYPE_UNIX_FD: {
3530                                 uint32_t j;
3531
3532                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3533                                 if (j >= m->n_fds)
3534                                         return -EBADMSG;
3535
3536                                 if (p)
3537                                         *(int*) p = m->fds[j];
3538                                 break;
3539                         }
3540
3541                         default:
3542                                 assert_not_reached("Unknown basic type...");
3543                         }
3544                 }
3545         }
3546
3547         m->rindex = rindex;
3548
3549         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3550                 c->index++;
3551
3552         return 1;
3553 }
3554
3555 static int bus_message_enter_array(
3556                 sd_bus_message *m,
3557                 struct bus_container *c,
3558                 const char *contents,
3559                 uint32_t **array_size,
3560                 size_t *item_size,
3561                 size_t **offsets,
3562                 size_t *n_offsets) {
3563
3564         size_t rindex;
3565         void *q;
3566         int r, alignment;
3567
3568         assert(m);
3569         assert(c);
3570         assert(contents);
3571         assert(array_size);
3572         assert(item_size);
3573         assert(offsets);
3574         assert(n_offsets);
3575
3576         if (!signature_is_single(contents, true))
3577                 return -EINVAL;
3578
3579         if (!c->signature || c->signature[c->index] == 0)
3580                 return -ENXIO;
3581
3582         if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3583                 return -ENXIO;
3584
3585         if (!startswith(c->signature + c->index + 1, contents))
3586                 return -ENXIO;
3587
3588         rindex = m->rindex;
3589
3590         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3591                 /* dbus1 */
3592
3593                 r = message_peek_body(m, &rindex, 4, 4, &q);
3594                 if (r < 0)
3595                         return r;
3596
3597                 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3598                         return -EBADMSG;
3599
3600                 alignment = bus_type_get_alignment(contents[0]);
3601                 if (alignment < 0)
3602                         return alignment;
3603
3604                 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3605                 if (r < 0)
3606                         return r;
3607
3608                 *array_size = (uint32_t*) q;
3609
3610         } else if (c->item_size <= 0) {
3611
3612                 /* gvariant: empty array */
3613                 *item_size = 0;
3614                 *offsets = NULL;
3615                 *n_offsets = 0;
3616
3617         } else if (bus_gvariant_is_fixed_size(contents)) {
3618
3619                 /* gvariant: fixed length array */
3620                 *item_size = bus_gvariant_get_size(contents);
3621                 *offsets = NULL;
3622                 *n_offsets = 0;
3623
3624         } else {
3625                 size_t where, p = 0, framing, sz;
3626                 unsigned i;
3627
3628                 /* gvariant: variable length array */
3629                 sz = bus_gvariant_determine_word_size(c->item_size, 0);
3630
3631                 where = rindex + c->item_size - sz;
3632                 r = message_peek_body(m, &where, 1, sz, &q);
3633                 if (r < 0)
3634                         return r;
3635
3636                 framing = bus_gvariant_read_word_le(q, sz);
3637                 if (framing > c->item_size - sz)
3638                         return -EBADMSG;
3639                 if ((c->item_size - framing) % sz != 0)
3640                         return -EBADMSG;
3641
3642                 *n_offsets = (c->item_size - framing) / sz;
3643
3644                 where = rindex + framing;
3645                 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3646                 if (r < 0)
3647                         return r;
3648
3649                 *offsets = new(size_t, *n_offsets);
3650                 if (!*offsets)
3651                         return -ENOMEM;
3652
3653                 for (i = 0; i < *n_offsets; i++) {
3654                         size_t x;
3655
3656                         x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
3657                         if (x > c->item_size - sz)
3658                                 return -EBADMSG;
3659                         if (x < p)
3660                                 return -EBADMSG;
3661
3662                         (*offsets)[i] = rindex + x;
3663                         p = x;
3664                 }
3665
3666                 *item_size = (*offsets)[0] - rindex;
3667         }
3668
3669         m->rindex = rindex;
3670
3671         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3672                 c->index += 1 + strlen(contents);
3673
3674         return 1;
3675 }
3676
3677 static int bus_message_enter_variant(
3678                 sd_bus_message *m,
3679                 struct bus_container *c,
3680                 const char *contents,
3681                 size_t *item_size) {
3682
3683         size_t rindex;
3684         uint8_t l;
3685         void *q;
3686         int r;
3687
3688         assert(m);
3689         assert(c);
3690         assert(contents);
3691         assert(item_size);
3692
3693         if (!signature_is_single(contents, false))
3694                 return -EINVAL;
3695
3696         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3697                 return -EINVAL;
3698
3699         if (!c->signature || c->signature[c->index] == 0)
3700                 return -ENXIO;
3701
3702         if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3703                 return -ENXIO;
3704
3705         rindex = m->rindex;
3706
3707         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3708                 size_t k, where;
3709
3710                 k = strlen(contents);
3711                 if (1+k > c->item_size)
3712                         return -EBADMSG;
3713
3714                 where = rindex + c->item_size - (1+k);
3715                 r = message_peek_body(m, &where, 1, 1+k, &q);
3716                 if (r < 0)
3717                         return r;
3718
3719                 if (*(char*) q != 0)
3720                         return -EBADMSG;
3721
3722                 if (memcmp((uint8_t*) q+1, contents, k))
3723                         return -ENXIO;
3724
3725                 *item_size = c->item_size - (1+k);
3726
3727         } else {
3728                 r = message_peek_body(m, &rindex, 1, 1, &q);
3729                 if (r < 0)
3730                         return r;
3731
3732                 l = *(uint8_t*) q;
3733                 r = message_peek_body(m, &rindex, 1, l+1, &q);
3734                 if (r < 0)
3735                         return r;
3736
3737                 if (!validate_signature(q, l))
3738                         return -EBADMSG;
3739
3740                 if (!streq(q, contents))
3741                         return -ENXIO;
3742         }
3743
3744         m->rindex = rindex;
3745
3746         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3747                 c->index++;
3748
3749         return 1;
3750 }
3751
3752 static int build_struct_offsets(
3753                 sd_bus_message *m,
3754                 const char *signature,
3755                 size_t size,
3756                 size_t *item_size,
3757                 size_t **offsets,
3758                 size_t *n_offsets) {
3759
3760         unsigned n_variable = 0, n_total = 0, v;
3761         size_t previous = 0, where;
3762         const char *p;
3763         size_t sz;
3764         void *q;
3765         int r;
3766
3767         assert(m);
3768         assert(item_size);
3769         assert(offsets);
3770         assert(n_offsets);
3771
3772         if (isempty(signature)) {
3773                 /* Unary type is encoded as *fixed* 1 byte padding */
3774                 r = message_peek_body(m, &m->rindex, 1, 1, &q);
3775                 if (r < 0)
3776                         return r;
3777
3778                 if (*(uint8_t *) q != 0)
3779                         return -EBADMSG;
3780
3781                 *item_size = 0;
3782                 *offsets = NULL;
3783                 *n_offsets = 0;
3784                 return 0;
3785         }
3786
3787         sz = bus_gvariant_determine_word_size(size, 0);
3788         if (sz <= 0)
3789                 return -EBADMSG;
3790
3791         /* First, loop over signature and count variable elements and
3792          * elements in general. We use this to know how large the
3793          * offset array is at the end of the structure. Note that
3794          * GVariant only stores offsets for all variable size elements
3795          * that are not the last item. */
3796
3797         p = signature;
3798         while (*p != 0) {
3799                 size_t n;
3800
3801                 r = signature_element_length(p, &n);
3802                 if (r < 0)
3803                         return r;
3804                 else {
3805                         char t[n+1];
3806
3807                         memcpy(t, p, n);
3808                         t[n] = 0;
3809
3810                         r = bus_gvariant_is_fixed_size(t);
3811                 }
3812
3813                 if (r < 0)
3814                         return r;
3815                 if (r == 0 && p[n] != 0) /* except the last item */
3816                         n_variable++;
3817                 n_total++;
3818
3819                 p += n;
3820         }
3821
3822         if (size < n_variable * sz)
3823                 return -EBADMSG;
3824
3825         where = m->rindex + size - (n_variable * sz);
3826         r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3827         if (r < 0)
3828                 return r;
3829
3830         v = n_variable;
3831
3832         *offsets = new(size_t, n_total);
3833         if (!*offsets)
3834                 return -ENOMEM;
3835
3836         *n_offsets = 0;
3837
3838         /* Second, loop again and build an offset table */
3839         p = signature;
3840         while (*p != 0) {
3841                 size_t n, offset;
3842                 int k;
3843
3844                 r = signature_element_length(p, &n);
3845                 if (r < 0)
3846                         return r;
3847                 else {
3848                         char t[n+1];
3849
3850                         memcpy(t, p, n);
3851                         t[n] = 0;
3852
3853                         k = bus_gvariant_get_size(t);
3854                         if (k < 0) {
3855                                 size_t x;
3856
3857                                 /* variable size */
3858                                 if (v > 0) {
3859                                         v--;
3860
3861                                         x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
3862                                         if (x >= size)
3863                                                 return -EBADMSG;
3864                                         if (m->rindex + x < previous)
3865                                                 return -EBADMSG;
3866                                 } else
3867                                         /* The last item's end
3868                                          * is determined from
3869                                          * the start of the
3870                                          * offset array */
3871                                         x = size - (n_variable * sz);
3872
3873                                 offset = m->rindex + x;
3874
3875                         } else {
3876                                 size_t align;
3877
3878                                 /* fixed size */
3879                                 align = bus_gvariant_get_alignment(t);
3880                                 assert(align > 0);
3881
3882                                 offset = (*n_offsets == 0 ? m->rindex  : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3883                         }
3884                 }
3885
3886                 previous = (*offsets)[(*n_offsets)++] = offset;
3887                 p += n;
3888         }
3889
3890         assert(v == 0);
3891         assert(*n_offsets == n_total);
3892
3893         *item_size = (*offsets)[0] - m->rindex;
3894         return 0;
3895 }
3896
3897 static int enter_struct_or_dict_entry(
3898                 sd_bus_message *m,
3899                 struct bus_container *c,
3900                 const char *contents,
3901                 size_t *item_size,
3902                 size_t **offsets,
3903                 size_t *n_offsets) {
3904
3905         int r;
3906
3907         assert(m);
3908         assert(c);
3909         assert(contents);
3910         assert(item_size);
3911         assert(offsets);
3912         assert(n_offsets);
3913
3914         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3915
3916                 /* dbus1 */
3917                 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
3918                 if (r < 0)
3919                         return r;
3920
3921         } else
3922                 /* gvariant with contents */
3923                 return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
3924
3925         return 0;
3926 }
3927
3928 static int bus_message_enter_struct(
3929                 sd_bus_message *m,
3930                 struct bus_container *c,
3931                 const char *contents,
3932                 size_t *item_size,
3933                 size_t **offsets,
3934                 size_t *n_offsets) {
3935
3936         size_t l;
3937         int r;
3938
3939         assert(m);
3940         assert(c);
3941         assert(contents);
3942         assert(item_size);
3943         assert(offsets);
3944         assert(n_offsets);
3945
3946         if (!signature_is_valid(contents, false))
3947                 return -EINVAL;
3948
3949         if (!c->signature || c->signature[c->index] == 0)
3950                 return -ENXIO;
3951
3952         l = strlen(contents);
3953
3954         if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
3955             !startswith(c->signature + c->index + 1, contents) ||
3956             c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
3957                 return -ENXIO;
3958
3959         r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
3960         if (r < 0)
3961                 return r;
3962
3963         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3964                 c->index += 1 + l + 1;
3965
3966         return 1;
3967 }
3968
3969 static int bus_message_enter_dict_entry(
3970                 sd_bus_message *m,
3971                 struct bus_container *c,
3972                 const char *contents,
3973                 size_t *item_size,
3974                 size_t **offsets,
3975                 size_t *n_offsets) {
3976
3977         size_t l;
3978         int r;
3979
3980         assert(m);
3981         assert(c);
3982         assert(contents);
3983
3984         if (!signature_is_pair(contents))
3985                 return -EINVAL;
3986
3987         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3988                 return -ENXIO;
3989
3990         if (!c->signature || c->signature[c->index] == 0)
3991                 return 0;
3992
3993         l = strlen(contents);
3994
3995         if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
3996             !startswith(c->signature + c->index + 1, contents) ||
3997             c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
3998                 return -ENXIO;
3999
4000         r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
4001         if (r < 0)
4002                 return r;
4003
4004         if (c->enclosing != SD_BUS_TYPE_ARRAY)
4005                 c->index += 1 + l + 1;
4006
4007         return 1;
4008 }
4009
4010 _public_ int sd_bus_message_enter_container(sd_bus_message *m,
4011                                             char type,
4012                                             const char *contents) {
4013         struct bus_container *c, *w;
4014         uint32_t *array_size = NULL;
4015         char *signature;
4016         size_t before;
4017         size_t *offsets = NULL;
4018         size_t n_offsets = 0, item_size = 0;
4019         int r;
4020
4021         assert_return(m, -EINVAL);
4022         assert_return(m->sealed, -EPERM);
4023         assert_return(type != 0 || !contents, -EINVAL);
4024
4025         if (type == 0 || !contents) {
4026                 const char *cc;
4027                 char tt;
4028
4029                 /* Allow entering into anonymous containers */
4030                 r = sd_bus_message_peek_type(m, &tt, &cc);
4031                 if (r < 0)
4032                         return r;
4033
4034                 if (type != 0 && type != tt)
4035                         return -ENXIO;
4036
4037                 if (contents && !streq(contents, cc))
4038                         return -ENXIO;
4039
4040                 type = tt;
4041                 contents = cc;
4042         }
4043
4044         /*
4045          * We enforce a global limit on container depth, that is much
4046          * higher than the 32 structs and 32 arrays the specification
4047          * mandates. This is simpler to implement for us, and we need
4048          * this only to ensure our container array doesn't grow
4049          * without bounds. We are happy to return any data from a
4050          * message as long as the data itself is valid, even if the
4051          * overall message might be not.
4052          *
4053          * Note that the message signature is validated when
4054          * parsing the headers, and that validation does check the
4055          * 32/32 limit.
4056          *
4057          * Note that the specification defines no limits on the depth
4058          * of stacked variants, but we do.
4059          */
4060         if (m->n_containers >= BUS_CONTAINER_DEPTH)
4061                 return -EBADMSG;
4062
4063         if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
4064                 return -ENOMEM;
4065
4066         if (message_end_of_signature(m))
4067                 return -ENXIO;
4068
4069         if (message_end_of_array(m, m->rindex))
4070                 return 0;
4071
4072         c = message_get_container(m);
4073
4074         signature = strdup(contents);
4075         if (!signature)
4076                 return -ENOMEM;
4077
4078         c->saved_index = c->index;
4079         before = m->rindex;
4080
4081         if (type == SD_BUS_TYPE_ARRAY)
4082                 r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
4083         else if (type == SD_BUS_TYPE_VARIANT)
4084                 r = bus_message_enter_variant(m, c, contents, &item_size);
4085         else if (type == SD_BUS_TYPE_STRUCT)
4086                 r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
4087         else if (type == SD_BUS_TYPE_DICT_ENTRY)
4088                 r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
4089         else
4090                 r = -EINVAL;
4091
4092         if (r <= 0) {
4093                 free(signature);
4094                 free(offsets);
4095                 return r;
4096         }
4097
4098         /* OK, let's fill it in */
4099         w = m->containers + m->n_containers++;
4100         w->enclosing = type;
4101         w->signature = signature;
4102         w->peeked_signature = NULL;
4103         w->index = 0;
4104
4105         w->before = before;
4106         w->begin = m->rindex;
4107
4108         /* Unary type has fixed size of 1, but virtual size of 0 */
4109         if (BUS_MESSAGE_IS_GVARIANT(m) &&
4110             type == SD_BUS_TYPE_STRUCT &&
4111             isempty(signature))
4112                 w->end = m->rindex + 0;
4113         else
4114                 w->end = m->rindex + c->item_size;
4115
4116         w->array_size = array_size;
4117         w->item_size = item_size;
4118         w->offsets = offsets;
4119         w->n_offsets = n_offsets;
4120         w->offset_index = 0;
4121
4122         return 1;
4123 }
4124
4125 _public_ int sd_bus_message_exit_container(sd_bus_message *m) {
4126         struct bus_container *c;
4127         unsigned saved;
4128         int r;
4129
4130         assert_return(m, -EINVAL);
4131         assert_return(m->sealed, -EPERM);
4132         assert_return(m->n_containers > 0, -ENXIO);
4133
4134         c = message_get_container(m);
4135
4136         if (c->enclosing != SD_BUS_TYPE_ARRAY) {
4137                 if (c->signature && c->signature[c->index] != 0)
4138                         return -EBUSY;
4139         }
4140
4141         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4142                 if (m->rindex < c->end)
4143                         return -EBUSY;
4144
4145         } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
4146                 uint32_t l;
4147
4148                 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4149                 if (c->begin + l != m->rindex)
4150                         return -EBUSY;
4151         }
4152
4153         free(c->signature);
4154         free(c->peeked_signature);
4155         free(c->offsets);
4156         m->n_containers--;
4157
4158         c = message_get_container(m);
4159
4160         saved = c->index;
4161         c->index = c->saved_index;
4162         r = container_next_item(m, c, &m->rindex);
4163         c->index = saved;
4164         if (r < 0)
4165                 return r;
4166
4167         return 1;
4168 }
4169
4170 static void message_quit_container(sd_bus_message *m) {
4171         struct bus_container *c;
4172
4173         assert(m);
4174         assert(m->sealed);
4175         assert(m->n_containers > 0);
4176
4177         c = message_get_container(m);
4178
4179         /* Undo seeks */
4180         assert(m->rindex >= c->before);
4181         m->rindex = c->before;
4182
4183         /* Free container */
4184         free(c->signature);
4185         free(c->offsets);
4186         m->n_containers--;
4187
4188         /* Correct index of new top-level container */
4189         c = message_get_container(m);
4190         c->index = c->saved_index;
4191 }
4192
4193 _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
4194         struct bus_container *c;
4195         int r;
4196
4197         assert_return(m, -EINVAL);
4198         assert_return(m->sealed, -EPERM);
4199
4200         if (message_end_of_signature(m))
4201                 goto eof;
4202
4203         if (message_end_of_array(m, m->rindex))
4204                 goto eof;
4205
4206         c = message_get_container(m);
4207
4208         if (bus_type_is_basic(c->signature[c->index])) {
4209                 if (contents)
4210                         *contents = NULL;
4211                 if (type)
4212                         *type = c->signature[c->index];
4213                 return 1;
4214         }
4215
4216         if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
4217
4218                 if (contents) {
4219                         size_t l;
4220                         char *sig;
4221
4222                         r = signature_element_length(c->signature+c->index+1, &l);
4223                         if (r < 0)
4224                                 return r;
4225
4226                         assert(l >= 1);
4227
4228                         sig = strndup(c->signature + c->index + 1, l);
4229                         if (!sig)
4230                                 return -ENOMEM;
4231
4232                         free(c->peeked_signature);
4233                         *contents = c->peeked_signature = sig;
4234                 }
4235
4236                 if (type)
4237                         *type = SD_BUS_TYPE_ARRAY;
4238
4239                 return 1;
4240         }
4241
4242         if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) {
4243
4244                 if (contents) {
4245                         size_t l;
4246                         char *sig;
4247
4248                         r = signature_element_length(c->signature+c->index, &l);
4249                         if (r < 0)
4250                                 return r;
4251
4252                         assert(l >= 2);
4253                         sig = strndup(c->signature + c->index + 1, l - 2);
4254                         if (!sig)
4255                                 return -ENOMEM;
4256
4257                         free(c->peeked_signature);
4258                         *contents = c->peeked_signature = sig;
4259                 }
4260
4261                 if (type)
4262                         *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
4263
4264                 return 1;
4265         }
4266
4267         if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
4268                 if (contents) {
4269                         void *q;
4270
4271                         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4272                                 size_t k;
4273
4274                                 if (c->item_size < 2)
4275                                         return -EBADMSG;
4276
4277                                 /* Look for the NUL delimiter that
4278                                    separates the payload from the
4279                                    signature. Since the body might be
4280                                    in a different part that then the
4281                                    signature we map byte by byte. */
4282
4283                                 for (k = 2; k <= c->item_size; k++) {
4284                                         size_t where;
4285
4286                                         where = m->rindex + c->item_size - k;
4287                                         r = message_peek_body(m, &where, 1, k, &q);
4288                                         if (r < 0)
4289                                                 return r;
4290
4291                                         if (*(char*) q == 0)
4292                                                 break;
4293                                 }
4294
4295                                 if (k > c->item_size)
4296                                         return -EBADMSG;
4297
4298                                 free(c->peeked_signature);
4299                                 c->peeked_signature = strndup((char*) q + 1, k - 1);
4300                                 if (!c->peeked_signature)
4301                                         return -ENOMEM;
4302
4303                                 if (!signature_is_valid(c->peeked_signature, true))
4304                                         return -EBADMSG;
4305
4306                                 *contents = c->peeked_signature;
4307                         } else {
4308                                 size_t rindex, l;
4309
4310                                 rindex = m->rindex;
4311                                 r = message_peek_body(m, &rindex, 1, 1, &q);
4312                                 if (r < 0)
4313                                         return r;
4314
4315                                 l = *(uint8_t*) q;
4316                                 r = message_peek_body(m, &rindex, 1, l+1, &q);
4317                                 if (r < 0)
4318                                         return r;
4319
4320                                 if (!validate_signature(q, l))
4321                                         return -EBADMSG;
4322
4323                                 *contents = q;
4324                         }
4325                 }
4326
4327                 if (type)
4328                         *type = SD_BUS_TYPE_VARIANT;
4329
4330                 return 1;
4331         }
4332
4333         return -EINVAL;
4334
4335 eof:
4336         if (type)
4337                 *type = 0;
4338         if (contents)
4339                 *contents = NULL;
4340         return 0;
4341 }
4342
4343 _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
4344         struct bus_container *c;
4345
4346         assert_return(m, -EINVAL);
4347         assert_return(m->sealed, -EPERM);
4348
4349         if (complete) {
4350                 message_reset_containers(m);
4351                 m->rindex = 0;
4352
4353                 c = message_get_container(m);
4354         } else {
4355                 c = message_get_container(m);
4356
4357                 c->offset_index = 0;
4358                 c->index = 0;
4359                 m->rindex = c->begin;
4360         }
4361
4362         c->offset_index = 0;
4363         c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
4364
4365         return !isempty(c->signature);
4366 }
4367
4368 static int message_read_ap(
4369                 sd_bus_message *m,
4370                 const char *types,
4371                 va_list ap) {
4372
4373         unsigned n_array, n_struct;
4374         TypeStack stack[BUS_CONTAINER_DEPTH];
4375         unsigned stack_ptr = 0;
4376         unsigned n_loop = 0;
4377         int r;
4378
4379         assert(m);
4380
4381         if (isempty(types))
4382                 return 0;
4383
4384         /* Ideally, we'd just call ourselves recursively on every
4385          * complex type. However, the state of a va_list that is
4386          * passed to a function is undefined after that function
4387          * returns. This means we need to docode the va_list linearly
4388          * in a single stackframe. We hence implement our own
4389          * home-grown stack in an array. */
4390
4391         n_array = (unsigned) -1; /* length of current array entries */
4392         n_struct = strlen(types); /* length of current struct contents signature */
4393
4394         for (;;) {
4395                 const char *t;
4396
4397                 n_loop++;
4398
4399                 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
4400                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
4401                         if (r < 0)
4402                                 return r;
4403                         if (r == 0)
4404                                 break;
4405
4406                         r = sd_bus_message_exit_container(m);
4407                         if (r < 0)
4408                                 return r;
4409
4410                         continue;
4411                 }
4412
4413                 t = types;
4414                 if (n_array != (unsigned) -1)
4415                         n_array--;
4416                 else {
4417                         types++;
4418                         n_struct--;
4419                 }
4420
4421                 switch (*t) {
4422
4423                 case SD_BUS_TYPE_BYTE:
4424                 case SD_BUS_TYPE_BOOLEAN:
4425                 case SD_BUS_TYPE_INT16:
4426                 case SD_BUS_TYPE_UINT16:
4427                 case SD_BUS_TYPE_INT32:
4428                 case SD_BUS_TYPE_UINT32:
4429                 case SD_BUS_TYPE_INT64:
4430                 case SD_BUS_TYPE_UINT64:
4431                 case SD_BUS_TYPE_DOUBLE:
4432                 case SD_BUS_TYPE_STRING:
4433                 case SD_BUS_TYPE_OBJECT_PATH:
4434                 case SD_BUS_TYPE_SIGNATURE:
4435                 case SD_BUS_TYPE_UNIX_FD: {
4436                         void *p;
4437
4438                         p = va_arg(ap, void*);
4439                         r = sd_bus_message_read_basic(m, *t, p);
4440                         if (r < 0)
4441                                 return r;
4442                         if (r == 0) {
4443                                 if (n_loop <= 1)
4444                                         return 0;
4445
4446                                 return -ENXIO;
4447                         }
4448
4449                         break;
4450                 }
4451
4452                 case SD_BUS_TYPE_ARRAY: {
4453                         size_t k;
4454
4455                         r = signature_element_length(t + 1, &k);
4456                         if (r < 0)
4457                                 return r;
4458
4459                         {
4460                                 char s[k + 1];
4461                                 memcpy(s, t + 1, k);
4462                                 s[k] = 0;
4463
4464                                 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4465                                 if (r < 0)
4466                                         return r;
4467                                 if (r == 0) {
4468                                         if (n_loop <= 1)
4469                                                 return 0;
4470
4471                                         return -ENXIO;
4472                                 }
4473                         }
4474
4475                         if (n_array == (unsigned) -1) {
4476                                 types += k;
4477                                 n_struct -= k;
4478                         }
4479
4480                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4481                         if (r < 0)
4482                                 return r;
4483
4484                         types = t + 1;
4485                         n_struct = k;
4486                         n_array = va_arg(ap, unsigned);
4487
4488                         break;
4489                 }
4490
4491                 case SD_BUS_TYPE_VARIANT: {
4492                         const char *s;
4493
4494                         s = va_arg(ap, const char *);
4495                         if (!s)
4496                                 return -EINVAL;
4497
4498                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
4499                         if (r < 0)
4500                                 return r;
4501                         if (r == 0) {
4502                                 if (n_loop <= 1)
4503                                         return 0;
4504
4505                                 return -ENXIO;
4506                         }
4507
4508                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4509                         if (r < 0)
4510                                 return r;
4511
4512                         types = s;
4513                         n_struct = strlen(s);
4514                         n_array = (unsigned) -1;
4515
4516                         break;
4517                 }
4518
4519                 case SD_BUS_TYPE_STRUCT_BEGIN:
4520                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4521                         size_t k;
4522
4523                         r = signature_element_length(t, &k);
4524                         if (r < 0)
4525                                 return r;
4526
4527                         {
4528                                 char s[k - 1];
4529                                 memcpy(s, t + 1, k - 2);
4530                                 s[k - 2] = 0;
4531
4532                                 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4533                                 if (r < 0)
4534                                         return r;
4535                                 if (r == 0) {
4536                                         if (n_loop <= 1)
4537                                                 return 0;
4538                                         return -ENXIO;
4539                                 }
4540                         }
4541
4542                         if (n_array == (unsigned) -1) {
4543                                 types += k - 1;
4544                                 n_struct -= k - 1;
4545                         }
4546
4547                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
4548                         if (r < 0)
4549                                 return r;
4550
4551                         types = t + 1;
4552                         n_struct = k - 2;
4553                         n_array = (unsigned) -1;
4554
4555                         break;
4556                 }
4557
4558                 default:
4559                         return -EINVAL;
4560                 }
4561         }
4562
4563         return 1;
4564 }
4565
4566 _public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
4567         va_list ap;
4568         int r;
4569
4570         assert_return(m, -EINVAL);
4571         assert_return(m->sealed, -EPERM);
4572         assert_return(types, -EINVAL);
4573
4574         va_start(ap, types);
4575         r = message_read_ap(m, types, ap);
4576         va_end(ap);
4577
4578         return r;
4579 }
4580
4581 _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
4582         int r;
4583
4584         assert_return(m, -EINVAL);
4585         assert_return(m->sealed, -EPERM);
4586
4587         /* If types is NULL, read exactly one element */
4588         if (!types) {
4589                 struct bus_container *c;
4590                 size_t l;
4591
4592                 if (message_end_of_signature(m))
4593                         return -ENXIO;
4594
4595                 if (message_end_of_array(m, m->rindex))
4596                         return 0;
4597
4598                 c = message_get_container(m);
4599
4600                 r = signature_element_length(c->signature + c->index, &l);
4601                 if (r < 0)
4602                         return r;
4603
4604                 types = strndupa(c->signature + c->index, l);
4605         }
4606
4607         switch (*types) {
4608
4609         case 0: /* Nothing to drop */
4610                 return 0;
4611
4612         case SD_BUS_TYPE_BYTE:
4613         case SD_BUS_TYPE_BOOLEAN:
4614         case SD_BUS_TYPE_INT16:
4615         case SD_BUS_TYPE_UINT16:
4616         case SD_BUS_TYPE_INT32:
4617         case SD_BUS_TYPE_UINT32:
4618         case SD_BUS_TYPE_INT64:
4619         case SD_BUS_TYPE_UINT64:
4620         case SD_BUS_TYPE_DOUBLE:
4621         case SD_BUS_TYPE_STRING:
4622         case SD_BUS_TYPE_OBJECT_PATH:
4623         case SD_BUS_TYPE_SIGNATURE:
4624         case SD_BUS_TYPE_UNIX_FD:
4625
4626                 r = sd_bus_message_read_basic(m, *types, NULL);
4627                 if (r <= 0)
4628                         return r;
4629
4630                 r = sd_bus_message_skip(m, types + 1);
4631                 if (r < 0)
4632                         return r;
4633
4634                 return 1;
4635
4636         case SD_BUS_TYPE_ARRAY: {
4637                 size_t k;
4638
4639                 r = signature_element_length(types + 1, &k);
4640                 if (r < 0)
4641                         return r;
4642
4643                 {
4644                         char s[k+1];
4645                         memcpy(s, types+1, k);
4646                         s[k] = 0;
4647
4648                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
4649                         if (r <= 0)
4650                                 return r;
4651
4652                         for (;;) {
4653                                 r = sd_bus_message_skip(m, s);
4654                                 if (r < 0)
4655                                         return r;
4656                                 if (r == 0)
4657                                         break;
4658                         }
4659
4660                         r = sd_bus_message_exit_container(m);
4661                         if (r < 0)
4662                                 return r;
4663                 }
4664
4665                 r = sd_bus_message_skip(m, types + 1 + k);
4666                 if (r < 0)
4667                         return r;
4668
4669                 return 1;
4670         }
4671
4672         case SD_BUS_TYPE_VARIANT: {
4673                 const char *contents;
4674                 char x;
4675
4676                 r = sd_bus_message_peek_type(m, &x, &contents);
4677                 if (r <= 0)
4678                         return r;
4679
4680                 if (x != SD_BUS_TYPE_VARIANT)
4681                         return -ENXIO;
4682
4683                 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
4684                 if (r <= 0)
4685                         return r;
4686
4687                 r = sd_bus_message_skip(m, contents);
4688                 if (r < 0)
4689                         return r;
4690                 assert(r != 0);
4691
4692                 r = sd_bus_message_exit_container(m);
4693                 if (r < 0)
4694                         return r;
4695
4696                 r = sd_bus_message_skip(m, types + 1);
4697                 if (r < 0)
4698                         return r;
4699
4700                 return 1;
4701         }
4702
4703         case SD_BUS_TYPE_STRUCT_BEGIN:
4704         case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
4705                 size_t k;
4706
4707                 r = signature_element_length(types, &k);
4708                 if (r < 0)
4709                         return r;
4710
4711                 {
4712                         char s[k-1];
4713                         memcpy(s, types+1, k-2);
4714                         s[k-2] = 0;
4715
4716                         r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
4717                         if (r <= 0)
4718                                 return r;
4719
4720                         r = sd_bus_message_skip(m, s);
4721                         if (r < 0)
4722                                 return r;
4723
4724                         r = sd_bus_message_exit_container(m);
4725                         if (r < 0)
4726                                 return r;
4727                 }
4728
4729                 r = sd_bus_message_skip(m, types + k);
4730                 if (r < 0)
4731                         return r;
4732
4733                 return 1;
4734         }
4735
4736         default:
4737                 return -EINVAL;
4738         }
4739 }
4740
4741 _public_ int sd_bus_message_read_array(
4742                 sd_bus_message *m,
4743                 char type,
4744                 const void **ptr,
4745                 size_t *size) {
4746
4747         struct bus_container *c;
4748         void *p;
4749         size_t sz;
4750         ssize_t align;
4751         int r;
4752
4753         assert_return(m, -EINVAL);
4754         assert_return(m->sealed, -EPERM);
4755         assert_return(bus_type_is_trivial(type), -EINVAL);
4756         assert_return(ptr, -EINVAL);
4757         assert_return(size, -EINVAL);
4758         assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
4759
4760         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
4761         if (r <= 0)
4762                 return r;
4763
4764         c = message_get_container(m);
4765
4766         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4767                 align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
4768                 if (align < 0)
4769                         return align;
4770
4771                 sz = c->end - c->begin;
4772         } else {
4773                 align = bus_type_get_alignment(type);
4774                 if (align < 0)
4775                         return align;
4776
4777                 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
4778         }
4779
4780         if (sz == 0)
4781                 /* Zero length array, let's return some aligned
4782                  * pointer that is not NULL */
4783                 p = (uint8_t*) align;
4784         else {
4785                 r = message_peek_body(m, &m->rindex, align, sz, &p);
4786                 if (r < 0)
4787                         goto fail;
4788         }
4789
4790         r = sd_bus_message_exit_container(m);
4791         if (r < 0)
4792                 goto fail;
4793
4794         *ptr = (const void*) p;
4795         *size = sz;
4796
4797         return 1;
4798
4799 fail:
4800         message_quit_container(m);
4801         return r;
4802 }
4803
4804 static int message_peek_fields(
4805                 sd_bus_message *m,
4806                 size_t *rindex,
4807                 size_t align,
4808                 size_t nbytes,
4809                 void **ret) {
4810
4811         assert(m);
4812         assert(rindex);
4813         assert(align > 0);
4814
4815         return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
4816 }
4817
4818 static int message_peek_field_uint32(
4819                 sd_bus_message *m,
4820                 size_t *ri,
4821                 size_t item_size,
4822                 uint32_t *ret) {
4823
4824         int r;
4825         void *q;
4826
4827         assert(m);
4828         assert(ri);
4829
4830         if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
4831                 return -EBADMSG;
4832
4833         /* identical for gvariant and dbus1 */
4834
4835         r = message_peek_fields(m, ri, 4, 4, &q);
4836         if (r < 0)
4837                 return r;
4838
4839         if (ret)
4840                 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
4841
4842         return 0;
4843 }
4844
4845 static int message_peek_field_uint64(
4846                 sd_bus_message *m,
4847                 size_t *ri,
4848                 size_t item_size,
4849                 uint64_t *ret) {
4850
4851         int r;
4852         void *q;
4853
4854         assert(m);
4855         assert(ri);
4856
4857         if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
4858                 return -EBADMSG;
4859
4860         /* identical for gvariant and dbus1 */
4861
4862         r = message_peek_fields(m, ri, 8, 8, &q);
4863         if (r < 0)
4864                 return r;
4865
4866         if (ret)
4867                 *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
4868
4869         return 0;
4870 }
4871
4872 static int message_peek_field_string(
4873                 sd_bus_message *m,
4874                 bool (*validate)(const char *p),
4875                 size_t *ri,
4876                 size_t item_size,
4877                 const char **ret) {
4878
4879         uint32_t l;
4880         int r;
4881         void *q;
4882
4883         assert(m);
4884         assert(ri);
4885
4886         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4887
4888                 if (item_size <= 0)
4889                         return -EBADMSG;
4890
4891                 r = message_peek_fields(m, ri, 1, item_size, &q);
4892                 if (r < 0)
4893                         return r;
4894
4895                 l = item_size - 1;
4896         } else {
4897                 r = message_peek_field_uint32(m, ri, 4, &l);
4898                 if (r < 0)
4899                         return r;
4900
4901                 r = message_peek_fields(m, ri, 1, l+1, &q);
4902                 if (r < 0)
4903                         return r;
4904         }
4905
4906         if (validate) {
4907                 if (!validate_nul(q, l))
4908                         return -EBADMSG;
4909
4910                 if (!validate(q))
4911                         return -EBADMSG;
4912         } else {
4913                 if (!validate_string(q, l))
4914                         return -EBADMSG;
4915         }
4916
4917         if (ret)
4918                 *ret = q;
4919
4920         return 0;
4921 }
4922
4923 static int message_peek_field_signature(
4924                 sd_bus_message *m,
4925                 size_t *ri,
4926                 size_t item_size,
4927                 const char **ret) {
4928
4929         size_t l;
4930         int r;
4931         void *q;
4932
4933         assert(m);
4934         assert(ri);
4935
4936         if (BUS_MESSAGE_IS_GVARIANT(m)) {
4937
4938                 if (item_size <= 0)
4939                         return -EBADMSG;
4940
4941                 r = message_peek_fields(m, ri, 1, item_size, &q);
4942                 if (r < 0)
4943                         return r;
4944
4945                 l = item_size - 1;
4946         } else {
4947                 r = message_peek_fields(m, ri, 1, 1, &q);
4948                 if (r < 0)
4949                         return r;
4950
4951                 l = *(uint8_t*) q;
4952                 r = message_peek_fields(m, ri, 1, l+1, &q);
4953                 if (r < 0)
4954                         return r;
4955         }
4956
4957         if (!validate_signature(q, l))
4958                 return -EBADMSG;
4959
4960         if (ret)
4961                 *ret = q;
4962
4963         return 0;
4964 }
4965
4966 static int message_skip_fields(
4967                 sd_bus_message *m,
4968                 size_t *ri,
4969                 uint32_t array_size,
4970                 const char **signature) {
4971
4972         size_t original_index;
4973         int r;
4974
4975         assert(m);
4976         assert(ri);
4977         assert(signature);
4978         assert(!BUS_MESSAGE_IS_GVARIANT(m));
4979
4980         original_index = *ri;
4981
4982         for (;;) {
4983                 char t;
4984                 size_t l;
4985
4986                 if (array_size != (uint32_t) -1 &&
4987                     array_size <= *ri - original_index)
4988                         return 0;
4989
4990                 t = **signature;
4991                 if (!t)
4992                         return 0;
4993
4994                 if (t == SD_BUS_TYPE_STRING) {
4995
4996                         r = message_peek_field_string(m, NULL, ri, 0, NULL);
4997                         if (r < 0)
4998                                 return r;
4999
5000                         (*signature)++;
5001
5002                 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
5003
5004                         r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
5005                         if (r < 0)
5006                                 return r;
5007
5008                         (*signature)++;
5009
5010                 } else if (t == SD_BUS_TYPE_SIGNATURE) {
5011
5012                         r = message_peek_field_signature(m, ri, 0, NULL);
5013                         if (r < 0)
5014                                 return r;
5015
5016                         (*signature)++;
5017
5018                 } else if (bus_type_is_basic(t)) {
5019                         ssize_t align, k;
5020
5021                         align = bus_type_get_alignment(t);
5022                         k = bus_type_get_size(t);
5023                         assert(align > 0 && k > 0);
5024
5025                         r = message_peek_fields(m, ri, align, k, NULL);
5026                         if (r < 0)
5027                                 return r;
5028
5029                         (*signature)++;
5030
5031                 } else if (t == SD_BUS_TYPE_ARRAY) {
5032
5033                         r = signature_element_length(*signature+1, &l);
5034                         if (r < 0)
5035                                 return r;
5036
5037                         assert(l >= 1);
5038                         {
5039                                 char sig[l-1], *s;
5040                                 uint32_t nas;
5041                                 int alignment;
5042
5043                                 strncpy(sig, *signature + 1, l-1);
5044                                 s = sig;
5045
5046                                 alignment = bus_type_get_alignment(sig[0]);
5047                                 if (alignment < 0)
5048                                         return alignment;
5049
5050                                 r = message_peek_field_uint32(m, ri, 0, &nas);
5051                                 if (r < 0)
5052                                         return r;
5053                                 if (nas > BUS_ARRAY_MAX_SIZE)
5054                                         return -EBADMSG;
5055
5056                                 r = message_peek_fields(m, ri, alignment, 0, NULL);
5057                                 if (r < 0)
5058                                         return r;
5059
5060                                 r = message_skip_fields(m, ri, nas, (const char**) &s);
5061                                 if (r < 0)
5062                                         return r;
5063                         }
5064
5065                         (*signature) += 1 + l;
5066
5067                 } else if (t == SD_BUS_TYPE_VARIANT) {
5068                         const char *s;
5069
5070                         r = message_peek_field_signature(m, ri, 0, &s);
5071                         if (r < 0)
5072                                 return r;
5073
5074                         r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5075                         if (r < 0)
5076                                 return r;
5077
5078                         (*signature)++;
5079
5080                 } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) {
5081
5082                         r = signature_element_length(*signature, &l);
5083                         if (r < 0)
5084                                 return r;
5085
5086                         assert(l >= 2);
5087                         {
5088                                 char sig[l-1], *s;
5089                                 strncpy(sig, *signature + 1, l-1);
5090                                 s = sig;
5091
5092                                 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
5093                                 if (r < 0)
5094                                         return r;
5095                         }
5096
5097                         *signature += l;
5098                 } else
5099                         return -EINVAL;
5100         }
5101 }
5102
5103 int bus_message_parse_fields(sd_bus_message *m) {
5104         size_t ri;
5105         int r;
5106         uint32_t unix_fds = 0;
5107         bool unix_fds_set = false;
5108         void *offsets = NULL;
5109         unsigned n_offsets = 0;
5110         size_t sz = 0;
5111         unsigned i = 0;
5112
5113         assert(m);
5114
5115         if (BUS_MESSAGE_IS_GVARIANT(m)) {
5116                 char *p;
5117
5118                 /* Read the signature from the end of the body variant first */
5119                 sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
5120                 if (m->footer_accessible < 1 + sz)
5121                         return -EBADMSG;
5122
5123                 p = (char*) m->footer + m->footer_accessible - (1 + sz);
5124                 for (;;) {
5125                         if (p < (char*) m->footer)
5126                                 return -EBADMSG;
5127
5128                         if (*p == 0) {
5129                                 size_t l;
5130                                 char *c;
5131
5132                                 /* We found the beginning of the signature
5133                                  * string, yay! We require the body to be a
5134                                  * structure, so verify it and then strip the
5135                                  * opening/closing brackets. */
5136
5137                                 l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
5138                                 if (l < 2 ||
5139                                     p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
5140                                     p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
5141                                         return -EBADMSG;
5142
5143                                 c = strndup(p + 1 + 1, l - 2);
5144                                 if (!c)
5145                                         return -ENOMEM;
5146
5147                                 free(m->root_container.signature);
5148                                 m->root_container.signature = c;
5149                                 break;
5150                         }
5151
5152                         p--;
5153                 }
5154
5155                 /* Calculate the actual user body size, by removing
5156                  * the trailing variant signature and struct offset
5157                  * table */
5158                 m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
5159
5160                 /* Pull out the offset table for the fields array */
5161                 sz = bus_gvariant_determine_word_size(m->fields_size, 0);
5162                 if (sz > 0) {
5163                         size_t framing;
5164                         void *q;
5165
5166                         ri = m->fields_size - sz;
5167                         r = message_peek_fields(m, &ri, 1, sz, &q);
5168                         if (r < 0)
5169                                 return r;
5170
5171                         framing = bus_gvariant_read_word_le(q, sz);
5172                         if (framing >= m->fields_size - sz)
5173                                 return -EBADMSG;
5174                         if ((m->fields_size - framing) % sz != 0)
5175                                 return -EBADMSG;
5176
5177                         ri = framing;
5178                         r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
5179                         if (r < 0)
5180                                 return r;
5181
5182                         n_offsets = (m->fields_size - framing) / sz;
5183                 }
5184         } else
5185                 m->user_body_size = m->body_size;
5186
5187         ri = 0;
5188         while (ri < m->fields_size) {
5189                 _cleanup_free_ char *sig = NULL;
5190                 const char *signature;
5191                 uint64_t field_type;
5192                 size_t item_size = (size_t) -1;
5193
5194                 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5195                         uint64_t *u64;
5196
5197                         if (i >= n_offsets)
5198                                 break;
5199
5200                         if (i == 0)
5201                                 ri = 0;
5202                         else
5203                                 ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
5204
5205                         r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
5206                         if (r < 0)
5207                                 return r;
5208
5209                         field_type = BUS_MESSAGE_BSWAP64(m, *u64);
5210                 } else {
5211                         uint8_t *u8;
5212
5213                         r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
5214                         if (r < 0)
5215                                 return r;
5216
5217                         field_type = *u8;
5218                 }
5219
5220                 if (BUS_MESSAGE_IS_GVARIANT(m)) {
5221                         size_t where, end;
5222                         char *b;
5223                         void *q;
5224
5225                         end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
5226
5227                         if (end < ri)
5228                                 return -EBADMSG;
5229
5230                         where = ri = ALIGN_TO(ri, 8);
5231                         item_size = end - ri;
5232                         r = message_peek_fields(m, &where, 1, item_size, &q);
5233                         if (r < 0)
5234                                 return r;
5235
5236                         b = memrchr(q, 0, item_size);
5237                         if (!b)
5238                                 return -EBADMSG;
5239
5240                         sig = strndup(b+1, item_size - (b+1-(char*) q));
5241                         if (!sig)
5242                                 return -ENOMEM;
5243
5244                         signature = sig;
5245                         item_size = b - (char*) q;
5246                 } else {
5247                         r = message_peek_field_signature(m, &ri, 0, &signature);
5248                         if (r < 0)
5249                                 return r;
5250                 }
5251
5252                 switch (field_type) {
5253
5254                 case _BUS_MESSAGE_HEADER_INVALID:
5255                         return -EBADMSG;
5256
5257                 case BUS_MESSAGE_HEADER_PATH:
5258
5259                         if (m->path)
5260                                 return -EBADMSG;
5261
5262                         if (!streq(signature, "o"))
5263                                 return -EBADMSG;
5264
5265                         r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
5266                         break;
5267
5268                 case BUS_MESSAGE_HEADER_INTERFACE:
5269
5270                         if (m->interface)
5271                                 return -EBADMSG;
5272
5273                         if (!streq(signature, "s"))
5274                                 return -EBADMSG;
5275
5276                         r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
5277                         break;
5278
5279                 case BUS_MESSAGE_HEADER_MEMBER:
5280
5281                         if (m->member)
5282                                 return -EBADMSG;
5283
5284                         if (!streq(signature, "s"))
5285                                 return -EBADMSG;
5286
5287                         r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
5288                         break;
5289
5290                 case BUS_MESSAGE_HEADER_ERROR_NAME:
5291
5292                         if (m->error.name)
5293                                 return -EBADMSG;
5294
5295                         if (!streq(signature, "s"))
5296                                 return -EBADMSG;
5297
5298                         r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
5299                         if (r >= 0)
5300                                 m->error._need_free = -1;
5301
5302                         break;
5303
5304                 case BUS_MESSAGE_HEADER_DESTINATION:
5305
5306                         if (m->destination)
5307                                 return -EBADMSG;
5308
5309                         if (!streq(signature, "s"))
5310                                 return -EBADMSG;
5311
5312                         r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
5313                         break;
5314
5315                 case BUS_MESSAGE_HEADER_SENDER:
5316
5317                         if (m->sender)
5318                                 return -EBADMSG;
5319
5320                         if (!streq(signature, "s"))
5321                                 return -EBADMSG;
5322
5323                         r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
5324
5325                         if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) {
5326                                 m->creds.unique_name = (char*) m->sender;
5327                                 m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
5328                         }
5329
5330                         break;
5331
5332
5333                 case BUS_MESSAGE_HEADER_SIGNATURE: {
5334                         const char *s;
5335                         char *c;
5336
5337                         if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
5338                                 return -EBADMSG;
5339
5340                         if (m->root_container.signature)
5341                                 return -EBADMSG;
5342
5343                         if (!streq(signature, "g"))
5344                                 return -EBADMSG;
5345
5346                         r = message_peek_field_signature(m, &ri, item_size, &s);
5347                         if (r < 0)
5348                                 return r;
5349
5350                         c = strdup(s);
5351                         if (!c)
5352                                 return -ENOMEM;
5353
5354                         free(m->root_container.signature);
5355                         m->root_container.signature = c;
5356                         break;
5357                 }
5358
5359                 case BUS_MESSAGE_HEADER_REPLY_SERIAL:
5360
5361                         if (m->reply_cookie != 0)
5362                                 return -EBADMSG;
5363
5364                         if (BUS_MESSAGE_IS_GVARIANT(m)) {
5365                                 /* 64bit on dbus2 */
5366
5367                                 if (!streq(signature, "t"))
5368                                         return -EBADMSG;
5369
5370                                 r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
5371                                 if (r < 0)
5372                                         return r;
5373                         } else {
5374                                 /* 32bit on dbus1 */
5375                                 uint32_t serial;
5376
5377                                 if (!streq(signature, "u"))
5378                                         return -EBADMSG;
5379
5380                                 r = message_peek_field_uint32(m, &ri, item_size, &serial);
5381                                 if (r < 0)
5382                                         return r;
5383
5384                                 m->reply_cookie = serial;
5385                         }
5386
5387                         if (m->reply_cookie == 0)
5388                                 return -EBADMSG;
5389
5390                         break;
5391
5392                 case BUS_MESSAGE_HEADER_UNIX_FDS:
5393                         if (unix_fds_set)
5394                                 return -EBADMSG;
5395
5396                         if (!streq(signature, "u"))
5397                                 return -EBADMSG;
5398
5399                         r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
5400                         if (r < 0)
5401                                 return -EBADMSG;
5402
5403                         unix_fds_set = true;
5404                         break;
5405
5406                 default:
5407                         if (!BUS_MESSAGE_IS_GVARIANT(m))
5408                                 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
5409                 }
5410
5411                 if (r < 0)
5412                         return r;
5413
5414                 i++;
5415         }
5416
5417         if (m->n_fds != unix_fds)
5418                 return -EBADMSG;
5419
5420         switch (m->header->type) {
5421
5422         case SD_BUS_MESSAGE_SIGNAL:
5423                 if (!m->path || !m->interface || !m->member)
5424                         return -EBADMSG;
5425
5426                 if (m->reply_cookie != 0)
5427                         return -EBADMSG;
5428
5429                 break;
5430
5431         case SD_BUS_MESSAGE_METHOD_CALL:
5432
5433                 if (!m->path || !m->member)
5434                         return -EBADMSG;
5435
5436                 if (m->reply_cookie != 0)
5437                         return -EBADMSG;
5438
5439                 break;
5440
5441         case SD_BUS_MESSAGE_METHOD_RETURN:
5442
5443                 if (m->reply_cookie == 0)
5444                         return -EBADMSG;
5445                 break;
5446
5447         case SD_BUS_MESSAGE_METHOD_ERROR:
5448
5449                 if (m->reply_cookie == 0 || !m->error.name)
5450                         return -EBADMSG;
5451                 break;
5452         }
5453
5454         /* Refuse non-local messages that claim they are local */
5455         if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
5456                 return -EBADMSG;
5457         if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
5458                 return -EBADMSG;
5459         if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
5460                 return -EBADMSG;
5461
5462         m->root_container.end = m->user_body_size;
5463
5464         if (BUS_MESSAGE_IS_GVARIANT(m)) {
5465                 r = build_struct_offsets(
5466                                 m,
5467                                 m->root_container.signature,
5468                                 m->user_body_size,
5469                                 &m->root_container.item_size,
5470                                 &m->root_container.offsets,
5471                                 &m->root_container.n_offsets);
5472                 if (r < 0)
5473                         return r;
5474         }
5475
5476         /* Try to read the error message, but if we can't it's a non-issue */
5477         if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
5478                 (void) sd_bus_message_read(m, "s", &m->error.message);
5479
5480         return 0;
5481 }
5482
5483 _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
5484         assert_return(m, -EINVAL);
5485         assert_return(destination, -EINVAL);
5486         assert_return(!m->sealed, -EPERM);
5487         assert_return(!m->destination, -EEXIST);
5488
5489         return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
5490 }
5491
5492 _public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
5493         assert_return(m, -EINVAL);
5494         assert_return(sender, -EINVAL);
5495         assert_return(!m->sealed, -EPERM);
5496         assert_return(!m->sender, -EEXIST);
5497
5498         return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5499 }
5500
5501 #if 0 /// UNNEEDED by elogind
5502 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
5503         size_t total;
5504         void *p, *e;
5505         unsigned i;
5506         struct bus_body_part *part;
5507
5508         assert(m);
5509         assert(buffer);
5510         assert(sz);
5511
5512         total = BUS_MESSAGE_SIZE(m);
5513
5514         p = malloc(total);
5515         if (!p)
5516                 return -ENOMEM;
5517
5518         e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
5519         MESSAGE_FOREACH_PART(part, i, m)
5520                 e = mempcpy(e, part->data, part->size);
5521
5522         assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
5523
5524         *buffer = p;
5525         *sz = total;
5526
5527         return 0;
5528 }
5529 #endif // 0
5530
5531 int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
5532         const char *s;
5533         int r;
5534
5535         assert(m);
5536         assert(l);
5537
5538         r = sd_bus_message_enter_container(m, 'a', "s");
5539         if (r <= 0)
5540                 return r;
5541
5542         while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
5543                 r = strv_extend(l, s);
5544                 if (r < 0)
5545                         return r;
5546         }
5547         if (r < 0)
5548                 return r;
5549
5550         r = sd_bus_message_exit_container(m);
5551         if (r < 0)
5552                 return r;
5553
5554         return 1;
5555 }
5556
5557 _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
5558         char **strv = NULL;
5559         int r;
5560
5561         assert_return(m, -EINVAL);
5562         assert_return(m->sealed, -EPERM);
5563         assert_return(l, -EINVAL);
5564
5565         r = bus_message_read_strv_extend(m, &strv);
5566         if (r <= 0) {
5567                 strv_free(strv);
5568                 return r;
5569         }
5570
5571         *l = strv;
5572         return 1;
5573 }
5574
5575 static int bus_message_get_arg_skip(
5576                 sd_bus_message *m,
5577                 unsigned i,
5578                 char *_type,
5579                 const char **_contents) {
5580
5581         unsigned j;
5582         int r;
5583
5584         r = sd_bus_message_rewind(m, true);
5585         if (r < 0)
5586                 return r;
5587
5588         for (j = 0;; j++) {
5589                 const char *contents;
5590                 char type;
5591
5592                 r = sd_bus_message_peek_type(m, &type, &contents);
5593                 if (r < 0)
5594                         return r;
5595                 if (r == 0)
5596                         return -ENXIO;
5597
5598                 /* Don't match against arguments after the first one we don't understand */
5599                 if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
5600                     !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
5601                         return -ENXIO;
5602
5603                 if (j >= i) {
5604                         if (_contents)
5605                                 *_contents = contents;
5606                         if (_type)
5607                                 *_type = type;
5608                         return 0;
5609                 }
5610
5611                 r = sd_bus_message_skip(m, NULL);
5612                 if (r < 0)
5613                         return r;
5614         }
5615
5616 }
5617
5618 int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
5619         char type;
5620         int r;
5621
5622         assert(m);
5623         assert(str);
5624
5625         r = bus_message_get_arg_skip(m, i, &type, NULL);
5626         if (r < 0)
5627                 return r;
5628
5629         if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
5630                 return -ENXIO;
5631
5632         return sd_bus_message_read_basic(m, type, str);
5633 }
5634
5635 int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
5636         const char *contents;
5637         char type;
5638         int r;
5639
5640         assert(m);
5641         assert(strv);
5642
5643         r = bus_message_get_arg_skip(m, i, &type, &contents);
5644         if (r < 0)
5645                 return r;
5646
5647         if (type != SD_BUS_TYPE_ARRAY)
5648                 return -ENXIO;
5649         if (!STR_IN_SET(contents, "s", "o", "g"))
5650                 return -ENXIO;
5651
5652         return sd_bus_message_read_strv(m, strv);
5653 }
5654
5655 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
5656         assert_return(m, EINVAL);
5657
5658         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
5659                 return 0;
5660
5661         return sd_bus_error_get_errno(&m->error);
5662 }
5663
5664 _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
5665         struct bus_container *c;
5666
5667         assert_return(m, NULL);
5668
5669         c = complete ? &m->root_container : message_get_container(m);
5670         return strempty(c->signature);
5671 }
5672
5673 _public_ int sd_bus_message_is_empty(sd_bus_message *m) {
5674         assert_return(m, -EINVAL);
5675
5676         return isempty(m->root_container.signature);
5677 }
5678
5679 _public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
5680         assert_return(m, -EINVAL);
5681
5682         return streq(strempty(m->root_container.signature), strempty(signature));
5683 }
5684
5685 _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
5686         bool done_something = false;
5687         int r;
5688
5689         assert_return(m, -EINVAL);
5690         assert_return(source, -EINVAL);
5691         assert_return(!m->sealed, -EPERM);
5692         assert_return(source->sealed, -EPERM);
5693
5694         do {
5695                 const char *contents;
5696                 char type;
5697                 union {
5698                         uint8_t u8;
5699                         uint16_t u16;
5700                         int16_t s16;
5701                         uint32_t u32;
5702                         int32_t s32;
5703                         uint64_t u64;
5704                         int64_t s64;
5705                         double d64;
5706                         const char *string;
5707                         int i;
5708                 } basic;
5709
5710                 r = sd_bus_message_peek_type(source, &type, &contents);
5711                 if (r < 0)
5712                         return r;
5713                 if (r == 0)
5714                         break;
5715
5716                 done_something = true;
5717
5718                 if (bus_type_is_container(type) > 0) {
5719
5720                         r = sd_bus_message_enter_container(source, type, contents);
5721                         if (r < 0)
5722                                 return r;
5723
5724                         r = sd_bus_message_open_container(m, type, contents);
5725                         if (r < 0)
5726                                 return r;
5727
5728                         r = sd_bus_message_copy(m, source, true);
5729                         if (r < 0)
5730                                 return r;
5731
5732                         r = sd_bus_message_close_container(m);
5733                         if (r < 0)
5734                                 return r;
5735
5736                         r = sd_bus_message_exit_container(source);
5737                         if (r < 0)
5738                                 return r;
5739
5740                         continue;
5741                 }
5742
5743                 r = sd_bus_message_read_basic(source, type, &basic);
5744                 if (r < 0)
5745                         return r;
5746
5747                 assert(r > 0);
5748
5749                 if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING))
5750                         r = sd_bus_message_append_basic(m, type, basic.string);
5751                 else
5752                         r = sd_bus_message_append_basic(m, type, &basic);
5753
5754                 if (r < 0)
5755                         return r;
5756
5757         } while (all);
5758
5759         return done_something;
5760 }
5761
5762 _public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
5763         const char *c;
5764         char t;
5765         int r;
5766
5767         assert_return(m, -EINVAL);
5768         assert_return(m->sealed, -EPERM);
5769         assert_return(!type || bus_type_is_valid(type), -EINVAL);
5770         assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
5771         assert_return(type || contents, -EINVAL);
5772         assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
5773
5774         r = sd_bus_message_peek_type(m, &t, &c);
5775         if (r <= 0)
5776                 return r;
5777
5778         if (type != 0 && type != t)
5779                 return 0;
5780
5781         if (contents && !streq_ptr(contents, c))
5782                 return 0;
5783
5784         return 1;
5785 }
5786
5787 _public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
5788         assert_return(m, NULL);
5789
5790         return m->bus;
5791 }
5792
5793 int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
5794         _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
5795         usec_t timeout;
5796         int r;
5797
5798         assert(bus);
5799         assert(m);
5800         assert(*m);
5801
5802         switch ((*m)->header->type) {
5803
5804         case SD_BUS_MESSAGE_SIGNAL:
5805                 r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
5806                 if (r < 0)
5807                         return r;
5808
5809                 break;
5810
5811         case SD_BUS_MESSAGE_METHOD_CALL:
5812                 r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
5813                 if (r < 0)
5814                         return r;
5815
5816                 break;
5817
5818         case SD_BUS_MESSAGE_METHOD_RETURN:
5819         case SD_BUS_MESSAGE_METHOD_ERROR:
5820
5821                 r = sd_bus_message_new(bus, &n, (*m)->header->type);
5822                 if (r < 0)
5823                         return -ENOMEM;
5824
5825                 assert(n);
5826
5827                 n->reply_cookie = (*m)->reply_cookie;
5828
5829                 r = message_append_reply_cookie(n, n->reply_cookie);
5830                 if (r < 0)
5831                         return r;
5832
5833                 if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
5834                         r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
5835                         if (r < 0)
5836                                 return r;
5837
5838                         n->error._need_free = -1;
5839                 }
5840
5841                 break;
5842
5843         default:
5844                 return -EINVAL;
5845         }
5846
5847         if ((*m)->destination && !n->destination) {
5848                 r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
5849                 if (r < 0)
5850                         return r;
5851         }
5852
5853         if ((*m)->sender && !n->sender) {
5854                 r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
5855                 if (r < 0)
5856                         return r;
5857         }
5858
5859         n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
5860
5861         r = sd_bus_message_copy(n, *m, true);
5862         if (r < 0)
5863                 return r;
5864
5865         timeout = (*m)->timeout;
5866         if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
5867                 timeout = BUS_DEFAULT_TIMEOUT;
5868
5869         r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
5870         if (r < 0)
5871                 return r;
5872
5873         sd_bus_message_unref(*m);
5874         *m = n;
5875         n = NULL;
5876
5877         return 0;
5878 }
5879
5880 #if 0 /// UNNEEDED by elogind
5881 int bus_message_append_sender(sd_bus_message *m, const char *sender) {
5882         assert(m);
5883         assert(sender);
5884
5885         assert_return(!m->sealed, -EPERM);
5886         assert_return(!m->sender, -EPERM);
5887
5888         return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
5889 }
5890 #endif // 0
5891
5892 _public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
5893         assert_return(m, -EINVAL);
5894         assert_return(priority, -EINVAL);
5895
5896         *priority = m->priority;
5897         return 0;
5898 }
5899
5900 _public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
5901         assert_return(m, -EINVAL);
5902         assert_return(!m->sealed, -EPERM);
5903
5904         m->priority = priority;
5905         return 0;
5906 }