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