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