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