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