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