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