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