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