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