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