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