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