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