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