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