]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
bus: also finish connection before returning from sd_bus_get_unique_name()
[thirdparty/systemd.git] / src / libsystemd-bus / bus-message.c
CommitLineData
de1c301e
LP
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
24#include "util.h"
9a17484d 25#include "utf8.h"
89ffcd2a 26#include "strv.h"
de1c301e 27
de1c301e 28#include "sd-bus.h"
9a17484d 29#include "bus-message.h"
de1c301e
LP
30#include "bus-internal.h"
31#include "bus-type.h"
32#include "bus-signature.h"
33
80a46c73
LP
34static int message_parse_fields(sd_bus_message *m);
35static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
de1c301e 36
9a17484d
LP
37static void reset_containers(sd_bus_message *m) {
38 unsigned i;
39
40 assert(m);
41
42 for (i = 0; i < m->n_containers; i++)
43 free(m->containers[i].signature);
44
45 free(m->containers);
46 m->containers = NULL;
47
48 m->n_containers = 0;
49 m->root_container.index = 0;
50}
51
de1c301e
LP
52static void message_free(sd_bus_message *m) {
53 unsigned i;
54
55 assert(m);
56
57 if (m->free_header)
58 free(m->header);
59
60 if (m->free_fields)
61 free(m->fields);
62
63 if (m->free_body)
64 free(m->body);
65
66 for (i = 0; i < m->n_fds; i++)
67 close_nointr_nofail(m->fds[i]);
68
9a17484d
LP
69 reset_containers(m);
70 free(m->root_container.signature);
de1c301e 71
9a17484d 72 free(m->peeked_signature);
de1c301e
LP
73 free(m);
74}
75
76static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
77 size_t start, n;
78 void *k;
79
80 assert(p);
81 assert(sz);
82 assert(align > 0);
83
84 start = ALIGN_TO((size_t) *sz, align);
85 n = start + extend;
86
87 if (n == *sz)
88 return (uint8_t*) *p + start;
89
90 if (n > (size_t) ((uint32_t) -1))
91 return NULL;
92
93 k = realloc(*p, n);
94 if (!k)
95 return NULL;
96
97 /* Zero out padding */
98 if (start > *sz)
99 memset((uint8_t*) k + *sz, 0, start - *sz);
100
101 *p = k;
102 *sz = n;
103
104 return (uint8_t*) k + start;
105}
106
107static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
108 void *p, *o;
109
110 assert(m);
111
112 o = m->fields;
113 p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
114 if (!p)
115 return NULL;
116
117 if (o != m->fields) {
118 /* Adjust quick access pointers */
119
120 if (m->path)
121 m->path = (const char*) m->fields + (m->path - (const char*) o);
122 if (m->interface)
123 m->interface = (const char*) m->fields + (m->interface - (const char*) o);
124 if (m->member)
125 m->member = (const char*) m->fields + (m->member - (const char*) o);
126 if (m->destination)
127 m->destination = (const char*) m->fields + (m->destination - (const char*) o);
128 if (m->sender)
129 m->sender = (const char*) m->fields + (m->sender - (const char*) o);
de1c301e
LP
130 if (m->error.name)
131 m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
132 }
133
134 m->free_fields = true;
135
136 return p;
137}
138
139static int message_append_field_string(
140 sd_bus_message *m,
141 uint8_t h,
142 char type,
143 const char *s,
144 const char **ret) {
145
146 size_t l;
147 uint8_t *p;
148
149 assert(m);
150
151 l = strlen(s);
152 if (l > (size_t) (uint32_t) -1)
153 return -EINVAL;
154
155 /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
156 p = message_extend_fields(m, 8, 4 + 4 + l + 1);
157 if (!p)
158 return -ENOMEM;
159
160 p[0] = h;
161 p[1] = 1;
162 p[2] = type;
163 p[3] = 0;
164
165 ((uint32_t*) p)[1] = l;
166 memcpy(p + 8, s, l + 1);
167
168 if (ret)
169 *ret = (const char*) p + 8;
170
171 return 0;
172}
173
174static int message_append_field_signature(
175 sd_bus_message *m,
176 uint8_t h,
177 const char *s,
178 const char **ret) {
179
180 size_t l;
181 uint8_t *p;
182
183 assert(m);
184
185 l = strlen(s);
186 if (l > 255)
187 return -EINVAL;
188
189 /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
190 p = message_extend_fields(m, 8, 4 + 1 + l + 1);
191 if (!p)
192 return -ENOMEM;
193
194 p[0] = h;
195 p[1] = 1;
196 p[2] = SD_BUS_TYPE_SIGNATURE;
197 p[3] = 0;
198 p[4] = l;
199 memcpy(p + 5, s, l + 1);
200
201 if (ret)
202 *ret = (const char*) p + 5;
203
204 return 0;
205}
206
207static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
208 uint8_t *p;
209
210 assert(m);
211
212 /* field id byte + signature length + signature 'u' + NUL + value */
213 p = message_extend_fields(m, 8, 4 + 4);
214 if (!p)
215 return -ENOMEM;
216
217 p[0] = h;
218 p[1] = 1;
219 p[2] = SD_BUS_TYPE_UINT32;
220 p[3] = 0;
221
222 ((uint32_t*) p)[1] = x;
223
224 return 0;
225}
226
80a46c73
LP
227int bus_message_from_malloc(void *buffer, size_t length, sd_bus_message **ret) {
228 sd_bus_message *m;
229 struct bus_header *h;
230 size_t total, fs, bs;
231 int r;
232
233 assert(buffer || length <= 0);
234 assert(ret);
235
236 if (length < sizeof(struct bus_header))
237 return -EBADMSG;
238
239 h = buffer;
240 if (h->version != 1)
241 return -EBADMSG;
242
243 if (h->serial == 0)
244 return -EBADMSG;
245
246 if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
247 return -EBADMSG;
248
249 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
250 fs = h->fields_size;
251 bs = h->body_size;
252 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
253 fs = bswap_32(h->fields_size);
254 bs = bswap_32(h->body_size);
255 } else
256 return -EBADMSG;
257
258 total = sizeof(struct bus_header) + ALIGN_TO(fs, 8) + bs;
259 if (length != total)
260 return -EBADMSG;
261
262 m = new0(sd_bus_message, 1);
263 if (!m)
264 return -ENOMEM;
265
266 m->n_ref = 1;
267 m->header = h;
268 m->free_header = true;
269 m->fields = (uint8_t*) buffer + sizeof(struct bus_header);
270 m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN_TO(fs, 8);
271 m->sealed = true;
272
273 m->n_iovec = 1;
274 m->iovec[0].iov_base = buffer;
275 m->iovec[0].iov_len = length;
276
277 r = message_parse_fields(m);
278 if (r < 0) {
279 message_free(m);
280 return r;
281 }
282
283 *ret = m;
284 return 0;
285}
286
de1c301e
LP
287static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
288 sd_bus_message *m;
289
80a46c73 290 m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
de1c301e
LP
291 if (!m)
292 return NULL;
293
294 m->n_ref = 1;
295 m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
80a46c73 296 m->header->endian = SD_BUS_NATIVE_ENDIAN;
de1c301e
LP
297 m->header->type = type;
298 m->header->version = bus ? bus->message_version : 1;
299
300 return m;
301}
302
303int sd_bus_message_new_signal(
304 sd_bus *bus,
305 const char *path,
306 const char *interface,
307 const char *member,
308 sd_bus_message **m) {
309
310 sd_bus_message *t;
311 int r;
312
313 if (!path)
314 return -EINVAL;
315 if (!interface)
316 return -EINVAL;
317 if (!member)
318 return -EINVAL;
5407f2de
LP
319 if (!m)
320 return -EINVAL;
de1c301e
LP
321
322 t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
323 if (!t)
324 return -ENOMEM;
325
89ffcd2a
LP
326 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
327
de1c301e
LP
328 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
329 if (r < 0)
330 goto fail;
331 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
332 if (r < 0)
333 goto fail;
334 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
335 if (r < 0)
336 goto fail;
337
338 *m = t;
339 return 0;
340
341fail:
342 sd_bus_message_unref(t);
343 return r;
344}
345
346int sd_bus_message_new_method_call(
347 sd_bus *bus,
348 const char *destination,
349 const char *path,
350 const char *interface,
351 const char *member,
352 sd_bus_message **m) {
353
354 sd_bus_message *t;
355 int r;
356
357 if (!path)
358 return -EINVAL;
359 if (!member)
360 return -EINVAL;
5407f2de
LP
361 if (!m)
362 return -EINVAL;
de1c301e
LP
363
364 t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
365 if (!t)
366 return -ENOMEM;
367
368 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
369 if (r < 0)
370 goto fail;
371 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
372 if (r < 0)
373 goto fail;
374
375 if (interface) {
376 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
377 if (r < 0)
378 goto fail;
379 }
380
381 if (destination) {
382 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
383 if (r < 0)
384 goto fail;
385 }
386
387 *m = t;
388 return 0;
389
390fail:
391 message_free(t);
392 return r;
393}
394
5407f2de 395static int message_new_reply(
de1c301e
LP
396 sd_bus *bus,
397 sd_bus_message *call,
5407f2de 398 uint8_t type,
de1c301e
LP
399 sd_bus_message **m) {
400
401 sd_bus_message *t;
402 int r;
403
404 if (!call)
405 return -EINVAL;
e3017af9
LP
406 if (!call->sealed)
407 return -EPERM;
de1c301e
LP
408 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
409 return -EINVAL;
5407f2de
LP
410 if (!m)
411 return -EINVAL;
de1c301e 412
5407f2de 413 t = message_new(bus, type);
de1c301e
LP
414 if (!t)
415 return -ENOMEM;
416
89ffcd2a 417 t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
de1c301e 418 t->reply_serial = BUS_MESSAGE_SERIAL(call);
5407f2de 419
de1c301e
LP
420 r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
421 if (r < 0)
422 goto fail;
423
424 if (call->sender) {
425 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
426 if (r < 0)
427 goto fail;
428 }
429
5407f2de
LP
430 t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
431
de1c301e 432 *m = t;
89ffcd2a 433 return 0;
de1c301e
LP
434
435fail:
436 message_free(t);
437 return r;
438}
439
5407f2de
LP
440int sd_bus_message_new_method_return(
441 sd_bus *bus,
442 sd_bus_message *call,
443 sd_bus_message **m) {
444
445 return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
446}
447
de1c301e
LP
448int sd_bus_message_new_method_error(
449 sd_bus *bus,
450 sd_bus_message *call,
451 const sd_bus_error *e,
452 sd_bus_message **m) {
453
454 sd_bus_message *t;
455 int r;
456
fbfa72b0 457 if (!sd_bus_error_is_set(e))
de1c301e 458 return -EINVAL;
5407f2de
LP
459 if (!m)
460 return -EINVAL;
de1c301e 461
5407f2de 462 r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
de1c301e 463 if (r < 0)
5407f2de 464 return r;
de1c301e
LP
465
466 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
467 if (r < 0)
468 goto fail;
469
470 if (e->message) {
471 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
472 if (r < 0)
473 goto fail;
474 }
475
476 *m = t;
477 return 0;
478
479fail:
480 message_free(t);
481 return r;
482}
483
484sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
485 if (!m)
486 return NULL;
487
488 assert(m->n_ref > 0);
489 m->n_ref++;
490
491 return m;
492}
493
494sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
495 if (!m)
496 return NULL;
497
498 assert(m->n_ref > 0);
499 m->n_ref--;
500
501 if (m->n_ref <= 0)
502 message_free(m);
503
504 return NULL;
505}
506
507int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
508 if (!m)
509 return -EINVAL;
510 if (!type)
511 return -EINVAL;
512
513 *type = m->header->type;
514 return 0;
515}
516
517int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
518 if (!m)
519 return -EINVAL;
520 if (!serial)
521 return -EINVAL;
522 if (m->header->serial == 0)
523 return -ENOENT;
524
525 *serial = BUS_MESSAGE_SERIAL(m);
526 return 0;
527}
528
529int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
530 if (!m)
531 return -EINVAL;
532 if (!serial)
533 return -EINVAL;
534 if (m->reply_serial == 0)
535 return -ENOENT;
536
537 *serial = m->reply_serial;
538 return 0;
539}
540
541int sd_bus_message_get_no_reply(sd_bus_message *m) {
542 if (!m)
543 return -EINVAL;
544
545 return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
546}
547
548const char *sd_bus_message_get_path(sd_bus_message *m) {
549 if (!m)
550 return NULL;
551
552 return m->path;
553}
554
555const char *sd_bus_message_get_interface(sd_bus_message *m) {
556 if (!m)
557 return NULL;
558
559 return m->interface;
560}
561
562const char *sd_bus_message_get_member(sd_bus_message *m) {
563 if (!m)
564 return NULL;
565
566 return m->member;
567}
568const char *sd_bus_message_get_destination(sd_bus_message *m) {
569 if (!m)
570 return NULL;
571
572 return m->destination;
573}
574
575const char *sd_bus_message_get_sender(sd_bus_message *m) {
576 if (!m)
577 return NULL;
578
579 return m->sender;
580}
581
582const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
583 if (!m)
584 return NULL;
585
586 if (!sd_bus_error_is_set(&m->error))
587 return NULL;
588
589 return &m->error;
590}
591
592int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
593 if (!m)
594 return -EINVAL;
595 if (!m->uid_valid)
596 return -ENOENT;
597
598 *uid = m->uid;
599 return 0;
600}
601
602int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
603 if (!m)
604 return -EINVAL;
605 if (!m->gid_valid)
606 return -ENOENT;
607
608 *gid = m->gid;
609 return 0;
610}
611
612int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
613 if (!m)
614 return -EINVAL;
615 if (m->pid <= 0)
616 return -ENOENT;
617
618 *pid = m->pid;
619 return 0;
620}
621
622int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
623 if (!m)
624 return -EINVAL;
625 if (m->tid <= 0)
626 return -ENOENT;
627
628 *tid = m->tid;
629 return 0;
630}
631
632int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
633 if (!m)
634 return -EINVAL;
635
636 if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
637 return 0;
638
639 if (interface && (!m->interface || !streq(m->interface, interface)))
640 return 0;
641
642 if (member && (!m->member || !streq(m->member, member)))
643 return 0;
644
645 return 1;
646}
647
648int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
649 if (!m)
650 return -EINVAL;
651
652 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
653 return 0;
654
655 if (interface && (!m->interface || !streq(m->interface, interface)))
656 return 0;
657
658 if (member && (!m->member || !streq(m->member, member)))
659 return 0;
660
661 return 1;
662}
663
664int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
665 if (!m)
666 return -EINVAL;
667
668 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
669 return 0;
670
671 if (name && (!m->error.name || !streq(m->error.name, name)))
672 return 0;
673
674 return 1;
675}
676
677int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
678 if (!m)
679 return -EINVAL;
680 if (m->sealed)
681 return -EPERM;
682 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
683 return -EPERM;
684
685 if (b)
686 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
687 else
688 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
689
690 return 0;
691}
692
693static struct bus_container *message_get_container(sd_bus_message *m) {
694 assert(m);
695
696 if (m->n_containers == 0)
697 return &m->root_container;
698
9a17484d
LP
699 assert(m->containers);
700 return m->containers + m->n_containers - 1;
de1c301e
LP
701}
702
703static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
704 void *p, *o;
705 size_t added;
706 struct bus_container *c;
707
708 assert(m);
9a17484d 709 assert(align > 0);
de1c301e
LP
710
711 o = m->body;
712 added = m->header->body_size;
713
714 p = buffer_extend(&m->body, &m->header->body_size, align, sz);
715 if (!p)
716 return NULL;
717
718 added = m->header->body_size - added;
719
9a17484d 720 for (c = m->containers; c < m->containers + m->n_containers; c++)
de1c301e
LP
721 if (c->array_size) {
722 c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
723 *c->array_size += added;
724 }
725
726 if (o != m->body) {
727 if (m->error.message)
728 m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
729 }
730
731 m->free_body = true;
732
733 return p;
734}
735
736int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
737 struct bus_container *c;
9a17484d 738 size_t sz, align;
de1c301e
LP
739 uint32_t k;
740 void *a;
741 char *e = NULL;
742
743 if (!m)
744 return -EINVAL;
745 if (m->sealed)
746 return -EPERM;
747 if (!bus_type_is_basic(type))
748 return -EINVAL;
749
750 c = message_get_container(m);
751
752 if (c->signature && c->signature[c->index]) {
753 /* Container signature is already set */
754
755 if (c->signature[c->index] != type)
9a17484d 756 return -ENXIO;
de1c301e
LP
757 } else {
758 /* Maybe we can append to the signature? But only if this is the top-level container*/
759 if (c->enclosing != 0)
9a17484d 760 return -ENXIO;
de1c301e
LP
761
762 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
763 if (!e)
764 return -ENOMEM;
765 }
766
de1c301e
LP
767 switch (type) {
768
769 case SD_BUS_TYPE_STRING:
770 case SD_BUS_TYPE_OBJECT_PATH:
b8beb278
LP
771
772 if (!p) {
773 if (e)
774 c->signature[c->index] = 0;
775
776 return -EINVAL;
777 }
778
de1c301e
LP
779 align = 4;
780 sz = 4 + strlen(p) + 1;
781 break;
782
783 case SD_BUS_TYPE_SIGNATURE:
b8beb278
LP
784
785 if (!p) {
786 if (e)
787 c->signature[c->index] = 0;
788
789 return -EINVAL;
790 }
791
de1c301e
LP
792 align = 1;
793 sz = 1 + strlen(p) + 1;
794 break;
795
796 case SD_BUS_TYPE_BOOLEAN:
797 align = sz = 4;
798
799 assert_cc(sizeof(int) == sizeof(uint32_t));
800 memcpy(&k, p, 4);
801 k = !!k;
802 p = &k;
803 break;
804
805 default:
806 align = bus_type_get_alignment(type);
807 sz = bus_type_get_size(type);
808 break;
809 }
810
811 assert(align > 0);
812 assert(sz > 0);
813
814 a = message_extend_body(m, align, sz);
815 if (!a) {
816 /* Truncate extended signature again */
817 if (e)
818 c->signature[c->index] = 0;
819
820 return -ENOMEM;
821 }
822
823 if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
824 *(uint32_t*) a = sz - 5;
825 memcpy((uint8_t*) a + 4, p, sz - 4);
826
827 if (stored)
828 *stored = (const uint8_t*) a + 4;
829
830 } else if (type == SD_BUS_TYPE_SIGNATURE) {
831 *(uint8_t*) a = sz - 1;
832 memcpy((uint8_t*) a + 1, p, sz - 1);
833
834 if (stored)
835 *stored = (const uint8_t*) a + 1;
836
837 } else {
838 memcpy(a, p, sz);
839
840 if (stored)
841 *stored = a;
842 }
843
844 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 845 c->index++;
de1c301e
LP
846
847 return 0;
848}
849
850int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
851 return message_append_basic(m, type, p, NULL);
852}
853
854static int bus_message_open_array(
855 sd_bus_message *m,
856 struct bus_container *c,
857 const char *contents,
858 uint32_t **array_size) {
859
9a17484d 860 unsigned nindex;
de1c301e 861 char *e = NULL;
de1c301e
LP
862 void *a, *b;
863 int alignment;
864 size_t saved;
865
866 assert(m);
867 assert(c);
868 assert(contents);
869 assert(array_size);
870
871 if (!signature_is_single(contents))
872 return -EINVAL;
873
874 alignment = bus_type_get_alignment(contents[0]);
875 if (alignment < 0)
876 return alignment;
877
878 if (c->signature && c->signature[c->index]) {
879
880 /* Verify the existing signature */
881
882 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 883 return -ENXIO;
de1c301e
LP
884
885 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 886 return -ENXIO;
de1c301e
LP
887
888 nindex = c->index + 1 + strlen(contents);
889 } else {
890 if (c->enclosing != 0)
9a17484d 891 return -ENXIO;
de1c301e
LP
892
893 /* Extend the existing signature */
894
895 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
896 if (!e)
897 return -ENOMEM;
898
899 nindex = e - c->signature;
900 }
901
902 saved = m->header->body_size;
903 a = message_extend_body(m, 4, 4);
904 if (!a) {
905 /* Truncate extended signature again */
906 if (e)
907 c->signature[c->index] = 0;
908
909 return -ENOMEM;
910 }
911 b = m->body;
912
913 if (!message_extend_body(m, alignment, 0)) {
914 /* Add alignment between size and first element */
915 if (e)
916 c->signature[c->index] = 0;
917
918 m->header->body_size = saved;
919 return -ENOMEM;
920 }
921
922 if (c->enclosing != SD_BUS_TYPE_ARRAY)
923 c->index = nindex;
924
925 /* m->body might have changed so let's readjust a */
926 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
927 *(uint32_t*) a = 0;
928
929 *array_size = a;
930 return 0;
931}
932
933static int bus_message_open_variant(
934 sd_bus_message *m,
935 struct bus_container *c,
936 const char *contents) {
937
938 char *e = NULL;
9a17484d 939 size_t l;
de1c301e
LP
940 void *a;
941
942 assert(m);
943 assert(c);
944 assert(contents);
945
946 if (!signature_is_single(contents))
947 return -EINVAL;
948
949 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
950 return -EINVAL;
951
952 if (c->signature && c->signature[c->index]) {
953
954 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 955 return -ENXIO;
de1c301e
LP
956
957 } else {
958 if (c->enclosing != 0)
9a17484d 959 return -ENXIO;
de1c301e
LP
960
961 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
962 if (!e)
963 return -ENOMEM;
964 }
965
de1c301e
LP
966 l = strlen(contents);
967 a = message_extend_body(m, 1, 1 + l + 1);
968 if (!a) {
969 /* Truncate extended signature again */
970 if (e)
971 c->signature[c->index] = 0;
972
973 return -ENOMEM;
974 }
975
976 *(uint8_t*) a = l;
977 memcpy((uint8_t*) a + 1, contents, l + 1);
978
979 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 980 c->index++;
de1c301e
LP
981
982 return 0;
983}
984
985static int bus_message_open_struct(
986 sd_bus_message *m,
987 struct bus_container *c,
988 const char *contents) {
989
990 size_t nindex;
991 char *e = NULL;
992
993 assert(m);
994 assert(c);
995 assert(contents);
996
997 if (!signature_is_valid(contents, false))
998 return -EINVAL;
999
1000 if (c->signature && c->signature[c->index]) {
1001 size_t l;
1002
1003 l = strlen(contents);
1004
1005 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1006 !startswith(c->signature + c->index + 1, contents) ||
1007 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1008 return -ENXIO;
de1c301e
LP
1009
1010 nindex = c->index + 1 + l + 1;
1011 } else {
1012 if (c->enclosing != 0)
9a17484d 1013 return -ENXIO;
de1c301e
LP
1014
1015 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1016 if (!e)
1017 return -ENOMEM;
1018
1019 nindex = e - c->signature;
1020 }
1021
1022 /* Align contents to 8 byte boundary */
1023 if (!message_extend_body(m, 8, 0)) {
1024 if (e)
1025 c->signature[c->index] = 0;
1026
1027 return -ENOMEM;
1028 }
1029
1030 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1031 c->index = nindex;
1032
1033 return 0;
1034}
1035
1036static int bus_message_open_dict_entry(
1037 sd_bus_message *m,
1038 struct bus_container *c,
1039 const char *contents) {
1040
1041 size_t nindex;
1042
1043 assert(m);
1044 assert(c);
1045 assert(contents);
1046
1047 if (!signature_is_pair(contents))
1048 return -EINVAL;
1049
1050 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1051 return -ENXIO;
de1c301e
LP
1052
1053 if (c->signature && c->signature[c->index]) {
1054 size_t l;
1055
1056 l = strlen(contents);
1057
1058 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1059 !startswith(c->signature + c->index + 1, contents) ||
1060 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1061 return -ENXIO;
de1c301e
LP
1062
1063 nindex = c->index + 1 + l + 1;
1064 } else
9a17484d 1065 return -ENXIO;
de1c301e
LP
1066
1067 /* Align contents to 8 byte boundary */
1068 if (!message_extend_body(m, 8, 0))
1069 return -ENOMEM;
1070
1071 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1072 c->index = nindex;
1073
1074 return 0;
1075}
1076
1077int sd_bus_message_open_container(
1078 sd_bus_message *m,
1079 char type,
1080 const char *contents) {
1081
9a17484d 1082 struct bus_container *c, *w;
de1c301e 1083 uint32_t *array_size = NULL;
9a17484d 1084 char *signature;
de1c301e
LP
1085 int r;
1086
1087 if (!m)
1088 return -EINVAL;
1089 if (m->sealed)
1090 return -EPERM;
1091 if (!contents)
1092 return -EINVAL;
1093
1094 /* Make sure we have space for one more container */
9a17484d
LP
1095 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1096 if (!w)
de1c301e 1097 return -ENOMEM;
9a17484d 1098 m->containers = w;
de1c301e
LP
1099
1100 c = message_get_container(m);
1101
1102 signature = strdup(contents);
1103 if (!signature)
1104 return -ENOMEM;
1105
1106 if (type == SD_BUS_TYPE_ARRAY)
1107 r = bus_message_open_array(m, c, contents, &array_size);
1108 else if (type == SD_BUS_TYPE_VARIANT)
1109 r = bus_message_open_variant(m, c, contents);
1110 else if (type == SD_BUS_TYPE_STRUCT)
1111 r = bus_message_open_struct(m, c, contents);
1112 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1113 r = bus_message_open_dict_entry(m, c, contents);
1114 else
1115 r = -EINVAL;
1116
1117 if (r < 0) {
1118 free(signature);
1119 return r;
1120 }
1121
1122 /* OK, let's fill it in */
9a17484d
LP
1123 w += m->n_containers++;
1124 w->enclosing = type;
1125 w->signature = signature;
1126 w->index = 0;
1127 w->array_size = array_size;
1128 w->begin = 0;
de1c301e
LP
1129
1130 return 0;
1131}
1132
1133int sd_bus_message_close_container(sd_bus_message *m) {
1134 struct bus_container *c;
1135
1136 if (!m)
1137 return -EINVAL;
1138 if (m->sealed)
1139 return -EPERM;
1140 if (m->n_containers <= 0)
1141 return -EINVAL;
1142
1143 c = message_get_container(m);
de1c301e 1144 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1145 if (c->signature && c->signature[c->index] != 0)
de1c301e
LP
1146 return -EINVAL;
1147
1148 free(c->signature);
1149 m->n_containers--;
1150
1151 return 0;
1152}
1153
1154static int message_append_ap(
1155 sd_bus_message *m,
1156 const char *types,
1157 va_list ap) {
1158
1159 const char *t;
1160 int r;
1161
1162 assert(m);
1163 assert(types);
1164
1165 for (t = types; *t; t++) {
1166 switch (*t) {
1167
1168 case SD_BUS_TYPE_BYTE: {
1169 uint8_t x;
1170
1171 x = (uint8_t) va_arg(ap, int);
1172 r = sd_bus_message_append_basic(m, *t, &x);
1173 break;
1174 }
1175
1176 case SD_BUS_TYPE_BOOLEAN:
1177 case SD_BUS_TYPE_INT32:
9a17484d
LP
1178 case SD_BUS_TYPE_UINT32:
1179 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
1180 uint32_t x;
1181
9a17484d
LP
1182 /* We assume a boolean is the same as int32_t */
1183 assert_cc(sizeof(int32_t) == sizeof(int));
1184
de1c301e
LP
1185 x = va_arg(ap, uint32_t);
1186 r = sd_bus_message_append_basic(m, *t, &x);
1187 break;
1188 }
1189
1190 case SD_BUS_TYPE_INT16:
1191 case SD_BUS_TYPE_UINT16: {
1192 uint16_t x;
1193
1194 x = (uint16_t) va_arg(ap, int);
1195 r = sd_bus_message_append_basic(m, *t, &x);
1196 break;
1197 }
1198
1199 case SD_BUS_TYPE_INT64:
1200 case SD_BUS_TYPE_UINT64:
1201 case SD_BUS_TYPE_DOUBLE: {
1202 uint64_t x;
1203
1204 x = va_arg(ap, uint64_t);
1205 r = sd_bus_message_append_basic(m, *t, &x);
1206 break;
1207 }
1208
1209 case SD_BUS_TYPE_STRING:
1210 case SD_BUS_TYPE_OBJECT_PATH:
1211 case SD_BUS_TYPE_SIGNATURE: {
1212 const char *x;
1213
1214 x = va_arg(ap, const char*);
1215 r = sd_bus_message_append_basic(m, *t, x);
1216 break;
1217 }
1218
de1c301e 1219 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
1220 size_t k;
1221
1222 r = signature_element_length(t + 1, &k);
1223 if (r < 0)
1224 return r;
1225
1226 {
9a17484d 1227 unsigned i, n;
de1c301e
LP
1228 char s[k + 1];
1229
1230 memcpy(s, t + 1, k);
1231 s[k] = 0;
1232 t += k;
1233
1234 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1235 if (r < 0)
1236 return r;
1237
1238 n = va_arg(ap, unsigned);
de1c301e
LP
1239 for (i = 0; i < n; i++) {
1240 r = message_append_ap(m, s, ap);
1241 if (r < 0)
1242 return r;
1243 }
1244
1245 r = sd_bus_message_close_container(m);
1246 }
1247
1248 break;
1249 }
1250
1251 case SD_BUS_TYPE_VARIANT: {
1252 const char *s;
1253
1254 s = va_arg(ap, const char*);
1255 if (!s)
1256 return -EINVAL;
1257
1258 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1259 if (r < 0)
1260 return r;
1261
1262 r = message_append_ap(m, s, ap);
1263 if (r < 0)
1264 return r;
1265
1266 r = sd_bus_message_close_container(m);
1267 break;
1268 }
1269
1270 case SD_BUS_TYPE_STRUCT_BEGIN:
1271 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1272 size_t k;
1273
1274 r = signature_element_length(t, &k);
1275 if (r < 0)
1276 return r;
1277
1278 {
1279 char s[k - 1];
1280
1281 memcpy(s, t + 1, k - 2);
1282 s[k - 2] = 0;
1283
1284 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1285 if (r < 0)
1286 return r;
1287
1288 t += k - 1;
1289
1290 r = message_append_ap(m, s, ap);
1291 if (r < 0)
1292 return r;
1293
1294 r = sd_bus_message_close_container(m);
1295 }
1296
1297 break;
1298 }
1299
1300 default:
1301 r = -EINVAL;
1302 }
1303
1304 if (r < 0)
1305 return r;
1306 }
1307
1308 return 0;
1309}
1310
1311int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1312 va_list ap;
1313 int r;
1314
1315 if (!m)
1316 return -EINVAL;
1317 if (m->sealed)
1318 return -EPERM;
1319 if (!types)
1320 return -EINVAL;
1321
1322 va_start(ap, types);
1323 r = message_append_ap(m, types, ap);
1324 va_end(ap);
1325
1326 return r;
1327}
1328
9a17484d
LP
1329static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1330 size_t k, start, n;
de1c301e 1331
9a17484d
LP
1332 assert(rindex);
1333 assert(align > 0);
de1c301e 1334
9a17484d
LP
1335 start = ALIGN_TO((size_t) *rindex, align);
1336 n = start + nbytes;
1337
1338 if (n > sz)
1339 return -EBADMSG;
1340
1341 /* Verify that padding is 0 */
1342 for (k = *rindex; k < start; k++)
1343 if (((const uint8_t*) p)[k] != 0)
1344 return -EBADMSG;
1345
1346 if (r)
1347 *r = (uint8_t*) p + start;
1348
1349 *rindex = n;
1350
1351 return 1;
de1c301e
LP
1352}
1353
9a17484d
LP
1354static bool message_end_of_array(sd_bus_message *m, size_t index) {
1355 struct bus_container *c;
de1c301e 1356
9a17484d 1357 assert(m);
de1c301e 1358
9a17484d
LP
1359 c = message_get_container(m);
1360 if (!c->array_size)
1361 return false;
de1c301e 1362
9a17484d 1363 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
1364}
1365
9a17484d 1366static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
de1c301e 1367 assert(m);
9a17484d
LP
1368 assert(rindex);
1369 assert(align > 0);
de1c301e 1370
9a17484d
LP
1371 if (message_end_of_array(m, *rindex))
1372 return 0;
de1c301e 1373
9a17484d
LP
1374 return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1375}
de1c301e 1376
ac89bf1d 1377static bool validate_nul(const char *s, size_t l) {
de1c301e 1378
9a17484d
LP
1379 /* Check for NUL chars in the string */
1380 if (memchr(s, 0, l))
1381 return false;
de1c301e 1382
9a17484d
LP
1383 /* Check for NUL termination */
1384 if (s[l] != 0)
1385 return false;
de1c301e 1386
ac89bf1d
LP
1387 return true;
1388}
1389
1390static bool validate_string(const char *s, size_t l) {
1391
1392 if (!validate_nul(s, l))
1393 return false;
1394
9a17484d
LP
1395 /* Check if valid UTF8 */
1396 if (!utf8_is_valid(s))
1397 return false;
1398
1399 return true;
de1c301e
LP
1400}
1401
9a17484d 1402static bool validate_signature(const char *s, size_t l) {
de1c301e 1403
ac89bf1d 1404 if (!validate_nul(s, l))
9a17484d 1405 return false;
de1c301e 1406
9a17484d
LP
1407 /* Check if valid signature */
1408 if (!signature_is_valid(s, true))
1409 return false;
1410
1411 return true;
1412}
1413
ac89bf1d
LP
1414static bool validate_object_path(const char *s, size_t l) {
1415
1416 if (!validate_nul(s, l))
1417 return false;
1418
1419 if (!object_path_is_valid(s))
1420 return false;
1421
1422 return true;
1423}
1424
9a17484d
LP
1425int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
1426 struct bus_container *c;
1427 int r;
1428 void *q;
1429
1430 if (!m)
1431 return -EINVAL;
1432 if (!m->sealed)
de1c301e 1433 return -EPERM;
9a17484d
LP
1434 if (!bus_type_is_basic(type))
1435 return -EINVAL;
de1c301e 1436
9a17484d 1437 c = message_get_container(m);
de1c301e 1438
9a17484d
LP
1439 if (!c->signature || c->signature[c->index] == 0)
1440 return 0;
1441
1442 if (c->signature[c->index] != type)
1443 return -ENXIO;
1444
1445 switch (type) {
1446
1447 case SD_BUS_TYPE_STRING:
1448 case SD_BUS_TYPE_OBJECT_PATH: {
1449 uint32_t l;
1450 size_t rindex;
1451
1452 rindex = m->rindex;
1453 r = message_peek_body(m, &rindex, 4, 4, &q);
1454 if (r <= 0)
1455 return r;
1456
1457 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1458 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
1459 if (r < 0)
1460 return r;
9a17484d
LP
1461 if (r == 0)
1462 return -EBADMSG;
1463
ac89bf1d
LP
1464 if (type == SD_BUS_TYPE_OBJECT_PATH) {
1465 if (!validate_object_path(q, l))
1466 return -EBADMSG;
1467 } else {
1468 if (!validate_string(q, l))
1469 return -EBADMSG;
1470 }
9a17484d
LP
1471
1472 m->rindex = rindex;
1473 *(const char**) p = q;
1474 break;
de1c301e
LP
1475 }
1476
9a17484d
LP
1477 case SD_BUS_TYPE_SIGNATURE: {
1478 uint8_t l;
1479 size_t rindex;
1480
1481 rindex = m->rindex;
1482 r = message_peek_body(m, &rindex, 1, 1, &q);
1483 if (r <= 0)
1484 return r;
1485
1486 l = *(uint8_t*) q;
1487 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
1488 if (r < 0)
1489 return r;
9a17484d
LP
1490 if (r == 0)
1491 return -EBADMSG;
1492
1493 if (!validate_signature(q, l))
1494 return -EBADMSG;
1495
1496 m->rindex = rindex;
1497 *(const char**) p = q;
1498 break;
de1c301e
LP
1499 }
1500
9a17484d
LP
1501 default: {
1502 size_t sz, align;
de1c301e 1503
9a17484d
LP
1504 align = bus_type_get_alignment(type);
1505 sz = bus_type_get_size(type);
de1c301e 1506
9a17484d
LP
1507 r = message_peek_body(m, &m->rindex, align, sz, &q);
1508 if (r <= 0)
1509 return r;
1510
1511 switch (type) {
1512
1513 case SD_BUS_TYPE_BYTE:
1514 *(uint8_t*) p = *(uint8_t*) q;
1515 break;
1516
1517 case SD_BUS_TYPE_BOOLEAN:
1518 *(int*) p = !!*(uint32_t*) q;
1519 break;
1520
1521 case SD_BUS_TYPE_INT16:
1522 case SD_BUS_TYPE_UINT16:
1523 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
1524 break;
1525
1526 case SD_BUS_TYPE_INT32:
1527 case SD_BUS_TYPE_UINT32:
1528 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
1529 break;
1530
1531 case SD_BUS_TYPE_INT64:
1532 case SD_BUS_TYPE_UINT64:
1533 case SD_BUS_TYPE_DOUBLE:
1534 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
1535 break;
1536
1537 default:
1538 assert_not_reached("Unknown basic type...");
1539 }
1540
1541 break;
1542 }
1543 }
1544
1545 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1546 c->index++;
1547
1548 return 1;
de1c301e
LP
1549}
1550
9a17484d
LP
1551static int bus_message_enter_array(
1552 sd_bus_message *m,
1553 struct bus_container *c,
1554 const char *contents,
1555 uint32_t **array_size) {
1556
1557 size_t rindex;
1558 void *q;
1559 int r, alignment;
1560
1561 assert(m);
1562 assert(c);
1563 assert(contents);
1564 assert(array_size);
1565
1566 if (!signature_is_single(contents))
de1c301e 1567 return -EINVAL;
9a17484d
LP
1568
1569 alignment = bus_type_get_alignment(contents[0]);
1570 if (alignment < 0)
1571 return alignment;
1572
1573 if (!c->signature || c->signature[c->index] == 0)
1574 return 0;
1575
1576 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
1577 return -ENXIO;
1578
1579 if (!startswith(c->signature + c->index + 1, contents))
1580 return -ENXIO;
1581
1582 rindex = m->rindex;
1583 r = message_peek_body(m, &rindex, 4, 4, &q);
1584 if (r <= 0)
1585 return r;
1586
ac89bf1d 1587 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
80a46c73 1588 return -EBADMSG;
9a17484d
LP
1589
1590 r = message_peek_body(m, &rindex, alignment, 0, NULL);
1591 if (r < 0)
1592 return r;
1593 if (r == 0)
1594 return -EBADMSG;
1595
1596 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1597 c->index += 1 + strlen(contents);
1598
1599 m->rindex = rindex;
1600
1601 *array_size = (uint32_t*) q;
1602
1603 return 1;
1604}
1605
1606static int bus_message_enter_variant(
1607 sd_bus_message *m,
1608 struct bus_container *c,
1609 const char *contents) {
1610
1611 size_t rindex;
1612 uint8_t l;
1613 void *q;
1614 int r;
1615
1616 assert(m);
1617 assert(c);
1618 assert(contents);
1619
1620 if (!signature_is_single(contents))
de1c301e 1621 return -EINVAL;
de1c301e 1622
9a17484d
LP
1623 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1624 return -EINVAL;
1625
1626 if (!c->signature || c->signature[c->index] == 0)
1627 return 0;
1628
1629 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
1630 return -ENXIO;
1631
1632 rindex = m->rindex;
1633 r = message_peek_body(m, &rindex, 1, 1, &q);
1634 if (r <= 0)
1635 return r;
1636
1637 l = *(uint8_t*) q;
1638 r = message_peek_body(m, &rindex, 1, l+1, &q);
1639 if (r < 0)
1640 return r;
1641 if (r == 0)
1642 return -EBADMSG;
1643
1644 if (!validate_signature(q, l))
1645 return -EBADMSG;
1646
1647 if (!streq(q, contents))
1648 return -ENXIO;
1649
1650 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1651 c->index++;
1652
1653 m->rindex = rindex;
1654
1655 return 1;
de1c301e
LP
1656}
1657
9a17484d
LP
1658static int bus_message_enter_struct(
1659 sd_bus_message *m,
1660 struct bus_container *c,
1661 const char *contents) {
1662
1663 size_t l;
1664 int r;
1665
1666 assert(m);
1667 assert(c);
1668 assert(contents);
1669
1670 if (!signature_is_valid(contents, false))
1671 return -EINVAL;
1672
1673 if (!c->signature || c->signature[c->index] == 0)
1674 return 0;
1675
1676 l = strlen(contents);
1677
1678 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1679 !startswith(c->signature + c->index + 1, contents) ||
1680 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
1681 return -ENXIO;
1682
1683 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1684 if (r <= 0)
1685 return r;
1686
1687 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1688 c->index += 1 + l + 1;
1689
1690 return 1;
1691}
1692
1693static int bus_message_enter_dict_entry(
1694 sd_bus_message *m,
1695 struct bus_container *c,
1696 const char *contents) {
1697
1698 size_t l;
1699 int r;
1700
1701 assert(m);
1702 assert(c);
1703 assert(contents);
1704
1705 if (!signature_is_pair(contents))
1706 return -EINVAL;
1707
1708 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1709 return -ENXIO;
1710
1711 if (!c->signature || c->signature[c->index] == 0)
1712 return 0;
1713
1714 l = strlen(contents);
1715
1716 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1717 !startswith(c->signature + c->index + 1, contents) ||
1718 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
1719 return -ENXIO;
1720
1721 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
1722 if (r <= 0)
1723 return r;
1724
1725 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1726 c->index += 1 + l + 1;
1727
1728 return 1;
1729}
1730
1731int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
1732 struct bus_container *c, *w;
1733 uint32_t *array_size = NULL;
1734 char *signature;
1735 int r;
1736
1737 if (!m)
1738 return -EINVAL;
1739 if (!m->sealed)
1740 return -EPERM;
1741 if (!contents)
1742 return -EINVAL;
1743
ed205a6b
LP
1744 /*
1745 * We enforce a global limit on container depth, that is much
1746 * higher than the 32 structs and 32 arrays the specification
1747 * mandates. This is simpler to implement for us, and we need
1748 * this only to ensure our container array doesn't grow
1749 * without bounds. We are happy to return any data from a
1750 * message as long as the data itself is valid, even if the
1751 * overall message might be not.
1752 *
1753 * Note that the message signature is validated when
1754 * parsing the headers, and that validation does check the
1755 * 32/32 limit.
1756 *
1757 * Note that the specification defines no limits on the depth
1758 * of stacked variants, but we do.
1759 */
1760 if (m->n_containers >= BUS_CONTAINER_DEPTH)
1761 return -EBADMSG;
1762
9a17484d
LP
1763 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1764 if (!w)
1765 return -ENOMEM;
1766 m->containers = w;
1767
1768 c = message_get_container(m);
1769
1770 if (!c->signature || c->signature[c->index] == 0)
1771 return 0;
1772
1773 signature = strdup(contents);
1774 if (!signature)
1775 return -ENOMEM;
1776
1777 if (type == SD_BUS_TYPE_ARRAY)
1778 r = bus_message_enter_array(m, c, contents, &array_size);
1779 else if (type == SD_BUS_TYPE_VARIANT)
1780 r = bus_message_enter_variant(m, c, contents);
1781 else if (type == SD_BUS_TYPE_STRUCT)
1782 r = bus_message_enter_struct(m, c, contents);
1783 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1784 r = bus_message_enter_dict_entry(m, c, contents);
1785 else
1786 r = -EINVAL;
1787
1788 if (r <= 0) {
1789 free(signature);
1790 return r;
1791 }
1792
1793 /* OK, let's fill it in */
1794 w += m->n_containers++;
1795 w->enclosing = type;
1796 w->signature = signature;
1797 w->index = 0;
1798 w->array_size = array_size;
1799 w->begin = m->rindex;
1800
1801 return 1;
1802}
1803
1804int sd_bus_message_exit_container(sd_bus_message *m) {
1805 struct bus_container *c;
1806
1807 if (!m)
1808 return -EINVAL;
1809 if (!m->sealed)
1810 return -EPERM;
1811 if (m->n_containers <= 0)
1812 return -EINVAL;
1813
1814 c = message_get_container(m);
1815 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
1816 uint32_t l;
1817
1818 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
1819 if (c->begin + l != m->rindex)
1820 return -EBUSY;
1821
1822 } else {
1823 if (c->signature && c->signature[c->index] != 0)
1824 return -EINVAL;
1825 }
1826
1827 free(c->signature);
1828 m->n_containers--;
1829
1830 return 1;
1831}
1832
1833int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
1834 struct bus_container *c;
1835 int r;
1836
1837 if (!m)
1838 return -EINVAL;
1839 if (!m->sealed)
1840 return -EPERM;
1841
1842 c = message_get_container(m);
1843
1844 if (!c->signature || c->signature[c->index] == 0)
1845 goto eof;
1846
1847 if (message_end_of_array(m, m->rindex))
1848 goto eof;
1849
1850 if (bus_type_is_basic(c->signature[c->index])) {
1851 if (contents)
1852 *contents = NULL;
1853 if (type)
1854 *type = c->signature[c->index];
1855 return 1;
1856 }
1857
1858 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
1859
1860 if (contents) {
1861 size_t l;
1862 char *sig;
1863
1864 r = signature_element_length(c->signature+c->index+1, &l);
1865 if (r < 0)
1866 return r;
1867
80a46c73
LP
1868 assert(l >= 1);
1869
9a17484d
LP
1870 sig = strndup(c->signature + c->index + 1, l);
1871 if (!sig)
1872 return -ENOMEM;
1873
1874 free(m->peeked_signature);
1875 m->peeked_signature = sig;
1876
1877 *contents = sig;
1878 }
1879
1880 if (type)
1881 *type = SD_BUS_TYPE_ARRAY;
1882
1883 return 1;
1884 }
1885
1886 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
1887 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
1888
1889 if (contents) {
1890 size_t l;
1891 char *sig;
1892
1893 r = signature_element_length(c->signature+c->index, &l);
1894 if (r < 0)
1895 return r;
1896
1897 assert(l >= 2);
1898 sig = strndup(c->signature + c->index + 1, l - 2);
1899 if (!sig)
1900 return -ENOMEM;
1901
1902 free(m->peeked_signature);
1903 m->peeked_signature = sig;
1904
1905 *contents = sig;
1906 }
1907
1908 if (type)
1909 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
1910
1911 return 1;
1912 }
1913
1914 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
1915 if (contents) {
1916 size_t rindex, l;
1917 void *q;
1918
1919 rindex = m->rindex;
1920 r = message_peek_body(m, &rindex, 1, 1, &q);
1921 if (r < 0)
1922 return r;
1923 if (r == 0)
1924 goto eof;
1925
1926 l = *(uint8_t*) q;
1927 r = message_peek_body(m, &rindex, 1, l+1, &q);
1928 if (r < 0)
1929 return r;
1930 if (r == 0)
1931 return -EBADMSG;
1932
1933 if (!validate_signature(q, l))
1934 return -EBADMSG;
1935
1936 *contents = q;
1937 }
1938
1939 if (type)
1940 *type = SD_BUS_TYPE_VARIANT;
1941
1942 return 1;
1943 }
1944
1945 return -EINVAL;
1946
1947eof:
1948 if (type)
1949 *type = c->enclosing;
1950 if (contents)
1951 *contents = NULL;
1952 return 0;
1953}
1954
89ffcd2a 1955int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
1956 struct bus_container *c;
1957
1958 if (!m)
1959 return -EINVAL;
1960 if (!m->sealed)
1961 return -EPERM;
1962
1963 if (complete) {
1964 reset_containers(m);
1965 m->rindex = 0;
1966 m->root_container.index = 0;
1967
1968 c = message_get_container(m);
1969 } else {
1970 c = message_get_container(m);
1971
1972 c->index = 0;
1973 m->rindex = c->begin;
1974 }
1975
1976 return !isempty(c->signature);
1977}
1978
1979static int message_read_ap(sd_bus_message *m, const char *types, va_list ap) {
1980 const char *t;
1981 int r;
1982
1983 assert(m);
1984 assert(types);
1985
1986 for (t = types; *t; t++) {
1987 switch (*t) {
1988
1989 case SD_BUS_TYPE_BYTE:
1990 case SD_BUS_TYPE_BOOLEAN:
1991 case SD_BUS_TYPE_INT16:
1992 case SD_BUS_TYPE_UINT16:
1993 case SD_BUS_TYPE_INT32:
1994 case SD_BUS_TYPE_UINT32:
1995 case SD_BUS_TYPE_INT64:
1996 case SD_BUS_TYPE_UINT64:
1997 case SD_BUS_TYPE_DOUBLE:
1998 case SD_BUS_TYPE_STRING:
1999 case SD_BUS_TYPE_OBJECT_PATH:
2000 case SD_BUS_TYPE_SIGNATURE: {
2001 void *p;
2002
2003 p = va_arg(ap, void*);
2004 r = sd_bus_message_read_basic(m, *t, p);
2005 break;
2006 }
2007
2008 case SD_BUS_TYPE_ARRAY: {
2009 size_t k;
2010
2011 r = signature_element_length(t + 1, &k);
2012 if (r < 0)
2013 return r;
2014
2015 {
2016 unsigned i, n;
2017 char s[k + 1];
2018
2019 memcpy(s, t + 1, k);
2020 s[k] = 0;
2021 t += k;
2022
2023 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
2024 if (r < 0)
2025 return r;
2026 if (r == 0)
2027 return -ENXIO;
2028
2029 n = va_arg(ap, unsigned);
2030 for (i = 0; i < n; i++) {
2031 r = message_read_ap(m, s, ap);
2032 if (r < 0)
2033 return r;
2034 }
2035
2036 r = sd_bus_message_exit_container(m);
2037 }
2038
2039 break;
2040 }
2041
2042 case SD_BUS_TYPE_VARIANT: {
2043 const char *s;
2044
2045 s = va_arg(ap, const char *);
2046 if (!s)
2047 return -EINVAL;
2048
2049 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
2050 if (r < 0)
2051 return r;
2052 if (r == 0)
2053 return -ENXIO;
2054
2055 r = message_read_ap(m, s, ap);
2056 if (r < 0)
2057 return r;
2058 if (r == 0)
2059 return -ENXIO;
2060
2061 r = sd_bus_message_exit_container(m);
2062 break;
2063 }
2064
2065 case SD_BUS_TYPE_STRUCT_BEGIN:
2066 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2067 size_t k;
2068
2069 r = signature_element_length(t, &k);
2070 if (r < 0)
2071 return r;
2072
2073 {
2074 char s[k - 1];
2075 memcpy(s, t + 1, k - 2);
2076 s[k - 2] = 0;
2077
2078 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2079 if (r < 0)
2080 return r;
2081 if (r == 0)
2082 return -ENXIO;
2083
2084 t += k - 1;
2085
2086 r = message_read_ap(m, s, ap);
2087 if (r < 0)
2088 return r;
2089 if (r == 0)
2090 return -ENXIO;
2091
2092 r = sd_bus_message_exit_container(m);
2093 }
2094
2095 break;
2096 }
2097
2098 default:
2099 r = -EINVAL;
2100 }
2101
2102 if (r < 0)
2103 return r;
2104 if (r == 0)
2105 return -ENXIO;
2106 }
2107
2108 return 1;
2109}
2110
2111int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2112 va_list ap;
2113 int r;
2114
2115 if (!m)
2116 return -EINVAL;
2117 if (!m->sealed)
2118 return -EPERM;
2119 if (!types)
2120 return -EINVAL;
2121
2122 va_start(ap, types);
2123 r = message_read_ap(m, types, ap);
2124 va_end(ap);
2125
2126 return r;
2127}
2128
80a46c73
LP
2129static int message_peek_fields(
2130 sd_bus_message *m,
2131 size_t *rindex,
2132 size_t align,
2133 size_t nbytes,
2134 void **ret) {
2135
2136 assert(m);
2137 assert(rindex);
2138 assert(align > 0);
2139
2140 return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2141}
2142
9f26c90c
LP
2143static int message_peek_field_uint32(
2144 sd_bus_message *m,
2145 size_t *ri,
2146 uint32_t *ret) {
2147
2148 int r;
2149 void *q;
2150
2151 assert(m);
2152 assert(ri);
2153
2154 r = message_peek_fields(m, ri, 4, 4, &q);
2155 if (r < 0)
2156 return r;
2157
2158 if (ret)
2159 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2160
2161 return 0;
2162}
2163
80a46c73
LP
2164static int message_peek_field_string(
2165 sd_bus_message *m,
6693860f 2166 bool (*validate)(const char *p),
80a46c73
LP
2167 size_t *ri,
2168 const char **ret) {
2169
9f26c90c 2170 uint32_t l;
80a46c73
LP
2171 int r;
2172 void *q;
2173
9a17484d 2174 assert(m);
80a46c73
LP
2175 assert(ri);
2176
9f26c90c 2177 r = message_peek_field_uint32(m, ri, &l);
80a46c73
LP
2178 if (r < 0)
2179 return r;
2180
80a46c73
LP
2181 r = message_peek_fields(m, ri, 1, l+1, &q);
2182 if (r < 0)
2183 return r;
9a17484d 2184
6693860f
LP
2185 if (validate) {
2186 if (!validate_nul(q, l))
2187 return -EBADMSG;
2188
2189 if (!validate(q))
ac89bf1d
LP
2190 return -EBADMSG;
2191 } else {
2192 if (!validate_string(q, l))
2193 return -EBADMSG;
2194 }
80a46c73
LP
2195
2196 if (ret)
2197 *ret = q;
2198
2199 return 0;
2200}
2201
2202static int message_peek_field_signature(
2203 sd_bus_message *m,
2204 size_t *ri,
2205 const char **ret) {
2206
2207 size_t l;
2208 int r;
2209 void *q;
2210
2211 assert(m);
2212 assert(ri);
2213
2214 r = message_peek_fields(m, ri, 1, 1, &q);
2215 if (r < 0)
2216 return r;
2217
2218 l = *(uint8_t*) q;
2219 r = message_peek_fields(m, ri, 1, l+1, &q);
2220 if (r < 0)
2221 return r;
2222
2223 if (!validate_signature(q, l))
2224 return -EBADMSG;
2225
2226 if (ret)
2227 *ret = q;
2228
2229 return 0;
2230}
2231
80a46c73
LP
2232static int message_skip_fields(
2233 sd_bus_message *m,
2234 size_t *ri,
2235 uint32_t array_size,
2236 const char **signature) {
2237
2238 size_t original_index;
2239 int r;
2240
2241 assert(m);
2242 assert(ri);
2243 assert(signature);
2244
2245 original_index = *ri;
2246
2247 for (;;) {
2248 char t;
80a46c73
LP
2249 size_t l;
2250
2251 if (array_size != (uint32_t) -1 &&
2252 array_size <= *ri - original_index)
2253 return 0;
2254
2255 t = **signature;
2256 if (!t)
2257 return 0;
2258
6693860f
LP
2259 if (t == SD_BUS_TYPE_STRING) {
2260
2261 r = message_peek_field_string(m, NULL, ri, NULL);
2262 if (r < 0)
2263 return r;
2264
2265 (*signature)++;
2266
2267 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 2268
6693860f 2269 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
2270 if (r < 0)
2271 return r;
2272
2273 (*signature)++;
2274
2275 } else if (t == SD_BUS_TYPE_SIGNATURE) {
2276
2277 r = message_peek_field_signature(m, ri, NULL);
2278 if (r < 0)
2279 return r;
2280
2281 (*signature)++;
2282
2283 } else if (bus_type_is_basic(t)) {
2284 size_t align, k;
2285
c66a2e0c
TG
2286 align = bus_type_get_alignment(t);
2287 k = bus_type_get_size(t);
80a46c73
LP
2288
2289 r = message_peek_fields(m, ri, align, k, NULL);
2290 if (r < 0)
2291 return r;
9a17484d 2292
80a46c73
LP
2293 (*signature)++;
2294
2295 } else if (t == SD_BUS_TYPE_ARRAY) {
2296
2297 r = signature_element_length(*signature+1, &l);
2298 if (r < 0)
2299 return r;
2300
2301 assert(l >= 1);
2302 {
2303 char sig[l-1], *s;
9f26c90c 2304 uint32_t nas;
80a46c73
LP
2305 int alignment;
2306
2307 strncpy(sig, *signature + 1, l-1);
2308 s = sig;
2309
2310 alignment = bus_type_get_alignment(sig[0]);
2311 if (alignment < 0)
2312 return alignment;
2313
9f26c90c 2314 r = message_peek_field_uint32(m, ri, &nas);
80a46c73
LP
2315 if (r < 0)
2316 return r;
ac89bf1d 2317 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
2318 return -EBADMSG;
2319
2320 r = message_peek_fields(m, ri, alignment, 0, NULL);
2321 if (r < 0)
2322 return r;
2323
2324 r = message_skip_fields(m, ri, nas, (const char**) &s);
2325 if (r < 0)
2326 return r;
2327 }
2328
2329 (*signature) += 1 + l;
2330
2331 } else if (t == SD_BUS_TYPE_VARIANT) {
2332 const char *s;
2333
2334 r = message_peek_field_signature(m, ri, &s);
2335 if (r < 0)
2336 return r;
2337
2338 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2339 if (r < 0)
2340 return r;
2341
2342 (*signature)++;
2343
2344 } else if (t == SD_BUS_TYPE_STRUCT ||
2345 t == SD_BUS_TYPE_DICT_ENTRY) {
2346
2347 r = signature_element_length(*signature, &l);
2348 if (r < 0)
2349 return r;
2350
2351 assert(l >= 2);
2352 {
2353 char sig[l-1], *s;
2354 strncpy(sig, *signature + 1, l-1);
2355 s = sig;
2356
2357 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2358 if (r < 0)
2359 return r;
2360 }
2361
2362 *signature += l;
2363 } else
2364 return -EINVAL;
2365 }
2366}
2367
2368static int message_parse_fields(sd_bus_message *m) {
2369 size_t ri;
2370 int r;
2371
2372 assert(m);
2373
2374 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
2375 const char *signature;
2376 uint8_t *header;
2377
2378 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
2379 if (r < 0)
2380 return r;
2381
2382 r = message_peek_field_signature(m, &ri, &signature);
2383 if (r < 0)
2384 return r;
2385
2386 switch (*header) {
2387 case _SD_BUS_MESSAGE_HEADER_INVALID:
2388 return -EBADMSG;
2389
2390 case SD_BUS_MESSAGE_HEADER_PATH:
2391 if (!streq(signature, "o"))
2392 return -EBADMSG;
2393
6693860f 2394 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
2395 break;
2396
2397 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2398 if (!streq(signature, "s"))
2399 return -EBADMSG;
2400
6693860f 2401 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
2402 break;
2403
2404 case SD_BUS_MESSAGE_HEADER_MEMBER:
2405 if (!streq(signature, "s"))
2406 return -EBADMSG;
2407
6693860f 2408 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
2409 break;
2410
2411 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2412 if (!streq(signature, "s"))
2413 return -EBADMSG;
2414
6693860f 2415 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
2416 break;
2417
2418 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2419 if (!streq(signature, "s"))
2420 return -EBADMSG;
2421
6693860f 2422 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
2423 break;
2424
2425 case SD_BUS_MESSAGE_HEADER_SENDER:
2426 if (!streq(signature, "s"))
2427 return -EBADMSG;
2428
6693860f 2429 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
2430 break;
2431
2432
2433 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
2434 const char *s;
2435 char *c;
2436
2437 if (!streq(signature, "g"))
2438 return -EBADMSG;
2439
2440 r = message_peek_field_signature(m, &ri, &s);
2441 if (r < 0)
2442 return r;
2443
2444 c = strdup(s);
2445 if (!c)
2446 return -ENOMEM;
2447
2448 free(m->root_container.signature);
2449 m->root_container.signature = c;
80a46c73
LP
2450 break;
2451 }
2452
2453 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2454 if (!streq(signature, "u"))
2455 return -EBADMSG;
2456
2457 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
2458 if (r < 0)
2459 return r;
2460
2461 if (m->reply_serial == 0)
2462 return -EBADMSG;
2463
80a46c73
LP
2464 break;
2465
2466 default:
2467 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
2468 }
2469
2470 if (r < 0)
2471 return r;
2472 }
2473
2474 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
2475 return -EBADMSG;
2476
2477 switch (m->header->type) {
2478
2479 case SD_BUS_MESSAGE_TYPE_SIGNAL:
2480 if (!m->path || !m->interface || !m->member)
2481 return -EBADMSG;
2482 break;
2483
2484 case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
2485
2486 if (!m->path || !m->member)
2487 return -EBADMSG;
2488
2489 break;
2490
2491 case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
2492
2493 if (m->reply_serial == 0)
2494 return -EBADMSG;
2495 break;
2496
2497 case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
2498
2499 if (m->reply_serial == 0 || !m->error.name)
2500 return -EBADMSG;
2501 break;
2502 }
9a17484d 2503
89ffcd2a
LP
2504 /* Try to read the error message, but if we can't it's a non-issue */
2505 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
2506 sd_bus_message_read(m, "s", &m->error.message);
2507
9a17484d
LP
2508 return 0;
2509}
2510
2511static void setup_iovec(sd_bus_message *m) {
2512 assert(m);
2513 assert(m->sealed);
2514
2515 m->n_iovec = 0;
e3017af9 2516 m->size = 0;
9a17484d
LP
2517
2518 m->iovec[m->n_iovec].iov_base = m->header;
2519 m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
e3017af9 2520 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2521 m->n_iovec++;
2522
2523 if (m->fields) {
2524 m->iovec[m->n_iovec].iov_base = m->fields;
2525 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
e3017af9 2526 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2527 m->n_iovec++;
2528
2529 if (m->header->fields_size % 8 != 0) {
2530 static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
2531
2532 m->iovec[m->n_iovec].iov_base = (void*) padding;
2533 m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
e3017af9 2534 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2535 m->n_iovec++;
2536 }
2537 }
2538
2539 if (m->body) {
2540 m->iovec[m->n_iovec].iov_base = m->body;
2541 m->iovec[m->n_iovec].iov_len = m->header->body_size;
e3017af9 2542 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2543 m->n_iovec++;
2544 }
2545}
2546
2547int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2548 int r;
2549
2550 assert(m);
2551
2552 if (m->sealed)
2553 return -EPERM;
2554
2555 if (m->n_containers > 0)
2556 return -EBADMSG;
2557
2558 /* If there's a non-trivial signature set, then add it in here */
2559 if (!isempty(m->root_container.signature)) {
80a46c73 2560 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
2561 if (r < 0)
2562 return r;
2563 }
2564
2565 if (m->n_fds > 0) {
2566 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2567 if (r < 0)
2568 return r;
2569 }
2570
2571 m->header->serial = serial;
2572 m->sealed = true;
2573
2574 setup_iovec(m);
2575
2576 return 0;
2577}
2578
2579int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
2580 if (!m)
2581 return -EINVAL;
2582 if (!destination)
2583 return -EINVAL;
2584 if (m->sealed)
2585 return -EPERM;
2586 if (m->destination)
2587 return -EEXIST;
2588
2589 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
2590}
2591
2592int bus_message_dump(sd_bus_message *m) {
2593 unsigned level = 1;
2594 int r;
2595
2596 assert(m);
2597
2598 printf("Message %p\n"
2599 "\tn_ref=%u\n"
2600 "\tendian=%c\n"
2601 "\ttype=%i\n"
2602 "\tflags=%u\n"
2603 "\tversion=%u\n"
2604 "\tserial=%u\n"
2605 "\tfields_size=%u\n"
2606 "\tbody_size=%u\n"
2607 "\tpath=%s\n"
2608 "\tinterface=%s\n"
2609 "\tmember=%s\n"
2610 "\tdestination=%s\n"
2611 "\tsender=%s\n"
2612 "\tsignature=%s\n"
2613 "\treply_serial=%u\n"
2614 "\terror.name=%s\n"
2615 "\terror.message=%s\n"
2616 "\tsealed=%s\n",
2617 m,
2618 m->n_ref,
2619 m->header->endian,
2620 m->header->type,
2621 m->header->flags,
2622 m->header->version,
2623 BUS_MESSAGE_SERIAL(m),
2624 BUS_MESSAGE_FIELDS_SIZE(m),
2625 BUS_MESSAGE_BODY_SIZE(m),
2626 strna(m->path),
2627 strna(m->interface),
2628 strna(m->member),
2629 strna(m->destination),
2630 strna(m->sender),
80a46c73 2631 strna(m->root_container.signature),
9a17484d
LP
2632 m->reply_serial,
2633 strna(m->error.name),
2634 strna(m->error.message),
2635 yes_no(m->sealed));
2636
2637 r = sd_bus_message_rewind(m, true);
2638 if (r < 0) {
2639 log_error("Failed to rewind: %s", strerror(-r));
2640 return r;
2641 }
2642
80a46c73 2643 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
2644
2645 for(;;) {
2646 _cleanup_free_ char *prefix = NULL;
2647 const char *contents = NULL;
2648 char type;
2649 union {
2650 uint8_t u8;
2651 uint16_t u16;
2652 int16_t s16;
2653 uint32_t u32;
2654 int32_t s32;
2655 uint64_t u64;
2656 int64_t s64;
2657 double d64;
2658 const char *string;
2659 int i;
2660 } basic;
2661
2662 r = sd_bus_message_peek_type(m, &type, &contents);
2663 if (r < 0) {
2664 log_error("Failed to peek type: %s", strerror(-r));
2665 return r;
2666 }
2667 if (r == 0) {
2668 if (level <= 1)
2669 break;
2670
2671 r = sd_bus_message_exit_container(m);
2672 if (r < 0) {
2673 log_error("Failed to exit container: %s", strerror(-r));
2674 return r;
2675 }
2676
2677 level--;
2678
2679 prefix = strrep("\t", level);
2680 if (!prefix)
2681 return log_oom();
2682
2683 if (type == SD_BUS_TYPE_ARRAY)
2684 printf("%s} END_ARRAY \n", prefix);
2685 else if (type == SD_BUS_TYPE_VARIANT)
2686 printf("%s} END_VARIANT\n", prefix);
2687 else if (type == SD_BUS_TYPE_STRUCT)
2688 printf("%s} END_STRUCT\n", prefix);
2689 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2690 printf("%s} END_DICT_ENTRY\n", prefix);
2691
2692 continue;
2693 }
2694
2695 prefix = strrep("\t", level);
2696 if (!prefix)
2697 return log_oom();
2698
2699 if (bus_type_is_container(type) > 0) {
2700 r = sd_bus_message_enter_container(m, type, contents);
2701 if (r < 0) {
2702 log_error("Failed to enter container: %s", strerror(-r));
2703 return r;
2704 }
2705
2706 if (type == SD_BUS_TYPE_ARRAY)
2707 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
2708 else if (type == SD_BUS_TYPE_VARIANT)
2709 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
2710 else if (type == SD_BUS_TYPE_STRUCT)
2711 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
2712 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2713 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
2714
2715 level ++;
2716
2717 continue;
2718 }
2719
2720 r = sd_bus_message_read_basic(m, type, &basic);
2721 if (r < 0) {
2722 log_error("Failed to get basic: %s", strerror(-r));
2723 return r;
2724 }
2725
2726 switch (type) {
2727
2728 case SD_BUS_TYPE_BYTE:
2729 printf("%sBYTE: %u\n", prefix, basic.u8);
2730 break;
2731
2732 case SD_BUS_TYPE_BOOLEAN:
2733 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
2734 break;
2735
2736 case SD_BUS_TYPE_INT16:
2737 printf("%sINT16: %i\n", prefix, basic.s16);
2738 break;
2739
2740 case SD_BUS_TYPE_UINT16:
2741 printf("%sUINT16: %u\n", prefix, basic.u16);
2742 break;
2743
2744 case SD_BUS_TYPE_INT32:
2745 printf("%sINT32: %i\n", prefix, basic.s32);
2746 break;
2747
2748 case SD_BUS_TYPE_UINT32:
2749 printf("%sUINT32: %u\n", prefix, basic.u32);
2750 break;
2751
2752 case SD_BUS_TYPE_INT64:
2753 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
2754 break;
2755
2756 case SD_BUS_TYPE_UINT64:
2757 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
2758 break;
2759
2760 case SD_BUS_TYPE_DOUBLE:
2761 printf("%sDOUBLE: %g\n", prefix, basic.d64);
2762 break;
2763
2764 case SD_BUS_TYPE_STRING:
2765 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
2766 break;
2767
2768 case SD_BUS_TYPE_OBJECT_PATH:
2769 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
2770 break;
2771
2772 case SD_BUS_TYPE_SIGNATURE:
2773 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
2774 break;
2775
2776 case SD_BUS_TYPE_UNIX_FD:
2777 printf("%sUNIX_FD: %i\n", prefix, basic.i);
2778 break;
2779
2780 default:
2781 assert_not_reached("Unknown basic type.");
2782 }
2783 }
2784
2785 printf("} END_MESSAGE\n");
2786 return 0;
de1c301e
LP
2787}
2788
2789int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
2790 size_t total;
2791 unsigned i;
2792 void *p, *e;
2793
2794 assert(m);
2795 assert(buffer);
2796 assert(sz);
2797
2798 for (i = 0, total = 0; i < m->n_iovec; i++)
2799 total += m->iovec[i].iov_len;
2800
2801 p = malloc(total);
2802 if (!p)
2803 return -ENOMEM;
2804
2805 for (i = 0, e = p; i < m->n_iovec; i++)
2806 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);
2807
2808 *buffer = p;
2809 *sz = total;
2810
2811 return 0;
2812}
89ffcd2a
LP
2813
2814int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
2815 int r;
2816
2817 assert(m);
2818 assert(l);
2819
2820 r = sd_bus_message_enter_container(m, 'a', "s");
2821 if (r < 0)
2822 return r;
2823
2824 for (;;) {
2825 const char *s;
2826
2827 r = sd_bus_message_read_basic(m, 's', &s);
2828 if (r < 0)
2829 return r;
2830 if (r == 0)
2831 break;
2832
2833 r = strv_extend(l, s);
2834 if (r < 0)
2835 return r;
2836 }
2837
2838 r = sd_bus_message_exit_container(m);
2839 if (r < 0)
2840 return r;
2841
2842 return 0;
2843}