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