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