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