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