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