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