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