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