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