chiark / gitweb /
35a46786009881d336550a60e20ac766979d82c2
[elogind.git] / src / libsystemd-bus / bus-message.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25
26 #include "util.h"
27 #include "utf8.h"
28 #include "strv.h"
29 #include "time-util.h"
30 #include "cgroup-util.h"
31
32 #include "sd-bus.h"
33 #include "bus-message.h"
34 #include "bus-internal.h"
35 #include "bus-type.h"
36 #include "bus-signature.h"
37 #include "bus-gvariant.h"
38
39 static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
40
41 static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
42
43         if (p == NULL)
44                 return NULL;
45
46         if (old_base == new_base)
47                 return (void*) p;
48
49         if ((uint8_t*) p < (uint8_t*) old_base)
50                 return (void*) p;
51
52         if ((uint8_t*) p >= (uint8_t*) old_base + sz)
53                 return (void*) p;
54
55         return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
56 }
57
58 static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
59         assert(m);
60         assert(part);
61
62         if (part->memfd >= 0) {
63                 /* If we can reuse the memfd, try that. For that it
64                  * can't be sealed yet. */
65
66                 if (!part->sealed)
67                         bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped);
68                 else {
69                         if (part->mapped > 0)
70                                 assert_se(munmap(part->data, part->mapped) == 0);
71
72                         close_nointr_nofail(part->memfd);
73                 }
74
75         } else if (part->munmap_this)
76                 munmap(part->data, part->mapped);
77         else if (part->free_this)
78                 free(part->data);
79
80         if (part != &m->body)
81                 free(part);
82 }
83
84 static void message_reset_parts(sd_bus_message *m) {
85         struct bus_body_part *part;
86
87         assert(m);
88
89         part = &m->body;
90         while (m->n_body_parts > 0) {
91                 struct bus_body_part *next = part->next;
92                 message_free_part(m, part);
93                 part = next;
94                 m->n_body_parts--;
95         }
96
97         m->body_end = NULL;
98
99         m->cached_rindex_part = NULL;
100         m->cached_rindex_part_begin = 0;
101 }
102
103 static void message_reset_containers(sd_bus_message *m) {
104         unsigned i;
105
106         assert(m);
107
108         for (i = 0; i < m->n_containers; i++) {
109                 free(m->containers[i].signature);
110                 free(m->containers[i].offsets);
111         }
112
113         free(m->containers);
114         m->containers = NULL;
115
116         m->n_containers = 0;
117         m->root_container.index = 0;
118 }
119
120 static void message_free(sd_bus_message *m) {
121         assert(m);
122
123         if (m->free_header)
124                 free(m->header);
125
126         message_reset_parts(m);
127
128         if (m->free_kdbus)
129                 free(m->kdbus);
130
131         if (m->release_kdbus) {
132                 uint64_t off;
133
134                 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
135                 ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
136         }
137
138         if (m->bus)
139                 sd_bus_unref(m->bus);
140
141         if (m->free_fds) {
142                 close_many(m->fds, m->n_fds);
143                 free(m->fds);
144         }
145
146         if (m->iovec != m->iovec_fixed)
147                 free(m->iovec);
148
149         message_reset_containers(m);
150         free(m->root_container.signature);
151         free(m->root_container.offsets);
152
153         free(m->peeked_signature);
154
155         bus_creds_done(&m->creds);
156         free(m);
157 }
158
159 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
160         void *op, *np;
161         size_t old_size, new_size, start;
162
163         assert(m);
164
165         if (m->poisoned)
166                 return NULL;
167
168         old_size = sizeof(struct bus_header) + m->header->fields_size;
169         start = ALIGN_TO(old_size, align);
170         new_size = start + sz;
171
172         if (old_size == new_size)
173                 return (uint8_t*) m->header + old_size;
174
175         if (new_size > (size_t) ((uint32_t) -1))
176                 goto poison;
177
178         if (m->free_header) {
179                 np = realloc(m->header, ALIGN8(new_size));
180                 if (!np)
181                         goto poison;
182         } else {
183                 /* Initially, the header is allocated as part of of
184                  * the sd_bus_message itself, let's replace it by
185                  * dynamic data */
186
187                 np = malloc(ALIGN8(new_size));
188                 if (!np)
189                         goto poison;
190
191                 memcpy(np, m->header, sizeof(struct bus_header));
192         }
193
194         /* Zero out padding */
195         if (start > old_size)
196                 memset((uint8_t*) np + old_size, 0, start - old_size);
197
198         op = m->header;
199         m->header = np;
200         m->header->fields_size = new_size - sizeof(struct bus_header);
201
202         /* Adjust quick access pointers */
203         m->path = adjust_pointer(m->path, op, old_size, m->header);
204         m->interface = adjust_pointer(m->interface, op, old_size, m->header);
205         m->member = adjust_pointer(m->member, op, old_size, m->header);
206         m->destination = adjust_pointer(m->destination, op, old_size, m->header);
207         m->sender = adjust_pointer(m->sender, op, old_size, m->header);
208         m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
209
210         m->free_header = true;
211
212         if (add_offset) {
213                 if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
214                         goto poison;
215
216                 m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
217         }
218
219         return (uint8_t*) np + start;
220
221 poison:
222         m->poisoned = true;
223         return NULL;
224 }
225
226 static int message_append_field_string(
227                 sd_bus_message *m,
228                 uint8_t h,
229                 char type,
230                 const char *s,
231                 const char **ret) {
232
233         size_t l;
234         uint8_t *p;
235
236         assert(m);
237
238         /* dbus1 doesn't allow strings over 32bit, let's enforce this
239          * globally, to not risk convertability */
240         l = strlen(s);
241         if (l > (size_t) (uint32_t) -1)
242                 return -EINVAL;
243
244         /* Signature "(yv)" where the variant contains "s" */
245
246         if (BUS_MESSAGE_IS_GVARIANT(m)) {
247
248                 /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
249                 p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
250                 if (!p)
251                         return -ENOMEM;
252
253                 p[0] = h;
254                 memset(p+1, 0, 7);
255                 memcpy(p+8, s, l);
256                 p[8+l] = 0;
257                 p[8+l+1] = 0;
258                 p[8+l+2] = type;
259
260                 if (ret)
261                         *ret = (char*) p + 8;
262
263         } else {
264                 /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
265                 p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
266                 if (!p)
267                         return -ENOMEM;
268
269                 p[0] = h;
270                 p[1] = 1;
271                 p[2] = type;
272                 p[3] = 0;
273
274                 ((uint32_t*) p)[1] = l;
275                 memcpy(p + 8, s, l + 1);
276
277                 if (ret)
278                         *ret = (char*) p + 8;
279         }
280
281         return 0;
282 }
283
284 static int message_append_field_signature(
285                 sd_bus_message *m,
286                 uint8_t h,
287                 const char *s,
288                 const char **ret) {
289
290         size_t l;
291         uint8_t *p;
292
293         assert(m);
294
295         /* dbus1 doesn't allow signatures over 32bit, let's enforce
296          * this globally, to not risk convertability */
297         l = strlen(s);
298         if (l > 255)
299                 return -EINVAL;
300
301         /* Signature "(yv)" where the variant contains "g" */
302
303         if (BUS_MESSAGE_IS_GVARIANT(m))
304                 /* For gvariant the serialization is the same as for normal strings */
305                 return message_append_field_string(m, h, 'g', s, ret);
306         else {
307                 /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
308                 p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
309                 if (!p)
310                         return -ENOMEM;
311
312                 p[0] = h;
313                 p[1] = 1;
314                 p[2] = SD_BUS_TYPE_SIGNATURE;
315                 p[3] = 0;
316                 p[4] = l;
317                 memcpy(p + 5, s, l + 1);
318
319                 if (ret)
320                         *ret = (const char*) p + 5;
321         }
322
323         return 0;
324 }
325
326 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
327         uint8_t *p;
328
329         assert(m);
330
331         if (BUS_MESSAGE_IS_GVARIANT(m)) {
332                 /* (field id byte + 7x padding + ((value + NUL + signature string 'u') */
333
334                 p = message_extend_fields(m, 8, 1 + 7 + 4 + 1 + 1, true);
335                 if (!p)
336                         return -ENOMEM;
337
338                 p[0] = h;
339                 memset(p+1, 0, 7);
340                 *((uint32_t*) (p + 8)) = x;
341                 p[12] = 0;
342                 p[13] = 'u';
343         } else {
344                 /* (field id byte + (signature length + signature 'u' + NUL) + value) */
345                 p = message_extend_fields(m, 8, 4 + 4, false);
346                 if (!p)
347                         return -ENOMEM;
348
349                 p[0] = h;
350                 p[1] = 1;
351                 p[2] = SD_BUS_TYPE_UINT32;
352                 p[3] = 0;
353
354                 ((uint32_t*) p)[1] = x;
355         }
356
357         return 0;
358 }
359
360 int bus_message_from_header(
361                 sd_bus *bus,
362                 void *buffer,
363                 size_t length,
364                 int *fds,
365                 unsigned n_fds,
366                 const struct ucred *ucred,
367                 const char *label,
368                 size_t extra,
369                 sd_bus_message **ret) {
370
371         sd_bus_message *m;
372         struct bus_header *h;
373         size_t a, label_sz;
374
375         assert(buffer || length <= 0);
376         assert(fds || n_fds <= 0);
377         assert(ret);
378
379         if (length < sizeof(struct bus_header))
380                 return -EBADMSG;
381
382         h = buffer;
383         if (h->version != 1 &&
384             h->version != 2)
385                 return -EBADMSG;
386
387         if (h->serial == 0)
388                 return -EBADMSG;
389
390         if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
391                 return -EBADMSG;
392
393         if (h->endian != BUS_LITTLE_ENDIAN &&
394             h->endian != BUS_BIG_ENDIAN)
395                 return -EBADMSG;
396
397         a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
398
399         if (label) {
400                 label_sz = strlen(label);
401                 a += label_sz + 1;
402         }
403
404         m = malloc0(a);
405         if (!m)
406                 return -ENOMEM;
407
408         m->n_ref = 1;
409         m->sealed = true;
410         m->header = h;
411         m->fds = fds;
412         m->n_fds = n_fds;
413
414         if (ucred) {
415                 m->creds.uid = ucred->uid;
416                 m->creds.pid = ucred->pid;
417                 m->creds.gid = ucred->gid;
418                 m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID;
419         }
420
421         if (label) {
422                 m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
423                 memcpy(m->creds.label, label, label_sz + 1);
424
425                 m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
426         }
427
428         if (bus)
429                 m->bus = sd_bus_ref(bus);
430
431         *ret = m;
432         return 0;
433 }
434
435 int bus_message_from_malloc(
436                 sd_bus *bus,
437                 void *buffer,
438                 size_t length,
439                 int *fds,
440                 unsigned n_fds,
441                 const struct ucred *ucred,
442                 const char *label,
443                 sd_bus_message **ret) {
444
445         sd_bus_message *m;
446         size_t sz;
447         int r;
448
449         r = bus_message_from_header(bus, buffer, length, fds, n_fds, ucred, label, 0, &m);
450         if (r < 0)
451                 return r;
452
453         if (length != BUS_MESSAGE_SIZE(m)) {
454                 r = -EBADMSG;
455                 goto fail;
456         }
457
458         sz = length - sizeof(struct bus_header) - ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
459         if (sz > 0) {
460                 m->n_body_parts = 1;
461                 m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m));
462                 m->body.size = sz;
463                 m->body.sealed = true;
464                 m->body.memfd = -1;
465         }
466
467         m->n_iovec = 1;
468         m->iovec = m->iovec_fixed;
469         m->iovec[0].iov_base = buffer;
470         m->iovec[0].iov_len = length;
471
472         r = bus_message_parse_fields(m);
473         if (r < 0)
474                 goto fail;
475
476         /* We take possession of the memory and fds now */
477         m->free_header = true;
478         m->free_fds = true;
479
480         *ret = m;
481         return 0;
482
483 fail:
484         message_free(m);
485         return r;
486 }
487
488 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
489         sd_bus_message *m;
490
491         m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
492         if (!m)
493                 return NULL;
494
495         m->n_ref = 1;
496         m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
497         m->header->endian = BUS_NATIVE_ENDIAN;
498         m->header->type = type;
499         m->header->version = bus ? bus->message_version : 1;
500         m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
501         m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
502
503         if (bus)
504                 m->bus = sd_bus_ref(bus);
505
506         return m;
507 }
508
509 _public_ int sd_bus_message_new_signal(
510                 sd_bus *bus,
511                 const char *path,
512                 const char *interface,
513                 const char *member,
514                 sd_bus_message **m) {
515
516         sd_bus_message *t;
517         int r;
518
519         assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
520         assert_return(object_path_is_valid(path), -EINVAL);
521         assert_return(interface_name_is_valid(interface), -EINVAL);
522         assert_return(member_name_is_valid(member), -EINVAL);
523         assert_return(m, -EINVAL);
524
525         t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
526         if (!t)
527                 return -ENOMEM;
528
529         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
530
531         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
532         if (r < 0)
533                 goto fail;
534         r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
535         if (r < 0)
536                 goto fail;
537         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
538         if (r < 0)
539                 goto fail;
540
541         *m = t;
542         return 0;
543
544 fail:
545         sd_bus_message_unref(t);
546         return r;
547 }
548
549 _public_ int sd_bus_message_new_method_call(
550                 sd_bus *bus,
551                 const char *destination,
552                 const char *path,
553                 const char *interface,
554                 const char *member,
555                 sd_bus_message **m) {
556
557         sd_bus_message *t;
558         int r;
559
560         assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN);
561         assert_return(!destination || service_name_is_valid(destination), -EINVAL);
562         assert_return(object_path_is_valid(path), -EINVAL);
563         assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
564         assert_return(member_name_is_valid(member), -EINVAL);
565         assert_return(m, -EINVAL);
566
567         t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
568         if (!t)
569                 return -ENOMEM;
570
571         r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
572         if (r < 0)
573                 goto fail;
574         r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
575         if (r < 0)
576                 goto fail;
577
578         if (interface) {
579                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
580                 if (r < 0)
581                         goto fail;
582         }
583
584         if (destination) {
585                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
586                 if (r < 0)
587                         goto fail;
588         }
589
590         *m = t;
591         return 0;
592
593 fail:
594         message_free(t);
595         return r;
596 }
597
598 static int message_new_reply(
599                 sd_bus_message *call,
600                 uint8_t type,
601                 sd_bus_message **m) {
602
603         sd_bus_message *t;
604         int r;
605
606         assert_return(call, -EINVAL);
607         assert_return(call->sealed, -EPERM);
608         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
609         assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN);
610         assert_return(m, -EINVAL);
611
612         t = message_new(call->bus, type);
613         if (!t)
614                 return -ENOMEM;
615
616         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
617         t->reply_serial = BUS_MESSAGE_SERIAL(call);
618
619         r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
620         if (r < 0)
621                 goto fail;
622
623         if (call->sender) {
624                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
625                 if (r < 0)
626                         goto fail;
627         }
628
629         t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
630         t->enforced_reply_signature = call->enforced_reply_signature;
631
632         *m = t;
633         return 0;
634
635 fail:
636         message_free(t);
637         return r;
638 }
639
640 _public_ int sd_bus_message_new_method_return(
641                 sd_bus_message *call,
642                 sd_bus_message **m) {
643
644         return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
645 }
646
647 _public_ int sd_bus_message_new_method_error(
648                 sd_bus_message *call,
649                 const sd_bus_error *e,
650                 sd_bus_message **m) {
651
652         sd_bus_message *t;
653         int r;
654
655         assert_return(sd_bus_error_is_set(e), -EINVAL);
656         assert_return(m, -EINVAL);
657
658         r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
659         if (r < 0)
660                 return r;
661
662         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
663         if (r < 0)
664                 goto fail;
665
666         if (e->message) {
667                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
668                 if (r < 0)
669                         goto fail;
670         }
671
672         t->error._need_free = -1;
673
674         *m = t;
675         return 0;
676
677 fail:
678         message_free(t);
679         return r;
680 }
681
682 _public_ int sd_bus_message_new_method_errorf(
683                 sd_bus_message *call,
684                 sd_bus_message **m,
685                 const char *name,
686                 const char *format,
687                 ...) {
688
689         _cleanup_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
690         va_list ap;
691
692         assert_return(name, -EINVAL);
693         assert_return(m, -EINVAL);
694
695         va_start(ap, format);
696         bus_error_setfv(&error, name, format, ap);
697         va_end(ap);
698
699         return sd_bus_message_new_method_error(call, &error, m);
700 }
701
702 _public_ int sd_bus_message_new_method_errno(
703                 sd_bus_message *call,
704                 int error,
705                 const sd_bus_error *p,
706                 sd_bus_message **m) {
707
708         _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
709
710         if (sd_bus_error_is_set(p))
711                 return sd_bus_message_new_method_error(call, p, m);
712
713         sd_bus_error_set_errno(&berror, error);
714
715         return sd_bus_message_new_method_error(call, &berror, m);
716 }
717
718 _public_ int sd_bus_message_new_method_errnof(
719                 sd_bus_message *call,
720                 sd_bus_message **m,
721                 int error,
722                 const char *format,
723                 ...) {
724
725         _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
726         va_list ap;
727
728         va_start(ap, format);
729         bus_error_set_errnofv(&berror, error, format, ap);
730         va_end(ap);
731
732         return sd_bus_message_new_method_error(call, &berror, m);
733 }
734
735 int bus_message_new_synthetic_error(
736                 sd_bus *bus,
737                 uint64_t serial,
738                 const sd_bus_error *e,
739                 sd_bus_message **m) {
740
741         sd_bus_message *t;
742         int r;
743
744         assert(sd_bus_error_is_set(e));
745         assert(m);
746
747         t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
748         if (!t)
749                 return -ENOMEM;
750
751         t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
752         t->reply_serial = serial;
753
754         r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
755         if (r < 0)
756                 goto fail;
757
758         if (bus && bus->unique_name) {
759                 r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
760                 if (r < 0)
761                         goto fail;
762         }
763
764         r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
765         if (r < 0)
766                 goto fail;
767
768         if (e->message) {
769                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
770                 if (r < 0)
771                         goto fail;
772         }
773
774         t->error._need_free = -1;
775
776         *m = t;
777         return 0;
778
779 fail:
780         message_free(t);
781         return r;
782 }
783
784 _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
785         assert_return(m, NULL);
786
787         assert(m->n_ref > 0);
788         m->n_ref++;
789
790         return m;
791 }
792
793 _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
794         assert_return(m, NULL);
795
796         assert(m->n_ref > 0);
797         m->n_ref--;
798
799         if (m->n_ref <= 0)
800                 message_free(m);
801
802         return NULL;
803 }
804
805 _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
806         assert_return(m, -EINVAL);
807         assert_return(type, -EINVAL);
808
809         *type = m->header->type;
810         return 0;
811 }
812
813 _public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
814         assert_return(m, -EINVAL);
815         assert_return(serial, -EINVAL);
816         assert_return(m->header->serial != 0, -ENOENT);
817
818         *serial = BUS_MESSAGE_SERIAL(m);
819         return 0;
820 }
821
822 _public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
823         assert_return(m, -EINVAL);
824         assert_return(serial, -EINVAL);
825         assert_return(m->reply_serial != 0, -ENOENT);
826
827         *serial = m->reply_serial;
828         return 0;
829 }
830
831 _public_ int sd_bus_message_get_no_reply(sd_bus_message *m) {
832         assert_return(m, -EINVAL);
833
834         return m->header->type == SD_BUS_MESSAGE_METHOD_CALL ? !!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
835 }
836
837 _public_ int sd_bus_message_get_no_auto_start(sd_bus_message *m) {
838         assert_return(m, -EINVAL);
839
840         return !!(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
841 }
842
843 _public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
844         assert_return(m, NULL);
845
846         return m->path;
847 }
848
849 _public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
850         assert_return(m, NULL);
851
852         return m->interface;
853 }
854
855 _public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
856         assert_return(m, NULL);
857
858         return m->member;
859 }
860
861 _public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
862         assert_return(m, NULL);
863
864         return m->destination;
865 }
866
867 _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
868         assert_return(m, NULL);
869
870         return m->sender;
871 }
872
873 _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
874         assert_return(m, NULL);
875         assert_return(sd_bus_error_is_set(&m->error), NULL);
876
877         return &m->error;
878 }
879
880 _public_ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) {
881         assert_return(m, -EINVAL);
882         assert_return(usec, -EINVAL);
883         assert_return(m->monotonic > 0, -ENODATA);
884
885         *usec = m->monotonic;
886         return 0;
887 }
888
889 _public_ int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) {
890         assert_return(m, -EINVAL);
891         assert_return(usec, -EINVAL);
892         assert_return(m->realtime > 0, -ENODATA);
893
894         *usec = m->realtime;
895         return 0;
896 }
897
898 _public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
899         assert_return(m, NULL);
900
901         if (m->creds.mask == 0)
902                 return NULL;
903
904         return &m->creds;
905 }
906
907 _public_ int sd_bus_message_is_signal(sd_bus_message *m,
908                                       const char *interface,
909                                       const char *member) {
910         assert_return(m, -EINVAL);
911
912         if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
913                 return 0;
914
915         if (interface && (!m->interface || !streq(m->interface, interface)))
916                 return 0;
917
918         if (member &&  (!m->member || !streq(m->member, member)))
919                 return 0;
920
921         return 1;
922 }
923
924 _public_ int sd_bus_message_is_method_call(sd_bus_message *m,
925                                            const char *interface,
926                                            const char *member) {
927         assert_return(m, -EINVAL);
928
929         if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
930                 return 0;
931
932         if (interface && (!m->interface || !streq(m->interface, interface)))
933                 return 0;
934
935         if (member &&  (!m->member || !streq(m->member, member)))
936                 return 0;
937
938         return 1;
939 }
940
941 _public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
942         assert_return(m, -EINVAL);
943
944         if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
945                 return 0;
946
947         if (name && (!m->error.name || !streq(m->error.name, name)))
948                 return 0;
949
950         return 1;
951 }
952
953 _public_ int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
954         assert_return(m, -EINVAL);
955         assert_return(!m->sealed, -EPERM);
956         assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
957
958         if (b)
959                 m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
960         else
961                 m->header->flags &= ~BUS_MESSAGE_NO_REPLY_EXPECTED;
962
963         return 0;
964 }
965
966 _public_ int sd_bus_message_set_no_auto_start(sd_bus_message *m, int b) {
967         assert_return(m, -EINVAL);
968         assert_return(!m->sealed, -EPERM);
969
970         if (b)
971                 m->header->flags |= BUS_MESSAGE_NO_AUTO_START;
972         else
973                 m->header->flags &= ~BUS_MESSAGE_NO_AUTO_START;
974
975         return 0;
976 }
977
978 static struct bus_container *message_get_container(sd_bus_message *m) {
979         assert(m);
980
981         if (m->n_containers == 0)
982                 return &m->root_container;
983
984         assert(m->containers);
985         return m->containers + m->n_containers - 1;
986 }
987
988 struct bus_body_part *message_append_part(sd_bus_message *m) {
989         struct bus_body_part *part;
990
991         assert(m);
992
993         if (m->poisoned)
994                 return NULL;
995
996         if (m->n_body_parts <= 0) {
997                 part = &m->body;
998                 zero(*part);
999         } else {
1000                 assert(m->body_end);
1001
1002                 part = new0(struct bus_body_part, 1);
1003                 if (!part) {
1004                         m->poisoned = true;
1005                         return NULL;
1006                 }
1007
1008                 m->body_end->next = part;
1009         }
1010
1011         part->memfd = -1;
1012         m->body_end = part;
1013         m->n_body_parts ++;
1014
1015         return part;
1016 }
1017
1018 static void part_zero(struct bus_body_part *part, size_t sz) {
1019         assert(part);
1020         assert(sz > 0);
1021         assert(sz < 8);
1022
1023         /* All other fields can be left in their defaults */
1024         assert(!part->data);
1025         assert(part->memfd < 0);
1026
1027         part->size = sz;
1028         part->is_zero = true;
1029         part->sealed = true;
1030 }
1031
1032 static int part_make_space(
1033                 struct sd_bus_message *m,
1034                 struct bus_body_part *part,
1035                 size_t sz,
1036                 void **q) {
1037
1038         void *n;
1039         int r;
1040
1041         assert(m);
1042         assert(part);
1043         assert(!part->sealed);
1044
1045         if (m->poisoned)
1046                 return -ENOMEM;
1047
1048         if (!part->data && part->memfd < 0)
1049                 part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped);
1050
1051         if (part->memfd >= 0) {
1052                 uint64_t u = sz;
1053
1054                 r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u);
1055                 if (r < 0) {
1056                         m->poisoned = true;
1057                         return -errno;
1058                 }
1059
1060                 if (!part->data || sz > part->mapped) {
1061                         size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1);
1062
1063                         if (part->mapped <= 0)
1064                                 n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
1065                         else
1066                                 n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE);
1067
1068                         if (n == MAP_FAILED) {
1069                                 m->poisoned = true;
1070                                 return -errno;
1071                         }
1072
1073                         part->mapped = psz;
1074                         part->data = n;
1075                 }
1076
1077                 part->munmap_this = true;
1078         } else {
1079                 n = realloc(part->data, MAX(sz, 1u));
1080                 if (!n) {
1081                         m->poisoned = true;
1082                         return -ENOMEM;
1083                 }
1084
1085                 part->data = n;
1086                 part->free_this = true;
1087         }
1088
1089         if (q)
1090                 *q = part->data ? (uint8_t*) part->data + part->size : NULL;
1091
1092         part->size = sz;
1093         return 0;
1094 }
1095
1096 static int message_add_offset(sd_bus_message *m, size_t offset) {
1097         struct bus_container *c;
1098
1099         assert(m);
1100         assert(BUS_MESSAGE_IS_GVARIANT(m));
1101
1102         /* Add offset to current container, unless this is the first
1103          * item in it, which will have the 0 offset, which we can
1104          * ignore. */
1105         c = message_get_container(m);
1106
1107         if (!c->need_offsets)
1108                 return 0;
1109
1110         if (!GREEDY_REALLOC(c->offsets, c->n_offsets_allocated, c->n_offsets + 1))
1111                 return -ENOMEM;
1112
1113         c->offsets[c->n_offsets++] = offset;
1114         return 0;
1115 }
1116
1117 static void message_extend_containers(sd_bus_message *m, size_t expand) {
1118         struct bus_container *c;
1119
1120         assert(m);
1121
1122         if (expand <= 0)
1123                 return;
1124
1125         /* Update counters */
1126         for (c = m->containers; c < m->containers + m->n_containers; c++) {
1127
1128                 if (c->array_size)
1129                         *c->array_size += expand;
1130         }
1131 }
1132
1133 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
1134         size_t start_body, end_body, padding, added;
1135         void *p;
1136         int r;
1137
1138         assert(m);
1139         assert(align > 0);
1140         assert(!m->sealed);
1141
1142         if (m->poisoned)
1143                 return NULL;
1144
1145         start_body = ALIGN_TO((size_t) m->header->body_size, align);
1146         end_body = start_body + sz;
1147
1148         padding = start_body - m->header->body_size;
1149         added = padding + sz;
1150
1151         /* Check for 32bit overflows */
1152         if (end_body > (size_t) ((uint32_t) -1)) {
1153                 m->poisoned = true;
1154                 return NULL;
1155         }
1156
1157         if (added > 0) {
1158                 struct bus_body_part *part = NULL;
1159                 bool add_new_part;
1160
1161                 add_new_part =
1162                         m->n_body_parts <= 0 ||
1163                         m->body_end->sealed ||
1164                         padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size;
1165
1166                 if (add_new_part) {
1167                         if (padding > 0) {
1168                                 part = message_append_part(m);
1169                                 if (!part)
1170                                         return NULL;
1171
1172                                 part_zero(part, padding);
1173                         }
1174
1175                         part = message_append_part(m);
1176                         if (!part)
1177                                 return NULL;
1178
1179                         r = part_make_space(m, part, sz, &p);
1180                         if (r < 0)
1181                                 return NULL;
1182                 } else {
1183                         struct bus_container *c;
1184                         void *op;
1185                         size_t os, start_part, end_part;
1186
1187                         part = m->body_end;
1188                         op = part->data;
1189                         os = part->size;
1190
1191                         start_part = ALIGN_TO(part->size, align);
1192                         end_part = start_part + sz;
1193
1194                         r = part_make_space(m, part, end_part, &p);
1195                         if (r < 0)
1196                                 return NULL;
1197
1198                         if (padding > 0) {
1199                                 memset(p, 0, padding);
1200                                 p = (uint8_t*) p + padding;
1201                         }
1202
1203                         /* Readjust pointers */
1204                         for (c = m->containers; c < m->containers + m->n_containers; c++)
1205                                 c->array_size = adjust_pointer(c->array_size, op, os, part->data);
1206
1207                         m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
1208                 }
1209         } else
1210                 /* Return something that is not NULL and is aligned */
1211                 p = (uint8_t *) NULL + align;
1212
1213         m->header->body_size = end_body;
1214         message_extend_containers(m, added);
1215
1216         if (add_offset) {
1217                 r = message_add_offset(m, end_body);
1218                 if (r < 0) {
1219                         m->poisoned = true;
1220                         return NULL;
1221                 }
1222         }
1223
1224         return p;
1225 }
1226
1227 static int message_push_fd(sd_bus_message *m, int fd) {
1228         int *f, copy;
1229
1230         assert(m);
1231
1232         if (fd < 0)
1233                 return -EINVAL;
1234
1235         if (!m->allow_fds)
1236                 return -ENOTSUP;
1237
1238         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
1239         if (copy < 0)
1240                 return -errno;
1241
1242         f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
1243         if (!f) {
1244                 m->poisoned = true;
1245                 close_nointr_nofail(copy);
1246                 return -ENOMEM;
1247         }
1248
1249         m->fds = f;
1250         m->fds[m->n_fds] = copy;
1251         m->free_fds = true;
1252
1253         return copy;
1254 }
1255
1256 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
1257         _cleanup_close_ int fd = -1;
1258         struct bus_container *c;
1259         ssize_t align, sz;
1260         void *a;
1261
1262         assert_return(m, -EINVAL);
1263         assert_return(!m->sealed, -EPERM);
1264         assert_return(bus_type_is_basic(type), -EINVAL);
1265         assert_return(!m->poisoned, -ESTALE);
1266
1267         c = message_get_container(m);
1268
1269         if (c->signature && c->signature[c->index]) {
1270                 /* Container signature is already set */
1271
1272                 if (c->signature[c->index] != type)
1273                         return -ENXIO;
1274         } else {
1275                 char *e;
1276
1277                 /* Maybe we can append to the signature? But only if this is the top-level container*/
1278                 if (c->enclosing != 0)
1279                         return -ENXIO;
1280
1281                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
1282                 if (!e) {
1283                         m->poisoned = true;
1284                         return -ENOMEM;
1285                 }
1286         }
1287
1288         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1289                 uint8_t u8;
1290                 uint32_t u32;
1291
1292                 switch (type) {
1293
1294                 case SD_BUS_TYPE_SIGNATURE:
1295                 case SD_BUS_TYPE_STRING:
1296                         p = strempty(p);
1297
1298                         /* Fall through... */
1299                 case SD_BUS_TYPE_OBJECT_PATH:
1300                         if (!p)
1301                                 return -EINVAL;
1302
1303                         align = 1;
1304                         sz = strlen(p) + 1;
1305                         break;
1306
1307                 case SD_BUS_TYPE_BOOLEAN:
1308
1309                         u8 = p && *(int*) p;
1310                         p = &u8;
1311
1312                         align = sz = 1;
1313                         break;
1314
1315                 case SD_BUS_TYPE_UNIX_FD:
1316
1317                         if (!p)
1318                                 return -EINVAL;
1319
1320                         fd = message_push_fd(m, *(int*) p);
1321                         if (fd < 0)
1322                                 return fd;
1323
1324                         u32 = m->n_fds;
1325                         p = &u32;
1326
1327                         align = sz = 4;
1328                         break;
1329
1330                 default:
1331                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
1332                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
1333                         break;
1334                 }
1335
1336                 assert(align > 0);
1337                 assert(sz > 0);
1338
1339                 a = message_extend_body(m, align, sz, true);
1340                 if (!a)
1341                         return -ENOMEM;
1342
1343                 memcpy(a, p, sz);
1344
1345                 if (stored)
1346                         *stored = (const uint8_t*) a;
1347
1348         } else {
1349                 uint32_t u32;
1350
1351                 switch (type) {
1352
1353                 case SD_BUS_TYPE_STRING:
1354                         /* To make things easy we'll serialize a NULL string
1355                          * into the empty string */
1356                         p = strempty(p);
1357
1358                         /* Fall through... */
1359                 case SD_BUS_TYPE_OBJECT_PATH:
1360
1361                         if (!p)
1362                                 return -EINVAL;
1363
1364                         align = 4;
1365                         sz = 4 + strlen(p) + 1;
1366                         break;
1367
1368                 case SD_BUS_TYPE_SIGNATURE:
1369
1370                         p = strempty(p);
1371
1372                         align = 1;
1373                         sz = 1 + strlen(p) + 1;
1374                         break;
1375
1376                 case SD_BUS_TYPE_BOOLEAN:
1377
1378                         u32 = p && *(int*) p;
1379                         p = &u32;
1380
1381                         align = sz = 4;
1382                         break;
1383
1384                 case SD_BUS_TYPE_UNIX_FD:
1385
1386                         if (!p)
1387                                 return -EINVAL;
1388
1389                         fd = message_push_fd(m, *(int*) p);
1390                         if (fd < 0)
1391                                 return fd;
1392
1393                         u32 = m->n_fds;
1394                         p = &u32;
1395
1396                         align = sz = 4;
1397                         break;
1398
1399                 default:
1400                         align = bus_type_get_alignment(type);
1401                         sz = bus_type_get_size(type);
1402                         break;
1403                 }
1404
1405                 assert(align > 0);
1406                 assert(sz > 0);
1407
1408                 a = message_extend_body(m, align, sz, false);
1409                 if (!a)
1410                         return -ENOMEM;
1411
1412                 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
1413                         *(uint32_t*) a = sz - 5;
1414                         memcpy((uint8_t*) a + 4, p, sz - 4);
1415
1416                         if (stored)
1417                                 *stored = (const uint8_t*) a + 4;
1418
1419                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
1420                         *(uint8_t*) a = sz - 1;
1421                         memcpy((uint8_t*) a + 1, p, sz - 1);
1422
1423                         if (stored)
1424                                 *stored = (const uint8_t*) a + 1;
1425                 } else {
1426                         memcpy(a, p, sz);
1427
1428                         if (stored)
1429                                 *stored = a;
1430                 }
1431         }
1432
1433         if (type == SD_BUS_TYPE_UNIX_FD)
1434                 m->n_fds ++;
1435
1436         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1437                 c->index++;
1438
1439         fd = -1;
1440         return 0;
1441 }
1442
1443 _public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
1444         return message_append_basic(m, type, p, NULL);
1445 }
1446
1447 _public_ int sd_bus_message_append_string_space(
1448                 sd_bus_message *m,
1449                 size_t size,
1450                 char **s) {
1451
1452         struct bus_container *c;
1453         void *a;
1454
1455         assert_return(m, -EINVAL);
1456         assert_return(s, -EINVAL);
1457         assert_return(!m->sealed, -EPERM);
1458         assert_return(!m->poisoned, -ESTALE);
1459
1460         c = message_get_container(m);
1461
1462         if (c->signature && c->signature[c->index]) {
1463                 /* Container signature is already set */
1464
1465                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1466                         return -ENXIO;
1467         } else {
1468                 char *e;
1469
1470                 /* Maybe we can append to the signature? But only if this is the top-level container*/
1471                 if (c->enclosing != 0)
1472                         return -ENXIO;
1473
1474                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1475                 if (!e) {
1476                         m->poisoned = true;
1477                         return -ENOMEM;
1478                 }
1479         }
1480
1481         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1482                 a = message_extend_body(m, 1, size + 1, true);
1483                 if (!a)
1484                         return -ENOMEM;
1485
1486                 *s = a;
1487         } else {
1488                 a = message_extend_body(m, 4, 4 + size + 1, false);
1489                 if (!a)
1490                         return -ENOMEM;
1491
1492                 *(uint32_t*) a = size;
1493                 *s = (char*) a + 4;
1494         }
1495
1496         (*s)[size] = 0;
1497
1498         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1499                 c->index++;
1500
1501         return 0;
1502 }
1503
1504 _public_ int sd_bus_message_append_string_iovec(
1505                 sd_bus_message *m,
1506                 const struct iovec *iov,
1507                 unsigned n) {
1508
1509         size_t size;
1510         unsigned i;
1511         char *p;
1512         int r;
1513
1514         assert_return(m, -EINVAL);
1515         assert_return(!m->sealed, -EPERM);
1516         assert_return(iov || n == 0, -EINVAL);
1517         assert_return(!m->poisoned, -ESTALE);
1518
1519         size = IOVEC_TOTAL_SIZE(iov, n);
1520
1521         r = sd_bus_message_append_string_space(m, size, &p);
1522         if (r < 0)
1523                 return r;
1524
1525         for (i = 0; i < n; i++) {
1526
1527                 if (iov[i].iov_base)
1528                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
1529                 else
1530                         memset(p, ' ', iov[i].iov_len);
1531
1532                 p += iov[i].iov_len;
1533         }
1534
1535         return 0;
1536 }
1537
1538 static int bus_message_open_array(
1539                 sd_bus_message *m,
1540                 struct bus_container *c,
1541                 const char *contents,
1542                 uint32_t **array_size,
1543                 size_t *begin,
1544                 bool *need_offsets) {
1545
1546         unsigned nindex;
1547         int alignment, r;
1548
1549         assert(m);
1550         assert(c);
1551         assert(contents);
1552         assert(array_size);
1553         assert(begin);
1554         assert(need_offsets);
1555
1556         if (!signature_is_single(contents, true))
1557                 return -EINVAL;
1558
1559         if (c->signature && c->signature[c->index]) {
1560
1561                 /* Verify the existing signature */
1562
1563                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1564                         return -ENXIO;
1565
1566                 if (!startswith(c->signature + c->index + 1, contents))
1567                         return -ENXIO;
1568
1569                 nindex = c->index + 1 + strlen(contents);
1570         } else {
1571                 char *e;
1572
1573                 if (c->enclosing != 0)
1574                         return -ENXIO;
1575
1576                 /* Extend the existing signature */
1577
1578                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1579                 if (!e) {
1580                         m->poisoned = true;
1581                         return -ENOMEM;
1582                 }
1583
1584                 nindex = e - c->signature;
1585         }
1586
1587         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1588                 alignment = bus_gvariant_get_alignment(contents);
1589                 if (alignment < 0)
1590                         return alignment;
1591
1592                 /* Add alignment padding and add to offset list */
1593                 if (!message_extend_body(m, alignment, 0, false))
1594                         return -ENOMEM;
1595
1596                 r = bus_gvariant_is_fixed_size(contents);
1597                 if (r < 0)
1598                         return r;
1599
1600                 *begin = m->header->body_size;
1601                 *need_offsets = r == 0;
1602         } else {
1603                 void *a, *op;
1604                 size_t os;
1605                 struct bus_body_part *o;
1606
1607                 alignment = bus_type_get_alignment(contents[0]);
1608                 if (alignment < 0)
1609                         return alignment;
1610
1611                 a = message_extend_body(m, 4, 4, false);
1612                 if (!a)
1613                         return -ENOMEM;
1614
1615                 o = m->body_end;
1616                 op = m->body_end->data;
1617                 os = m->body_end->size;
1618
1619                 /* Add alignment between size and first element */
1620                 if (!message_extend_body(m, alignment, 0, false))
1621                         return -ENOMEM;
1622
1623                 /* location of array size might have changed so let's readjust a */
1624                 if (o == m->body_end)
1625                         a = adjust_pointer(a, op, os, m->body_end->data);
1626
1627                 *(uint32_t*) a = 0;
1628                 *array_size = a;
1629         }
1630
1631         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1632                 c->index = nindex;
1633
1634         return 0;
1635 }
1636
1637 static int bus_message_open_variant(
1638                 sd_bus_message *m,
1639                 struct bus_container *c,
1640                 const char *contents) {
1641
1642         assert(m);
1643         assert(c);
1644         assert(contents);
1645
1646         if (!signature_is_single(contents, false))
1647                 return -EINVAL;
1648
1649         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1650                 return -EINVAL;
1651
1652         if (c->signature && c->signature[c->index]) {
1653
1654                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1655                         return -ENXIO;
1656
1657         } else {
1658                 char *e;
1659
1660                 if (c->enclosing != 0)
1661                         return -ENXIO;
1662
1663                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
1664                 if (!e) {
1665                         m->poisoned = true;
1666                         return -ENOMEM;
1667                 }
1668         }
1669
1670         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1671                 /* Variants are always aligned to 8 */
1672
1673                 if (!message_extend_body(m, 8, 0, false))
1674                         return -ENOMEM;
1675
1676         } else {
1677                 size_t l;
1678                 void *a;
1679
1680                 l = strlen(contents);
1681                 a = message_extend_body(m, 1, 1 + l + 1, false);
1682                 if (!a)
1683                         return -ENOMEM;
1684
1685                 *(uint8_t*) a = l;
1686                 memcpy((uint8_t*) a + 1, contents, l + 1);
1687         }
1688
1689         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1690                 c->index++;
1691
1692         return 0;
1693 }
1694
1695 static int bus_message_open_struct(
1696                 sd_bus_message *m,
1697                 struct bus_container *c,
1698                 const char *contents,
1699                 size_t *begin,
1700                 bool *need_offsets) {
1701
1702         size_t nindex;
1703         int r;
1704
1705         assert(m);
1706         assert(c);
1707         assert(contents);
1708         assert(begin);
1709         assert(need_offsets);
1710
1711         if (!signature_is_valid(contents, false))
1712                 return -EINVAL;
1713
1714         if (c->signature && c->signature[c->index]) {
1715                 size_t l;
1716
1717                 l = strlen(contents);
1718
1719                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1720                     !startswith(c->signature + c->index + 1, contents) ||
1721                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1722                         return -ENXIO;
1723
1724                 nindex = c->index + 1 + l + 1;
1725         } else {
1726                 char *e;
1727
1728                 if (c->enclosing != 0)
1729                         return -ENXIO;
1730
1731                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1732                 if (!e) {
1733                         m->poisoned = true;
1734                         return -ENOMEM;
1735                 }
1736
1737                 nindex = e - c->signature;
1738         }
1739
1740         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1741                 int alignment;
1742
1743                 alignment = bus_gvariant_get_alignment(contents);
1744                 if (alignment < 0)
1745                         return alignment;
1746
1747                 if (!message_extend_body(m, alignment, 0, false))
1748                         return -ENOMEM;
1749
1750                 r = bus_gvariant_is_fixed_size(contents);
1751                 if (r < 0)
1752                         return r;
1753
1754                 *begin = m->header->body_size;
1755                 *need_offsets = r == 0;
1756         } else {
1757                 /* Align contents to 8 byte boundary */
1758                 if (!message_extend_body(m, 8, 0, false))
1759                         return -ENOMEM;
1760         }
1761
1762         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1763                 c->index = nindex;
1764
1765         return 0;
1766 }
1767
1768 static int bus_message_open_dict_entry(
1769                 sd_bus_message *m,
1770                 struct bus_container *c,
1771                 const char *contents,
1772                 size_t *begin,
1773                 bool *need_offsets) {
1774
1775         int r;
1776
1777         assert(m);
1778         assert(c);
1779         assert(contents);
1780         assert(begin);
1781         assert(need_offsets);
1782
1783         if (!signature_is_pair(contents))
1784                 return -EINVAL;
1785
1786         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1787                 return -ENXIO;
1788
1789         if (c->signature && c->signature[c->index]) {
1790                 size_t l;
1791
1792                 l = strlen(contents);
1793
1794                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1795                     !startswith(c->signature + c->index + 1, contents) ||
1796                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1797                         return -ENXIO;
1798         } else
1799                 return -ENXIO;
1800
1801         if (BUS_MESSAGE_IS_GVARIANT(m)) {
1802                 int alignment;
1803
1804                 alignment = bus_gvariant_get_alignment(contents);
1805                 if (alignment < 0)
1806                         return alignment;
1807
1808                 if (!message_extend_body(m, alignment, 0, false))
1809                         return -ENOMEM;
1810
1811                 r = bus_gvariant_is_fixed_size(contents);
1812                 if (r < 0)
1813                         return r;
1814
1815                 *begin = m->header->body_size;
1816                 *need_offsets = r == 0;
1817         } else {
1818                 /* Align contents to 8 byte boundary */
1819                 if (!message_extend_body(m, 8, 0, false))
1820                         return -ENOMEM;
1821         }
1822
1823         return 0;
1824 }
1825
1826 _public_ int sd_bus_message_open_container(
1827                 sd_bus_message *m,
1828                 char type,
1829                 const char *contents) {
1830
1831         struct bus_container *c, *w;
1832         uint32_t *array_size = NULL;
1833         char *signature;
1834         size_t before, begin;
1835         bool need_offsets = false;
1836         int r;
1837
1838         assert_return(m, -EINVAL);
1839         assert_return(!m->sealed, -EPERM);
1840         assert_return(contents, -EINVAL);
1841         assert_return(!m->poisoned, -ESTALE);
1842
1843         /* Make sure we have space for one more container */
1844         w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1845         if (!w) {
1846                 m->poisoned = true;
1847                 return -ENOMEM;
1848         }
1849
1850         m->containers = w;
1851
1852         c = message_get_container(m);
1853
1854         signature = strdup(contents);
1855         if (!signature) {
1856                 m->poisoned = true;
1857                 return -ENOMEM;
1858         }
1859
1860         /* Save old index in the parent container, in case we have to
1861          * abort this container */
1862         c->saved_index = c->index;
1863         before = m->header->body_size;
1864
1865         if (type == SD_BUS_TYPE_ARRAY)
1866                 r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
1867         else if (type == SD_BUS_TYPE_VARIANT)
1868                 r = bus_message_open_variant(m, c, contents);
1869         else if (type == SD_BUS_TYPE_STRUCT)
1870                 r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
1871         else if (type == SD_BUS_TYPE_DICT_ENTRY)
1872                 r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
1873         else
1874                 r = -EINVAL;
1875
1876         if (r < 0) {
1877                 free(signature);
1878                 return r;
1879         }
1880
1881         /* OK, let's fill it in */
1882         w += m->n_containers++;
1883         w->enclosing = type;
1884         w->signature = signature;
1885         w->index = 0;
1886         w->array_size = array_size;
1887         w->before = before;
1888         w->begin = begin;
1889         w->n_offsets = w->n_offsets_allocated = 0;
1890         w->offsets = NULL;
1891         w->need_offsets = need_offsets;
1892
1893         return 0;
1894 }
1895
1896 static size_t determine_word_size(size_t sz, size_t extra) {
1897         if (sz <= 0 && extra == 0)
1898                 return 0;
1899         else if (sz + extra <= 0xFF)
1900                 return 1;
1901         else if (sz + extra*2 <= 0xFFFF)
1902                 return 2;
1903         else if (sz + extra*4 <= 0xFFFFFFFF)
1904                 return 4;
1905         else
1906                 return 8;
1907 }
1908
1909 static size_t read_word_le(void *p, size_t sz) {
1910         union {
1911                 uint16_t u16;
1912                 uint32_t u32;
1913                 uint64_t u64;
1914         } x;
1915
1916         assert(p);
1917
1918         if (sz == 1)
1919                 return *(uint8_t*) p;
1920
1921         memcpy(&x, p, sz);
1922
1923         if (sz == 2)
1924                 return le16toh(x.u16);
1925         else if (sz == 4)
1926                 return le32toh(x.u32);
1927         else if (sz == 4)
1928                 return le64toh(x.u64);
1929
1930         assert_not_reached("unknown word width");
1931 }
1932
1933 static void write_word_le(void *p, size_t sz, size_t value) {
1934         union {
1935                 uint16_t u16;
1936                 uint32_t u32;
1937                 uint64_t u64;
1938         } x;
1939
1940         assert(p);
1941         assert(sz == 8 || (value < (1ULL << (sz*8))));
1942
1943         if (sz == 1) {
1944                 *(uint8_t*) p = value;
1945                 return;
1946         } else if (sz == 2)
1947                 x.u16 = htole16((uint16_t) value);
1948         else if (sz == 4)
1949                 x.u32 = htole32((uint32_t) value);
1950         else if (sz == 8)
1951                 x.u64 = htole64((uint64_t) value);
1952         else
1953                 assert_not_reached("unknown word width");
1954
1955         memcpy(p, &x, sz);
1956 }
1957
1958 static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
1959
1960         assert(m);
1961         assert(c);
1962
1963         if (!BUS_MESSAGE_IS_GVARIANT(m))
1964                 return 0;
1965
1966         if (c->need_offsets) {
1967                 size_t payload, sz, i;
1968                 uint8_t *a;
1969
1970                 /* Variable-width arrays */
1971
1972                 payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
1973                 sz = determine_word_size(payload, c->n_offsets);
1974
1975                 a = message_extend_body(m, 1, sz * c->n_offsets, true);
1976                 if (!a)
1977                         return -ENOMEM;
1978
1979                 for (i = 0; i < c->n_offsets; i++)
1980                         write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
1981         } else {
1982                 void *a;
1983
1984                 /* Fixed-width or empty arrays */
1985
1986                 a = message_extend_body(m, 1, 0, true); /* let's add offset to parent */
1987                 if (!a)
1988                         return -ENOMEM;
1989         }
1990
1991         return 0;
1992 }
1993
1994 static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
1995         uint8_t *a;
1996         size_t l;
1997
1998         assert(m);
1999         assert(c);
2000
2001         if (!BUS_MESSAGE_IS_GVARIANT(m))
2002                 return 0;
2003
2004         l = strlen(c->signature);
2005
2006         a = message_extend_body(m, 1, 1 + l, true);
2007         if (!a)
2008                 return -ENOMEM;
2009
2010         a[0] = 0;
2011         memcpy(a+1, c->signature, l);
2012
2013         return 0;
2014 }
2015
2016 static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
2017         size_t n_variable = 0;
2018         unsigned i = 0;
2019         const char *p;
2020         uint8_t *a;
2021         int r;
2022
2023         assert(m);
2024         assert(c);
2025
2026         if (!BUS_MESSAGE_IS_GVARIANT(m))
2027                 return 0;
2028
2029         p = strempty(c->signature);
2030         while (*p != 0) {
2031                 size_t n;
2032
2033                 r = signature_element_length(p, &n);
2034                 if (r < 0)
2035                         return r;
2036                 else {
2037                         char t[n+1];
2038
2039                         memcpy(t, p, n);
2040                         t[n] = 0;
2041
2042                         r = bus_gvariant_is_fixed_size(t);
2043                         if (r < 0)
2044                                 return r;
2045                 }
2046
2047                 assert(i <= c->n_offsets);
2048
2049                 /* We need to add an offset for each item that has a
2050                  * variable size and that is not the last one in the
2051                  * list */
2052                 if (r == 0 && p[n] != 0)
2053                         n_variable++;
2054
2055                 i++;
2056                 p += n;
2057         }
2058
2059         assert(i == c->n_offsets);
2060
2061         if (n_variable <= 0) {
2062                 a = message_extend_body(m, 1, 0, add_offset);
2063                 if (!a)
2064                         return -ENOMEM;
2065         } else {
2066                 size_t sz;
2067                 unsigned j;
2068
2069                 assert(c->offsets[c->n_offsets-1] == m->header->body_size);
2070
2071                 sz = determine_word_size(m->header->body_size - c->begin, n_variable);
2072
2073                 a = message_extend_body(m, 1, sz * n_variable, add_offset);
2074                 if (!a)
2075                         return -ENOMEM;
2076
2077                 p = strempty(c->signature);
2078                 for (i = 0, j = 0; i < c->n_offsets; i++) {
2079                         unsigned k;
2080                         size_t n;
2081
2082                         r = signature_element_length(p, &n);
2083                         if (r < 0)
2084                                 return r;
2085                         else {
2086                                 char t[n+1];
2087
2088                                 memcpy(t, p, n);
2089                                 t[n] = 0;
2090
2091                                 p += n;
2092
2093                                 r = bus_gvariant_is_fixed_size(t);
2094                                 if (r < 0)
2095                                         return r;
2096                                 if (r > 0 || p[0] == 0)
2097                                         continue;
2098                         }
2099
2100                         k = n_variable - 1 - j;
2101
2102                         write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
2103
2104                         j++;
2105                 }
2106         }
2107
2108         return 0;
2109 }
2110
2111 _public_ int sd_bus_message_close_container(sd_bus_message *m) {
2112         struct bus_container *c;
2113         int r;
2114
2115         assert_return(m, -EINVAL);
2116         assert_return(!m->sealed, -EPERM);
2117         assert_return(m->n_containers > 0, -EINVAL);
2118         assert_return(!m->poisoned, -ESTALE);
2119
2120         c = message_get_container(m);
2121
2122         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2123                 if (c->signature && c->signature[c->index] != 0)
2124                         return -EINVAL;
2125
2126         m->n_containers--;
2127
2128         if (c->enclosing == SD_BUS_TYPE_ARRAY)
2129                 r = bus_message_close_array(m, c);
2130         else if (c->enclosing == SD_BUS_TYPE_VARIANT)
2131                 r = bus_message_close_variant(m, c);
2132         else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
2133                 r = bus_message_close_struct(m, c, true);
2134         else
2135                 assert_not_reached("Unknown container type");
2136
2137         free(c->signature);
2138         free(c->offsets);
2139
2140         return r;
2141 }
2142
2143 typedef struct {
2144         const char *types;
2145         unsigned n_struct;
2146         unsigned n_array;
2147 } TypeStack;
2148
2149 static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
2150         assert(stack);
2151         assert(max > 0);
2152
2153         if (*i >= max)
2154                 return -EINVAL;
2155
2156         stack[*i].types = types;
2157         stack[*i].n_struct = n_struct;
2158         stack[*i].n_array = n_array;
2159         (*i)++;
2160
2161         return 0;
2162 }
2163
2164 static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
2165         assert(stack);
2166         assert(max > 0);
2167         assert(types);
2168         assert(n_struct);
2169         assert(n_array);
2170
2171         if (*i <= 0)
2172                 return 0;
2173
2174         (*i)--;
2175         *types = stack[*i].types;
2176         *n_struct = stack[*i].n_struct;
2177         *n_array = stack[*i].n_array;
2178
2179         return 1;
2180 }
2181
2182 int bus_message_append_ap(
2183                 sd_bus_message *m,
2184                 const char *types,
2185                 va_list ap) {
2186
2187         unsigned n_array, n_struct;
2188         TypeStack stack[BUS_CONTAINER_DEPTH];
2189         unsigned stack_ptr = 0;
2190         int r;
2191
2192         assert(m);
2193
2194         if (!types)
2195                 return 0;
2196
2197         n_array = (unsigned) -1;
2198         n_struct = strlen(types);
2199
2200         for (;;) {
2201                 const char *t;
2202
2203                 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
2204                         r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2205                         if (r < 0)
2206                                 return r;
2207                         if (r == 0)
2208                                 break;
2209
2210                         r = sd_bus_message_close_container(m);
2211                         if (r < 0)
2212                                 return r;
2213
2214                         continue;
2215                 }
2216
2217                 t = types;
2218                 if (n_array != (unsigned) -1)
2219                         n_array --;
2220                 else {
2221                         types ++;
2222                         n_struct--;
2223                 }
2224
2225                 switch (*t) {
2226
2227                 case SD_BUS_TYPE_BYTE: {
2228                         uint8_t x;
2229
2230                         x = (uint8_t) va_arg(ap, int);
2231                         r = sd_bus_message_append_basic(m, *t, &x);
2232                         break;
2233                 }
2234
2235                 case SD_BUS_TYPE_BOOLEAN:
2236                 case SD_BUS_TYPE_INT32:
2237                 case SD_BUS_TYPE_UINT32:
2238                 case SD_BUS_TYPE_UNIX_FD: {
2239                         uint32_t x;
2240
2241                         /* We assume a boolean is the same as int32_t */
2242                         assert_cc(sizeof(int32_t) == sizeof(int));
2243
2244                         x = va_arg(ap, uint32_t);
2245                         r = sd_bus_message_append_basic(m, *t, &x);
2246                         break;
2247                 }
2248
2249                 case SD_BUS_TYPE_INT16:
2250                 case SD_BUS_TYPE_UINT16: {
2251                         uint16_t x;
2252
2253                         x = (uint16_t) va_arg(ap, int);
2254                         r = sd_bus_message_append_basic(m, *t, &x);
2255                         break;
2256                 }
2257
2258                 case SD_BUS_TYPE_INT64:
2259                 case SD_BUS_TYPE_UINT64:
2260                 case SD_BUS_TYPE_DOUBLE: {
2261                         uint64_t x;
2262
2263                         x = va_arg(ap, uint64_t);
2264                         r = sd_bus_message_append_basic(m, *t, &x);
2265                         break;
2266                 }
2267
2268                 case SD_BUS_TYPE_STRING:
2269                 case SD_BUS_TYPE_OBJECT_PATH:
2270                 case SD_BUS_TYPE_SIGNATURE: {
2271                         const char *x;
2272
2273                         x = va_arg(ap, const char*);
2274                         r = sd_bus_message_append_basic(m, *t, x);
2275                         break;
2276                 }
2277
2278                 case SD_BUS_TYPE_ARRAY: {
2279                         size_t k;
2280
2281                         r = signature_element_length(t + 1, &k);
2282                         if (r < 0)
2283                                 return r;
2284
2285                         {
2286                                 char s[k + 1];
2287                                 memcpy(s, t + 1, k);
2288                                 s[k] = 0;
2289
2290                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
2291                                 if (r < 0)
2292                                         return r;
2293                         }
2294
2295                         if (n_array == (unsigned) -1) {
2296                                 types += k;
2297                                 n_struct -= k;
2298                         }
2299
2300                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2301                         if (r < 0)
2302                                 return r;
2303
2304                         types = t + 1;
2305                         n_struct = k;
2306                         n_array = va_arg(ap, unsigned);
2307
2308                         break;
2309                 }
2310
2311                 case SD_BUS_TYPE_VARIANT: {
2312                         const char *s;
2313
2314                         s = va_arg(ap, const char*);
2315                         if (!s)
2316                                 return -EINVAL;
2317
2318                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
2319                         if (r < 0)
2320                                 return r;
2321
2322                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2323                         if (r < 0)
2324                                 return r;
2325
2326                         types = s;
2327                         n_struct = strlen(s);
2328                         n_array = (unsigned) -1;
2329
2330                         break;
2331                 }
2332
2333                 case SD_BUS_TYPE_STRUCT_BEGIN:
2334                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2335                         size_t k;
2336
2337                         r = signature_element_length(t, &k);
2338                         if (r < 0)
2339                                 return r;
2340
2341                         {
2342                                 char s[k - 1];
2343
2344                                 memcpy(s, t + 1, k - 2);
2345                                 s[k - 2] = 0;
2346
2347                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2348                                 if (r < 0)
2349                                         return r;
2350                         }
2351
2352                         if (n_array == (unsigned) -1) {
2353                                 types += k - 1;
2354                                 n_struct -= k - 1;
2355                         }
2356
2357                         r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2358                         if (r < 0)
2359                                 return r;
2360
2361                         types = t + 1;
2362                         n_struct = k - 2;
2363                         n_array = (unsigned) -1;
2364
2365                         break;
2366                 }
2367
2368                 default:
2369                         r = -EINVAL;
2370                 }
2371
2372                 if (r < 0)
2373                         return r;
2374         }
2375
2376         return 1;
2377 }
2378
2379 _public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
2380         va_list ap;
2381         int r;
2382
2383         assert_return(m, -EINVAL);
2384         assert_return(types, -EINVAL);
2385         assert_return(!m->sealed, -EPERM);
2386         assert_return(!m->poisoned, -ESTALE);
2387
2388         va_start(ap, types);
2389         r = bus_message_append_ap(m, types, ap);
2390         va_end(ap);
2391
2392         return r;
2393 }
2394
2395 _public_ int sd_bus_message_append_array_space(
2396                 sd_bus_message *m,
2397                 char type,
2398                 size_t size,
2399                 void **ptr) {
2400
2401         ssize_t align, sz;
2402         void *a;
2403         int r;
2404
2405         assert_return(m, -EINVAL);
2406         assert_return(!m->sealed, -EPERM);
2407         assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
2408         assert_return(ptr || size == 0, -EINVAL);
2409         assert_return(!m->poisoned, -ESTALE);
2410
2411         /* alignment and size of the trivial types (except bool) is
2412          * identical for gvariant and dbus1 marshalling */
2413         align = bus_type_get_alignment(type);
2414         sz = bus_type_get_size(type);
2415
2416         assert_se(align > 0);
2417         assert_se(sz > 0);
2418
2419         if (size % sz != 0)
2420                 return -EINVAL;
2421
2422         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2423         if (r < 0)
2424                 return r;
2425
2426         a = message_extend_body(m, align, size, false);
2427         if (!a)
2428                 return -ENOMEM;
2429
2430         r = sd_bus_message_close_container(m);
2431         if (r < 0)
2432                 return r;
2433
2434         *ptr = a;
2435         return 0;
2436 }
2437
2438 _public_ int sd_bus_message_append_array(sd_bus_message *m,
2439                                          char type,
2440                                          const void *ptr,
2441                                          size_t size) {
2442         int r;
2443         void *p;
2444
2445         assert_return(m, -EINVAL);
2446         assert_return(!m->sealed, -EPERM);
2447         assert_return(bus_type_is_trivial(type), -EINVAL);
2448         assert_return(ptr || size == 0, -EINVAL);
2449         assert_return(!m->poisoned, -ESTALE);
2450
2451         r = sd_bus_message_append_array_space(m, type, size, &p);
2452         if (r < 0)
2453                 return r;
2454
2455         if (size > 0)
2456                 memcpy(p, ptr, size);
2457
2458         return 0;
2459 }
2460
2461 _public_ int sd_bus_message_append_array_iovec(
2462                 sd_bus_message *m,
2463                 char type,
2464                 const struct iovec *iov,
2465                 unsigned n) {
2466
2467         size_t size;
2468         unsigned i;
2469         void *p;
2470         int r;
2471
2472         assert_return(m, -EINVAL);
2473         assert_return(!m->sealed, -EPERM);
2474         assert_return(bus_type_is_trivial(type), -EINVAL);
2475         assert_return(iov || n == 0, -EINVAL);
2476         assert_return(!m->poisoned, -ESTALE);
2477
2478         size = IOVEC_TOTAL_SIZE(iov, n);
2479
2480         r = sd_bus_message_append_array_space(m, type, size, &p);
2481         if (r < 0)
2482                 return r;
2483
2484         for (i = 0; i < n; i++) {
2485
2486                 if (iov[i].iov_base)
2487                         memcpy(p, iov[i].iov_base, iov[i].iov_len);
2488                 else
2489                         memset(p, 0, iov[i].iov_len);
2490
2491                 p = (uint8_t*) p + iov[i].iov_len;
2492         }
2493
2494         return 0;
2495 }
2496
2497 _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
2498                                                char type,
2499                                                sd_memfd *memfd) {
2500         _cleanup_close_ int copy_fd = -1;
2501         struct bus_body_part *part;
2502         ssize_t align, sz;
2503         uint64_t size;
2504         void *a;
2505         int r;
2506
2507         if (!m)
2508                 return -EINVAL;
2509         if (!memfd)
2510                 return -EINVAL;
2511         if (m->sealed)
2512                 return -EPERM;
2513         if (!bus_type_is_trivial(type))
2514                 return -EINVAL;
2515         if (m->poisoned)
2516                 return -ESTALE;
2517
2518         r = sd_memfd_set_sealed(memfd, true);
2519         if (r < 0)
2520                 return r;
2521
2522         copy_fd = sd_memfd_dup_fd(memfd);
2523         if (copy_fd < 0)
2524                 return copy_fd;
2525
2526         r = sd_memfd_get_size(memfd, &size);
2527         if (r < 0)
2528                 return r;
2529
2530         align = bus_type_get_alignment(type);
2531         sz = bus_type_get_size(type);
2532
2533         assert_se(align > 0);
2534         assert_se(sz > 0);
2535
2536         if (size % sz != 0)
2537                 return -EINVAL;
2538
2539         if (size > (uint64_t) (uint32_t) -1)
2540                 return -EINVAL;
2541
2542         r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2543         if (r < 0)
2544                 return r;
2545
2546         a = message_extend_body(m, align, 0, false);
2547         if (!a)
2548                 return -ENOMEM;
2549
2550         part = message_append_part(m);
2551         if (!part)
2552                 return -ENOMEM;
2553
2554         part->memfd = copy_fd;
2555         part->sealed = true;
2556         part->size = size;
2557         copy_fd = -1;
2558
2559         m->header->body_size += size;
2560         message_extend_containers(m, size);
2561
2562         return sd_bus_message_close_container(m);
2563 }
2564
2565 _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) {
2566         _cleanup_close_ int copy_fd = -1;
2567         struct bus_body_part *part;
2568         struct bus_container *c;
2569         uint64_t size;
2570         void *a;
2571         int r;
2572
2573         assert_return(m, -EINVAL);
2574         assert_return(memfd, -EINVAL);
2575         assert_return(!m->sealed, -EPERM);
2576         assert_return(!m->poisoned, -ESTALE);
2577
2578         r = sd_memfd_set_sealed(memfd, true);
2579         if (r < 0)
2580                 return r;
2581
2582         copy_fd = sd_memfd_dup_fd(memfd);
2583         if (copy_fd < 0)
2584                 return copy_fd;
2585
2586         r = sd_memfd_get_size(memfd, &size);
2587         if (r < 0)
2588                 return r;
2589
2590         /* We require this to be NUL terminated */
2591         if (size == 0)
2592                 return -EINVAL;
2593
2594         if (size > (uint64_t) (uint32_t) -1)
2595                 return -EINVAL;
2596
2597         c = message_get_container(m);
2598         if (c->signature && c->signature[c->index]) {
2599                 /* Container signature is already set */
2600
2601                 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
2602                         return -ENXIO;
2603         } else {
2604                 char *e;
2605
2606                 /* Maybe we can append to the signature? But only if this is the top-level container*/
2607                 if (c->enclosing != 0)
2608                         return -ENXIO;
2609
2610                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
2611                 if (!e) {
2612                         m->poisoned = true;
2613                         return -ENOMEM;
2614                 }
2615         }
2616
2617         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
2618                 a = message_extend_body(m, 4, 4, false);
2619                 if (!a)
2620                         return -ENOMEM;
2621
2622                 *(uint32_t*) a = size - 1;
2623         }
2624
2625         part = message_append_part(m);
2626         if (!part)
2627                 return -ENOMEM;
2628
2629         part->memfd = copy_fd;
2630         part->sealed = true;
2631         part->size = size;
2632         copy_fd = -1;
2633
2634         m->header->body_size += size;
2635         message_extend_containers(m, size);
2636
2637         if (BUS_MESSAGE_IS_GVARIANT(m)) {
2638                 r = message_add_offset(m, m->header->body_size);
2639                 if (r < 0) {
2640                         m->poisoned = true;
2641                         return -ENOMEM;
2642                 }
2643         }
2644
2645         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2646                 c->index++;
2647
2648         return 0;
2649 }
2650
2651 _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
2652         char **i;
2653         int r;
2654
2655         assert_return(m, -EINVAL);
2656         assert_return(!m->sealed, -EPERM);
2657         assert_return(!m->poisoned, -ESTALE);
2658
2659         r = sd_bus_message_open_container(m, 'a', "s");
2660         if (r < 0)
2661                 return r;
2662
2663         STRV_FOREACH(i, l) {
2664                 r = sd_bus_message_append_basic(m, 's', *i);
2665                 if (r < 0)
2666                         return r;
2667         }
2668
2669         return sd_bus_message_close_container(m);
2670 }
2671
2672 static int bus_message_close_header(sd_bus_message *m) {
2673         uint8_t *a;
2674         size_t sz, i;
2675
2676         assert(m);
2677
2678         if (!BUS_MESSAGE_IS_GVARIANT(m))
2679                 return 0;
2680
2681         if (m->n_header_offsets < 1)
2682                 return 0;
2683
2684         assert(m->header->fields_size == m->header_offsets[m->n_header_offsets-1]);
2685
2686         sz = determine_word_size(m->header->fields_size, m->n_header_offsets);
2687
2688         a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
2689         if (!a)
2690                 return -ENOMEM;
2691
2692         for (i = 0; i < m->n_header_offsets; i++)
2693                 write_word_le(a + sz*i, sz, m->header_offsets[i]);
2694
2695         return 0;
2696 }
2697
2698 int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2699         struct bus_body_part *part;
2700         size_t l, a;
2701         unsigned i;
2702         int r;
2703
2704         assert(m);
2705
2706         if (m->sealed)
2707                 return -EPERM;
2708
2709         if (m->n_containers > 0)
2710                 return -EBADMSG;
2711
2712         if (m->poisoned)
2713                 return -ESTALE;
2714
2715         /* In vtables the return signature of method calls is listed,
2716          * let's check if they match if this is a response */
2717         if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
2718             m->enforced_reply_signature &&
2719             !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
2720                 return -ENOMSG;
2721
2722         /* If gvariant marshalling is used we need to close the body structure */
2723         r = bus_message_close_struct(m, &m->root_container, false);
2724         if (r < 0)
2725                 return r;
2726
2727         /* If there's a non-trivial signature set, then add it in here */
2728         if (!isempty(m->root_container.signature)) {
2729                 r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
2730                 if (r < 0)
2731                         return r;
2732         }
2733
2734         if (m->n_fds > 0) {
2735                 r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2736                 if (r < 0)
2737                         return r;
2738         }
2739
2740         r = bus_message_close_header(m);
2741         if (r < 0)
2742                 return r;
2743
2744         m->header->serial = serial;
2745
2746         /* Add padding at the end of the fields part, since we know
2747          * the body needs to start at an 8 byte alignment. We made
2748          * sure we allocated enough space for this, so all we need to
2749          * do here is to zero it out. */
2750         l = BUS_MESSAGE_FIELDS_SIZE(m);
2751         a = ALIGN8(l) - l;
2752         if (a > 0)
2753                 memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a);
2754
2755         /* If this is something we can send as memfd, then let's seal
2756         the memfd now. Note that we can send memfds as payload only
2757         for directed messages, and not for broadcasts. */
2758         if (m->destination && m->bus && m->bus->use_memfd) {
2759                 MESSAGE_FOREACH_PART(part, i, m)
2760                         if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) {
2761                                 bus_body_part_unmap(part);
2762
2763                                 if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0)
2764                                         part->sealed = true;
2765                         }
2766         }
2767
2768         m->root_container.end = BUS_MESSAGE_BODY_SIZE(m);
2769         m->root_container.index = 0;
2770         m->root_container.offset_index = 0;
2771         m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
2772
2773         m->sealed = true;
2774
2775         return 0;
2776 }
2777
2778 int bus_body_part_map(struct bus_body_part *part) {
2779         void *p;
2780         size_t psz;
2781
2782         assert_se(part);
2783
2784         if (part->data)
2785                 return 0;
2786
2787         if (part->size <= 0)
2788                 return 0;
2789
2790         /* For smaller zero parts (as used for padding) we don't need to map anything... */
2791         if (part->memfd < 0 && part->is_zero && part->size < 8) {
2792                 static const uint8_t zeroes[7] = { };
2793                 part->data = (void*) zeroes;
2794                 return 0;
2795         }
2796
2797         psz = PAGE_ALIGN(part->size);
2798
2799         if (part->memfd >= 0)
2800                 p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0);
2801         else if (part->is_zero)
2802                 p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
2803         else
2804                 return -EINVAL;
2805
2806         if (p == MAP_FAILED)
2807                 return -errno;
2808
2809         part->mapped = psz;
2810         part->data = p;
2811         part->munmap_this = true;
2812
2813         return 0;
2814 }
2815
2816 void bus_body_part_unmap(struct bus_body_part *part) {
2817
2818         assert_se(part);
2819
2820         if (part->memfd < 0)
2821                 return;
2822
2823         if (!part->data)
2824                 return;
2825
2826         if (!part->munmap_this)
2827                 return;
2828
2829         assert_se(munmap(part->data, part->mapped) == 0);
2830
2831         part->data = NULL;
2832         part->mapped = 0;
2833         part->munmap_this = false;
2834
2835         return;
2836 }
2837
2838 static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
2839         size_t k, start, end;
2840
2841         assert(rindex);
2842         assert(align > 0);
2843
2844         start = ALIGN_TO((size_t) *rindex, align);
2845         end = start + nbytes;
2846
2847         if (end > sz)
2848                 return -EBADMSG;
2849
2850         /* Verify that padding is 0 */
2851         for (k = *rindex; k < start; k++)
2852                 if (((const uint8_t*) p)[k] != 0)
2853                         return -EBADMSG;
2854
2855         if (r)
2856                 *r = (uint8_t*) p + start;
2857
2858         *rindex = end;
2859
2860         return 1;
2861 }
2862
2863 static bool message_end_of_signature(sd_bus_message *m) {
2864         struct bus_container *c;
2865
2866         assert(m);
2867
2868         c = message_get_container(m);
2869         return !c->signature || c->signature[c->index] == 0;
2870 }
2871
2872 static bool message_end_of_array(sd_bus_message *m, size_t index) {
2873         struct bus_container *c;
2874
2875         assert(m);
2876
2877         c = message_get_container(m);
2878         if (c->enclosing != SD_BUS_TYPE_ARRAY)
2879                 return false;
2880
2881         if (BUS_MESSAGE_IS_GVARIANT(m))
2882                 return index >= c->end;
2883         else {
2884                 assert(c->array_size);
2885                 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
2886         }
2887 }
2888
2889 _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
2890         assert_return(m, -EINVAL);
2891         assert_return(m->sealed, -EPERM);
2892
2893         if (complete && m->n_containers > 0)
2894                 return false;
2895
2896         if (message_end_of_signature(m))
2897                 return true;
2898
2899         if (message_end_of_array(m, m->rindex))
2900                 return true;
2901
2902         return false;
2903 }
2904
2905 static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
2906         struct bus_body_part *part;
2907         size_t begin;
2908         int r;
2909
2910         assert(m);
2911
2912         if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
2913                 part = m->cached_rindex_part;
2914                 begin = m->cached_rindex_part_begin;
2915         } else {
2916                 part = &m->body;
2917                 begin = 0;
2918         }
2919
2920         while (part) {
2921                 if (index < begin)
2922                         return NULL;
2923
2924                 if (index + sz <= begin + part->size) {
2925
2926                         r = bus_body_part_map(part);
2927                         if (r < 0)
2928                                 return NULL;
2929
2930                         if (p)
2931                                 *p = (uint8_t*) part->data + index - begin;
2932
2933                         m->cached_rindex_part = part;
2934                         m->cached_rindex_part_begin = begin;
2935
2936                         return part;
2937                 }
2938
2939                 begin += part->size;
2940                 part = part->next;
2941         }
2942
2943         return NULL;
2944 }
2945
2946 static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
2947         int r;
2948
2949         assert(m);
2950         assert(c);
2951         assert(rindex);
2952
2953         if (!BUS_MESSAGE_IS_GVARIANT(m))
2954                 return 0;
2955
2956         if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2957                 int sz;
2958
2959                 sz = bus_gvariant_get_size(c->signature);
2960                 if (sz < 0) {
2961                         int alignment;
2962
2963                         if (c->offset_index+1 >= c->n_offsets)
2964                                 goto end;
2965
2966                         /* Variable-size array */
2967
2968                         alignment = bus_gvariant_get_alignment(c->signature);
2969                         assert(alignment > 0);
2970
2971                         *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
2972                         c->item_size = c->offsets[c->offset_index+1] - *rindex;
2973                 } else {
2974
2975                         if (c->offset_index+1 >= (c->end-c->begin)/sz)
2976                                 goto end;
2977
2978                         /* Fixed-size array */
2979                         *rindex = c->begin + (c->offset_index+1) * sz;
2980                         c->item_size = sz;
2981                 }
2982
2983                 c->offset_index++;
2984
2985         } else if (c->enclosing == 0 ||
2986                    c->enclosing == SD_BUS_TYPE_STRUCT ||
2987                    c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
2988
2989                 int alignment;
2990                 size_t n, j;
2991
2992                 if (c->offset_index+1 >= c->n_offsets)
2993                         goto end;
2994
2995                 r = signature_element_length(c->signature + c->index, &n);
2996                 if (r < 0)
2997                         return r;
2998
2999                 r = signature_element_length(c->signature + c->index + n, &j);
3000                 if (r < 0)
3001                         return r;
3002                 else {
3003                         char t[j+1];
3004                         memcpy(t, c->signature + c->index + n, j);
3005                         t[j] = 0;
3006
3007                         alignment = bus_gvariant_get_alignment(t);
3008                 }
3009
3010                 assert(alignment > 0);
3011
3012                 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
3013                 c->item_size = c->offsets[c->offset_index+1] - *rindex;
3014
3015                 c->offset_index++;
3016
3017         } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
3018                 goto end;
3019         else
3020                 assert_not_reached("Unknown container type");
3021
3022         return 0;
3023
3024 end:
3025         /* Reached the end */
3026         *rindex = c->end;
3027         c->item_size = 0;
3028         return 0;
3029 }
3030
3031
3032 static int message_peek_body(
3033                 sd_bus_message *m,
3034                 size_t *rindex,
3035                 size_t align,
3036                 size_t nbytes,
3037                 void **ret) {
3038
3039         size_t k, start, end, padding;
3040         struct bus_body_part *part;
3041         uint8_t *q;
3042
3043         assert(m);
3044         assert(rindex);
3045         assert(align > 0);
3046
3047         start = ALIGN_TO((size_t) *rindex, align);
3048         padding = start - *rindex;
3049         end = start + nbytes;
3050
3051         if (end > BUS_MESSAGE_BODY_SIZE(m))
3052                 return -EBADMSG;
3053
3054         part = find_part(m, *rindex, padding, (void**) &q);
3055         if (!part)
3056                 return -EBADMSG;
3057
3058         if (q) {
3059                 /* Verify padding */
3060                 for (k = 0; k < padding; k++)
3061                         if (q[k] != 0)
3062                                 return -EBADMSG;
3063         }
3064
3065         part = find_part(m, start, nbytes, (void**) &q);
3066         if (!part || !q)
3067                 return -EBADMSG;
3068
3069         *rindex = end;
3070
3071         if (ret)
3072                 *ret = q;
3073
3074         return 0;
3075 }
3076
3077 static bool validate_nul(const char *s, size_t l) {
3078
3079         /* Check for NUL chars in the string */
3080         if (memchr(s, 0, l))
3081                 return false;
3082
3083         /* Check for NUL termination */
3084         if (s[l] != 0)
3085                 return false;
3086
3087         return true;
3088 }
3089
3090 static bool validate_string(const char *s, size_t l) {
3091
3092         if (!validate_nul(s, l))
3093                 return false;
3094
3095         /* Check if valid UTF8 */
3096         if (!utf8_is_valid(s))
3097                 return false;
3098
3099         return true;
3100 }
3101
3102 static bool validate_signature(const char *s, size_t l) {
3103
3104         if (!validate_nul(s, l))
3105                 return false;
3106
3107         /* Check if valid signature */
3108         if (!signature_is_valid(s, true))
3109                 return false;
3110
3111         return true;
3112 }
3113
3114 static bool validate_object_path(const char *s, size_t l) {
3115
3116         if (!validate_nul(s, l))
3117                 return false;
3118
3119         if (!object_path_is_valid(s))
3120                 return false;
3121
3122         return true;
3123 }
3124
3125 _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
3126         struct bus_container *c;
3127         size_t rindex;
3128         void *q;
3129         int r;
3130
3131         assert_return(m, -EINVAL);
3132         assert_return(m->sealed, -EPERM);
3133         assert_return(bus_type_is_basic(type), -EINVAL);
3134
3135         if (message_end_of_signature(m))
3136                 return -ENXIO;
3137
3138         if (message_end_of_array(m, m->rindex))
3139                 return 0;
3140
3141         c = message_get_container(m);
3142         if (c->signature[c->index] != type)
3143                 return -ENXIO;
3144
3145         rindex = m->rindex;
3146
3147         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3148
3149                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
3150                         bool ok;
3151
3152                         r = message_peek_body(m, &rindex, 1, c->item_size, &q);
3153                         if (r < 0)
3154                                 return r;
3155
3156                         if (type == SD_BUS_TYPE_STRING)
3157                                 ok = validate_string(q, c->item_size-1);
3158                         else if (type == SD_BUS_TYPE_OBJECT_PATH)
3159                                 ok = validate_object_path(q, c->item_size-1);
3160                         else
3161                                 ok = validate_signature(q, c->item_size-1);
3162
3163                         if (!ok)
3164                                 return -EBADMSG;
3165
3166                         if (p)
3167                                 *(const char**) p = q;
3168                 } else {
3169                         int sz, align;
3170
3171                         sz = bus_gvariant_get_size(CHAR_TO_STR(type));
3172                         assert(sz > 0);
3173                         if ((size_t) sz != c->item_size)
3174                                 return -EBADMSG;
3175
3176                         align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
3177                         assert(align > 0);
3178
3179                         r = message_peek_body(m, &rindex, align, c->item_size, &q);
3180                         if (r < 0)
3181                                 return r;
3182
3183                         switch (type) {
3184
3185                         case SD_BUS_TYPE_BYTE:
3186                                 if (p)
3187                                         *(uint8_t*) p = *(uint8_t*) q;
3188                                 break;
3189
3190                         case SD_BUS_TYPE_BOOLEAN:
3191                                 if (p)
3192                                         *(int*) p = !!*(uint8_t*) q;
3193                                 break;
3194
3195                         case SD_BUS_TYPE_INT16:
3196                         case SD_BUS_TYPE_UINT16:
3197                                 if (p)
3198                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3199                                 break;
3200
3201                         case SD_BUS_TYPE_INT32:
3202                         case SD_BUS_TYPE_UINT32:
3203                                 if (p)
3204                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3205                                 break;
3206
3207                         case SD_BUS_TYPE_INT64:
3208                         case SD_BUS_TYPE_UINT64:
3209                         case SD_BUS_TYPE_DOUBLE:
3210                                 if (p)
3211                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3212                                 break;
3213
3214                         case SD_BUS_TYPE_UNIX_FD: {
3215                                 uint32_t j;
3216
3217                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3218                                 if (j >= m->n_fds)
3219                                         return -EBADMSG;
3220
3221                                 if (p)
3222                                         *(int*) p = m->fds[j];
3223
3224                                 break;
3225                         }
3226
3227                         default:
3228                                 assert_not_reached("unexpected type");
3229                         }
3230                 }
3231
3232                 r = container_next_item(m, c, &rindex);
3233                 if (r < 0)
3234                         return r;
3235         } else {
3236
3237                 rindex = m->rindex;
3238
3239                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
3240                         uint32_t l;
3241                         bool ok;
3242
3243                         r = message_peek_body(m, &rindex, 4, 4, &q);
3244                         if (r < 0)
3245                                 return r;
3246
3247                         l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3248                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3249                         if (r < 0)
3250                                 return r;
3251
3252                         if (type == SD_BUS_TYPE_OBJECT_PATH)
3253                                 ok = validate_object_path(q, l);
3254                         else
3255                                 ok = validate_string(q, l);
3256                         if (!ok)
3257                                 return -EBADMSG;
3258
3259                         if (p)
3260                                 *(const char**) p = q;
3261
3262                 } else if (type == SD_BUS_TYPE_SIGNATURE) {
3263                         uint8_t l;
3264
3265                         r = message_peek_body(m, &rindex, 1, 1, &q);
3266                         if (r < 0)
3267                                 return r;
3268
3269                         l = *(uint8_t*) q;
3270                         r = message_peek_body(m, &rindex, 1, l+1, &q);
3271                         if (r < 0)
3272                                 return r;
3273
3274                         if (!validate_signature(q, l))
3275                                 return -EBADMSG;
3276
3277                         if (p)
3278                                 *(const char**) p = q;
3279
3280                 } else {
3281                         ssize_t sz, align;
3282
3283                         align = bus_type_get_alignment(type);
3284                         assert(align > 0);
3285
3286                         sz = bus_type_get_size(type);
3287                         assert(sz > 0);
3288
3289                         r = message_peek_body(m, &rindex, align, sz, &q);
3290                         if (r < 0)
3291                                 return r;
3292
3293                         switch (type) {
3294
3295                         case SD_BUS_TYPE_BYTE:
3296                                 if (p)
3297                                         *(uint8_t*) p = *(uint8_t*) q;
3298                                 break;
3299
3300                         case SD_BUS_TYPE_BOOLEAN:
3301                                 if (p)
3302                                         *(int*) p = !!*(uint32_t*) q;
3303                                 break;
3304
3305                         case SD_BUS_TYPE_INT16:
3306                         case SD_BUS_TYPE_UINT16:
3307                                 if (p)
3308                                         *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
3309                                 break;
3310
3311                         case SD_BUS_TYPE_INT32:
3312                         case SD_BUS_TYPE_UINT32:
3313                                 if (p)
3314                                         *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3315                                 break;
3316
3317                         case SD_BUS_TYPE_INT64:
3318                         case SD_BUS_TYPE_UINT64:
3319                         case SD_BUS_TYPE_DOUBLE:
3320                                 if (p)
3321                                         *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
3322                                 break;
3323
3324                         case SD_BUS_TYPE_UNIX_FD: {
3325                                 uint32_t j;
3326
3327                                 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
3328                                 if (j >= m->n_fds)
3329                                         return -EBADMSG;
3330
3331                                 if (p)
3332                                         *(int*) p = m->fds[j];
3333                                 break;
3334                         }
3335
3336                         default:
3337                                 assert_not_reached("Unknown basic type...");
3338                         }
3339                 }
3340         }
3341
3342         m->rindex = rindex;
3343
3344         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3345                 c->index++;
3346
3347         return 1;
3348 }
3349
3350 static int bus_message_enter_array(
3351                 sd_bus_message *m,
3352                 struct bus_container *c,
3353                 const char *contents,
3354                 uint32_t **array_size,
3355                 size_t *item_size,
3356                 size_t **offsets,
3357                 size_t *n_offsets) {
3358
3359         size_t rindex;
3360         void *q;
3361         int r, alignment;
3362
3363         assert(m);
3364         assert(c);
3365         assert(contents);
3366         assert(array_size);
3367         assert(item_size);
3368         assert(offsets);
3369         assert(n_offsets);
3370
3371         if (!signature_is_single(contents, true))
3372                 return -EINVAL;
3373
3374         if (!c->signature || c->signature[c->index] == 0)
3375                 return -ENXIO;
3376
3377         if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
3378                 return -ENXIO;
3379
3380         if (!startswith(c->signature + c->index + 1, contents))
3381                 return -ENXIO;
3382
3383         rindex = m->rindex;
3384
3385         if (!BUS_MESSAGE_IS_GVARIANT(m)) {
3386                 /* dbus1 */
3387
3388                 r = message_peek_body(m, &rindex, 4, 4, &q);
3389                 if (r < 0)
3390                         return r;
3391
3392                 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
3393                         return -EBADMSG;
3394
3395                 alignment = bus_type_get_alignment(contents[0]);
3396                 if (alignment < 0)
3397                         return alignment;
3398
3399                 r = message_peek_body(m, &rindex, alignment, 0, NULL);
3400                 if (r < 0)
3401                         return r;
3402
3403                 *array_size = (uint32_t*) q;
3404
3405         } else if (c->item_size <= 0) {
3406
3407                 /* gvariant: empty array */
3408                 *item_size = 0;
3409                 *offsets = NULL;
3410                 *n_offsets = 0;
3411
3412         } else if (bus_gvariant_is_fixed_size(contents)) {
3413
3414                 /* gvariant: fixed length array */
3415                 *item_size = bus_gvariant_get_size(contents);
3416                 *offsets = NULL;
3417                 *n_offsets = 0;
3418
3419         } else {
3420                 size_t where, p = 0, framing, sz;
3421                 unsigned i;
3422
3423                 /* gvariant: variable length array */
3424                 sz = determine_word_size(c->item_size, 0);
3425
3426                 where = rindex + c->item_size - sz;
3427                 r = message_peek_body(m, &where, 1, sz, &q);
3428                 if (r < 0)
3429                         return r;
3430
3431                 framing = read_word_le(q, sz);
3432                 if (framing > c->item_size - sz)
3433                         return -EBADMSG;
3434                 if ((c->item_size - framing) % sz != 0)
3435                         return -EBADMSG;
3436
3437                 *n_offsets = (c->item_size - framing) / sz;
3438
3439                 where = rindex + framing;
3440                 r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
3441                 if (r < 0)
3442                         return r;
3443
3444                 *offsets = new(size_t, *n_offsets);
3445                 if (!*offsets)
3446                         return -ENOMEM;
3447
3448                 for (i = 0; i < *n_offsets; i++) {
3449                         size_t x;
3450
3451                         x = read_word_le((uint8_t*) q + i * sz, sz);
3452                         if (x > c->item_size - sz)
3453                                 return -EBADMSG;
3454                         if (x < p)
3455                                 return -EBADMSG;
3456
3457                         (*offsets)[i] = rindex + x;
3458                         p = x;
3459                 }
3460
3461                 *item_size = (*offsets)[0] - rindex;
3462         }
3463
3464         m->rindex = rindex;
3465
3466         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3467                 c->index += 1 + strlen(contents);
3468
3469         return 1;
3470 }
3471
3472 static int bus_message_enter_variant(
3473                 sd_bus_message *m,
3474                 struct bus_container *c,
3475                 const char *contents,
3476                 size_t *item_size) {
3477
3478         size_t rindex;
3479         uint8_t l;
3480         void *q;
3481         int r;
3482
3483         assert(m);
3484         assert(c);
3485         assert(contents);
3486         assert(item_size);
3487
3488         if (!signature_is_single(contents, false))
3489                 return -EINVAL;
3490
3491         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
3492                 return -EINVAL;
3493
3494         if (!c->signature || c->signature[c->index] == 0)
3495                 return -ENXIO;
3496
3497         if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
3498                 return -ENXIO;
3499
3500         rindex = m->rindex;
3501
3502         if (BUS_MESSAGE_IS_GVARIANT(m)) {
3503                 size_t k, where;
3504
3505                 k = strlen(contents);
3506                 if (1+k > c->item_size)
3507                         return -EBADMSG;
3508
3509                 where = rindex + c->item_size - (1+k);
3510                 r = message_peek_body(m, &where, 1, 1+k, &q);
3511                 if (r < 0)
3512                         return r;
3513
3514                 if (*(char*) q != 0)
3515                         return -EBADMSG;
3516
3517                 if (memcmp((uint8_t*) q+1, contents, k))
3518                         return -ENXIO;
3519
3520                 *item_size = c->item_size - (1+k);
3521
3522         } else {
3523                 r = message_peek_body(m, &rindex, 1, 1, &q);
3524                 if (r < 0)
3525                         return r;
3526
3527                 l = *(uint8_t*) q;
3528                 r = message_peek_body(m, &rindex, 1, l+1, &q);
3529                 if (r < 0)
3530                         return r;
3531
3532                 if (!validate_signature(q, l))
3533                         return -EBADMSG;
3534
3535                 if (!streq(q, contents))
3536                         return -ENXIO;
3537         }
3538
3539         m->rindex = rindex;
3540
3541         if (c->enclosing != SD_BUS_TYPE_ARRAY)
3542                 c->index++;
3543
3544         return 1;
3545 }
3546
3547 static int build_struct_offsets(
3548                 sd_bus_message *m,
3549                 const char *signature,
3550                 size_t size,
3551                 size_t *item_size,
3552                 size_t **offsets,
3553                 size_t *n_offsets) {
3554
3555         unsigned n_variable = 0, n_total = 0, v;
3556         size_t previous = 0, where;
3557         const char *p;
3558         size_t sz;
3559         void *q;
3560         int r;
3561
3562         assert(m);
3563         assert(item_size);
3564         assert(offsets);
3565         assert(n_offsets);
3566
3567         if (isempty(signature)) {
3568                 *item_size = 0;
3569                 *offsets = NULL;
3570                 *n_offsets = 0;
3571                 return 0;
3572         }
3573
3574         sz = determine_word_size(size, 0);
3575         if (sz <= 0)
3576                 return -EBADMSG;
3577
3578         /* First, loop over signature and count variable elements and
3579          * elements in general. We use this to know how large the
3580          * offset array is at the end of the structure. Note that
3581          * GVariant only stores offsets for all variable size elements
3582          * that are not the last item. */
3583
3584         p = signature;
3585         while (*p != 0) {
3586                 size_t n;
3587
3588                 r = signature_element_length(p, &n);
3589                 if (r < 0)
3590                         return r;
3591                 else {
3592                         char t[n+1];
3593
3594                         memcpy(t, p, n);
3595                         t[n] = 0;
3596
3597                         r = bus_gvariant_is_fixed_size(t);
3598                 }
3599
3600                 if (r < 0)
3601                         return r;
3602                 if (r == 0 && p[n] != 0) /* except the last item */
3603                         n_variable ++;
3604                 n_total++;
3605
3606                 p += n;
3607         }
3608
3609         if (size < n_variable * sz)
3610                 return -EBADMSG;
3611
3612         where = m->rindex + size - (n_variable * sz);
3613         r = message_peek_body(m, &where, 1, n_variable * sz, &q);
3614         if (r < 0)
3615                 return r;
3616
3617         v = n_variable;
3618
3619         *offsets = new(size_t, n_total);
3620         if (!*offsets)
3621                 return -ENOMEM;
3622
3623         *n_offsets = 0;
3624
3625         /* Second, loop again and build an offset table */
3626         p = signature;
3627         while (*p != 0) {
3628                 size_t n, offset;
3629                 int k;
3630
3631                 r = signature_element_length(p, &n);
3632                 if (r < 0)
3633                         return r;
3634                 else {
3635                         char t[n+1];
3636
3637                         memcpy(t, p, n);
3638                         t[n] = 0;
3639
3640                         k = bus_gvariant_get_size(t);
3641                         if (k < 0) {
3642                                 size_t x;
3643
3644                                 /* variable size */
3645                                 if (v > 0) {
3646                                         v--;
3647
3648                                         x = read_word_le((uint8_t*) q + v*sz, sz);
3649                                         if (x >= size)
3650                                                 return -EBADMSG;
3651                                         if (m->rindex + x < previous)
3652                                                 return -EBADMSG;
3653                                 } else
3654                                         /* The last item's end
3655                                          * is determined from
3656                                          * the start of the
3657                                          * offset array */
3658                                         x = size - (n_variable * sz);
3659
3660                                 offset = m->rindex + x;
3661
3662                         } else {
3663                                 size_t align;
3664
3665                                 /* fixed size */
3666                                 align = bus_gvariant_get_alignment(t);
3667                                 assert(align > 0);
3668
3669                                 offset = (*n_offsets == 0 ? m->rindex  : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
3670                         }
3671                 }
3672
3673                 previous = (*offsets)[(*n_offsets)++] = offset;
3674                 p += n;
3675         }
3676
3677         assert(v == 0);
3678         assert(*n_offsets == n_total);
3679
3680         *item_size = (*offsets)[0] - m->rindex;
3681         return 0;
3682 }
3683
3684 static int enter_struct_or_dict_entry(
3685                 sd_bus_message *m,
3686                 struct bus_container *c,
3687                 const char *contents,
3688                 size_t *item_size,
3689                 size_t **offsets,
3690                 size_t *n_offsets) {
3691
3692         int r;
3693
3694         assert(m);
3695         assert(c);
3696         assert(contents);
3697         assert(item_size);
3698         assert(offsets);
3699         assert(n_offsets);
3700
3701