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