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