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