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