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