]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
bus: validate the entire header more closely
[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
1744 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1745 if (!w)
1746 return -ENOMEM;
1747 m->containers = w;
1748
1749 c = message_get_container(m);
1750
1751 if (!c->signature || c->signature[c->index] == 0)
1752 return 0;
1753
1754 signature = strdup(contents);
1755 if (!signature)
1756 return -ENOMEM;
1757
1758 if (type == SD_BUS_TYPE_ARRAY)
1759 r = bus_message_enter_array(m, c, contents, &array_size);
1760 else if (type == SD_BUS_TYPE_VARIANT)
1761 r = bus_message_enter_variant(m, c, contents);
1762 else if (type == SD_BUS_TYPE_STRUCT)
1763 r = bus_message_enter_struct(m, c, contents);
1764 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1765 r = bus_message_enter_dict_entry(m, c, contents);
1766 else
1767 r = -EINVAL;
1768
1769 if (r <= 0) {
1770 free(signature);
1771 return r;
1772 }
1773
1774 /* OK, let's fill it in */
1775 w += m->n_containers++;
1776 w->enclosing = type;
1777 w->signature = signature;
1778 w->index = 0;
1779 w->array_size = array_size;
1780 w->begin = m->rindex;
1781
1782 return 1;
1783}
1784
1785int sd_bus_message_exit_container(sd_bus_message *m) {
1786 struct bus_container *c;
1787
1788 if (!m)
1789 return -EINVAL;
1790 if (!m->sealed)
1791 return -EPERM;
1792 if (m->n_containers <= 0)
1793 return -EINVAL;
1794
1795 c = message_get_container(m);
1796 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
1797 uint32_t l;
1798
1799 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
1800 if (c->begin + l != m->rindex)
1801 return -EBUSY;
1802
1803 } else {
1804 if (c->signature && c->signature[c->index] != 0)
1805 return -EINVAL;
1806 }
1807
1808 free(c->signature);
1809 m->n_containers--;
1810
1811 return 1;
1812}
1813
1814int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
1815 struct bus_container *c;
1816 int r;
1817
1818 if (!m)
1819 return -EINVAL;
1820 if (!m->sealed)
1821 return -EPERM;
1822
1823 c = message_get_container(m);
1824
1825 if (!c->signature || c->signature[c->index] == 0)
1826 goto eof;
1827
1828 if (message_end_of_array(m, m->rindex))
1829 goto eof;
1830
1831 if (bus_type_is_basic(c->signature[c->index])) {
1832 if (contents)
1833 *contents = NULL;
1834 if (type)
1835 *type = c->signature[c->index];
1836 return 1;
1837 }
1838
1839 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
1840
1841 if (contents) {
1842 size_t l;
1843 char *sig;
1844
1845 r = signature_element_length(c->signature+c->index+1, &l);
1846 if (r < 0)
1847 return r;
1848
80a46c73
LP
1849 assert(l >= 1);
1850
9a17484d
LP
1851 sig = strndup(c->signature + c->index + 1, l);
1852 if (!sig)
1853 return -ENOMEM;
1854
1855 free(m->peeked_signature);
1856 m->peeked_signature = sig;
1857
1858 *contents = sig;
1859 }
1860
1861 if (type)
1862 *type = SD_BUS_TYPE_ARRAY;
1863
1864 return 1;
1865 }
1866
1867 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
1868 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
1869
1870 if (contents) {
1871 size_t l;
1872 char *sig;
1873
1874 r = signature_element_length(c->signature+c->index, &l);
1875 if (r < 0)
1876 return r;
1877
1878 assert(l >= 2);
1879 sig = strndup(c->signature + c->index + 1, l - 2);
1880 if (!sig)
1881 return -ENOMEM;
1882
1883 free(m->peeked_signature);
1884 m->peeked_signature = sig;
1885
1886 *contents = sig;
1887 }
1888
1889 if (type)
1890 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
1891
1892 return 1;
1893 }
1894
1895 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
1896 if (contents) {
1897 size_t rindex, l;
1898 void *q;
1899
1900 rindex = m->rindex;
1901 r = message_peek_body(m, &rindex, 1, 1, &q);
1902 if (r < 0)
1903 return r;
1904 if (r == 0)
1905 goto eof;
1906
1907 l = *(uint8_t*) q;
1908 r = message_peek_body(m, &rindex, 1, l+1, &q);
1909 if (r < 0)
1910 return r;
1911 if (r == 0)
1912 return -EBADMSG;
1913
1914 if (!validate_signature(q, l))
1915 return -EBADMSG;
1916
1917 *contents = q;
1918 }
1919
1920 if (type)
1921 *type = SD_BUS_TYPE_VARIANT;
1922
1923 return 1;
1924 }
1925
1926 return -EINVAL;
1927
1928eof:
1929 if (type)
1930 *type = c->enclosing;
1931 if (contents)
1932 *contents = NULL;
1933 return 0;
1934}
1935
89ffcd2a 1936int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
1937 struct bus_container *c;
1938
1939 if (!m)
1940 return -EINVAL;
1941 if (!m->sealed)
1942 return -EPERM;
1943
1944 if (complete) {
1945 reset_containers(m);
1946 m->rindex = 0;
1947 m->root_container.index = 0;
1948
1949 c = message_get_container(m);
1950 } else {
1951 c = message_get_container(m);
1952
1953 c->index = 0;
1954 m->rindex = c->begin;
1955 }
1956
1957 return !isempty(c->signature);
1958}
1959
1960static int message_read_ap(sd_bus_message *m, const char *types, va_list ap) {
1961 const char *t;
1962 int r;
1963
1964 assert(m);
1965 assert(types);
1966
1967 for (t = types; *t; t++) {
1968 switch (*t) {
1969
1970 case SD_BUS_TYPE_BYTE:
1971 case SD_BUS_TYPE_BOOLEAN:
1972 case SD_BUS_TYPE_INT16:
1973 case SD_BUS_TYPE_UINT16:
1974 case SD_BUS_TYPE_INT32:
1975 case SD_BUS_TYPE_UINT32:
1976 case SD_BUS_TYPE_INT64:
1977 case SD_BUS_TYPE_UINT64:
1978 case SD_BUS_TYPE_DOUBLE:
1979 case SD_BUS_TYPE_STRING:
1980 case SD_BUS_TYPE_OBJECT_PATH:
1981 case SD_BUS_TYPE_SIGNATURE: {
1982 void *p;
1983
1984 p = va_arg(ap, void*);
1985 r = sd_bus_message_read_basic(m, *t, p);
1986 break;
1987 }
1988
1989 case SD_BUS_TYPE_ARRAY: {
1990 size_t k;
1991
1992 r = signature_element_length(t + 1, &k);
1993 if (r < 0)
1994 return r;
1995
1996 {
1997 unsigned i, n;
1998 char s[k + 1];
1999
2000 memcpy(s, t + 1, k);
2001 s[k] = 0;
2002 t += k;
2003
2004 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
2005 if (r < 0)
2006 return r;
2007 if (r == 0)
2008 return -ENXIO;
2009
2010 n = va_arg(ap, unsigned);
2011 for (i = 0; i < n; i++) {
2012 r = message_read_ap(m, s, ap);
2013 if (r < 0)
2014 return r;
2015 }
2016
2017 r = sd_bus_message_exit_container(m);
2018 }
2019
2020 break;
2021 }
2022
2023 case SD_BUS_TYPE_VARIANT: {
2024 const char *s;
2025
2026 s = va_arg(ap, const char *);
2027 if (!s)
2028 return -EINVAL;
2029
2030 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
2031 if (r < 0)
2032 return r;
2033 if (r == 0)
2034 return -ENXIO;
2035
2036 r = message_read_ap(m, s, ap);
2037 if (r < 0)
2038 return r;
2039 if (r == 0)
2040 return -ENXIO;
2041
2042 r = sd_bus_message_exit_container(m);
2043 break;
2044 }
2045
2046 case SD_BUS_TYPE_STRUCT_BEGIN:
2047 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2048 size_t k;
2049
2050 r = signature_element_length(t, &k);
2051 if (r < 0)
2052 return r;
2053
2054 {
2055 char s[k - 1];
2056 memcpy(s, t + 1, k - 2);
2057 s[k - 2] = 0;
2058
2059 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2060 if (r < 0)
2061 return r;
2062 if (r == 0)
2063 return -ENXIO;
2064
2065 t += k - 1;
2066
2067 r = message_read_ap(m, s, ap);
2068 if (r < 0)
2069 return r;
2070 if (r == 0)
2071 return -ENXIO;
2072
2073 r = sd_bus_message_exit_container(m);
2074 }
2075
2076 break;
2077 }
2078
2079 default:
2080 r = -EINVAL;
2081 }
2082
2083 if (r < 0)
2084 return r;
2085 if (r == 0)
2086 return -ENXIO;
2087 }
2088
2089 return 1;
2090}
2091
2092int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2093 va_list ap;
2094 int r;
2095
2096 if (!m)
2097 return -EINVAL;
2098 if (!m->sealed)
2099 return -EPERM;
2100 if (!types)
2101 return -EINVAL;
2102
2103 va_start(ap, types);
2104 r = message_read_ap(m, types, ap);
2105 va_end(ap);
2106
2107 return r;
2108}
2109
80a46c73
LP
2110static int message_peek_fields(
2111 sd_bus_message *m,
2112 size_t *rindex,
2113 size_t align,
2114 size_t nbytes,
2115 void **ret) {
2116
2117 assert(m);
2118 assert(rindex);
2119 assert(align > 0);
2120
2121 return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2122}
2123
2124static int message_peek_field_string(
2125 sd_bus_message *m,
6693860f 2126 bool (*validate)(const char *p),
80a46c73
LP
2127 size_t *ri,
2128 const char **ret) {
2129
2130 size_t l;
2131 int r;
2132 void *q;
2133
9a17484d 2134 assert(m);
80a46c73
LP
2135 assert(ri);
2136
2137 r = message_peek_fields(m, ri, 4, 4, &q);
2138 if (r < 0)
2139 return r;
2140
2141 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2142 r = message_peek_fields(m, ri, 1, l+1, &q);
2143 if (r < 0)
2144 return r;
9a17484d 2145
6693860f
LP
2146 if (validate) {
2147 if (!validate_nul(q, l))
2148 return -EBADMSG;
2149
2150 if (!validate(q))
ac89bf1d
LP
2151 return -EBADMSG;
2152 } else {
2153 if (!validate_string(q, l))
2154 return -EBADMSG;
2155 }
80a46c73
LP
2156
2157 if (ret)
2158 *ret = q;
2159
2160 return 0;
2161}
2162
2163static int message_peek_field_signature(
2164 sd_bus_message *m,
2165 size_t *ri,
2166 const char **ret) {
2167
2168 size_t l;
2169 int r;
2170 void *q;
2171
2172 assert(m);
2173 assert(ri);
2174
2175 r = message_peek_fields(m, ri, 1, 1, &q);
2176 if (r < 0)
2177 return r;
2178
2179 l = *(uint8_t*) q;
2180 r = message_peek_fields(m, ri, 1, l+1, &q);
2181 if (r < 0)
2182 return r;
2183
2184 if (!validate_signature(q, l))
2185 return -EBADMSG;
2186
2187 if (ret)
2188 *ret = q;
2189
2190 return 0;
2191}
2192
2193static int message_peek_field_uint32(
2194 sd_bus_message *m,
2195 size_t *ri,
2196 uint32_t *ret) {
2197
2198 int r;
2199 void *q;
2200
2201 assert(m);
2202 assert(ri);
2203
2204 r = message_peek_fields(m, ri, 4, 4, &q);
2205 if (r < 0)
2206 return r;
2207
2208 if (ret)
2209 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2210
2211 return 0;
2212}
2213
2214static int message_skip_fields(
2215 sd_bus_message *m,
2216 size_t *ri,
2217 uint32_t array_size,
2218 const char **signature) {
2219
2220 size_t original_index;
2221 int r;
2222
2223 assert(m);
2224 assert(ri);
2225 assert(signature);
2226
2227 original_index = *ri;
2228
2229 for (;;) {
2230 char t;
2231 void *q;
2232 size_t l;
2233
2234 if (array_size != (uint32_t) -1 &&
2235 array_size <= *ri - original_index)
2236 return 0;
2237
2238 t = **signature;
2239 if (!t)
2240 return 0;
2241
6693860f
LP
2242 if (t == SD_BUS_TYPE_STRING) {
2243
2244 r = message_peek_field_string(m, NULL, ri, NULL);
2245 if (r < 0)
2246 return r;
2247
2248 (*signature)++;
2249
2250 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 2251
6693860f 2252 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
2253 if (r < 0)
2254 return r;
2255
2256 (*signature)++;
2257
2258 } else if (t == SD_BUS_TYPE_SIGNATURE) {
2259
2260 r = message_peek_field_signature(m, ri, NULL);
2261 if (r < 0)
2262 return r;
2263
2264 (*signature)++;
2265
2266 } else if (bus_type_is_basic(t)) {
2267 size_t align, k;
2268
c66a2e0c
TG
2269 align = bus_type_get_alignment(t);
2270 k = bus_type_get_size(t);
80a46c73
LP
2271
2272 r = message_peek_fields(m, ri, align, k, NULL);
2273 if (r < 0)
2274 return r;
9a17484d 2275
80a46c73
LP
2276 (*signature)++;
2277
2278 } else if (t == SD_BUS_TYPE_ARRAY) {
2279
2280 r = signature_element_length(*signature+1, &l);
2281 if (r < 0)
2282 return r;
2283
2284 assert(l >= 1);
2285 {
2286 char sig[l-1], *s;
2287 size_t nas;
2288 int alignment;
2289
2290 strncpy(sig, *signature + 1, l-1);
2291 s = sig;
2292
2293 alignment = bus_type_get_alignment(sig[0]);
2294 if (alignment < 0)
2295 return alignment;
2296
2297 r = message_peek_fields(m, ri, 4, 4, &q);
2298 if (r < 0)
2299 return r;
2300
2301 nas = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
ac89bf1d 2302 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
2303 return -EBADMSG;
2304
2305 r = message_peek_fields(m, ri, alignment, 0, NULL);
2306 if (r < 0)
2307 return r;
2308
2309 r = message_skip_fields(m, ri, nas, (const char**) &s);
2310 if (r < 0)
2311 return r;
2312 }
2313
2314 (*signature) += 1 + l;
2315
2316 } else if (t == SD_BUS_TYPE_VARIANT) {
2317 const char *s;
2318
2319 r = message_peek_field_signature(m, ri, &s);
2320 if (r < 0)
2321 return r;
2322
2323 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2324 if (r < 0)
2325 return r;
2326
2327 (*signature)++;
2328
2329 } else if (t == SD_BUS_TYPE_STRUCT ||
2330 t == SD_BUS_TYPE_DICT_ENTRY) {
2331
2332 r = signature_element_length(*signature, &l);
2333 if (r < 0)
2334 return r;
2335
2336 assert(l >= 2);
2337 {
2338 char sig[l-1], *s;
2339 strncpy(sig, *signature + 1, l-1);
2340 s = sig;
2341
2342 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
2343 if (r < 0)
2344 return r;
2345 }
2346
2347 *signature += l;
2348 } else
2349 return -EINVAL;
2350 }
2351}
2352
2353static int message_parse_fields(sd_bus_message *m) {
2354 size_t ri;
2355 int r;
2356
2357 assert(m);
2358
2359 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
2360 const char *signature;
2361 uint8_t *header;
2362
2363 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
2364 if (r < 0)
2365 return r;
2366
2367 r = message_peek_field_signature(m, &ri, &signature);
2368 if (r < 0)
2369 return r;
2370
2371 switch (*header) {
2372 case _SD_BUS_MESSAGE_HEADER_INVALID:
2373 return -EBADMSG;
2374
2375 case SD_BUS_MESSAGE_HEADER_PATH:
2376 if (!streq(signature, "o"))
2377 return -EBADMSG;
2378
6693860f 2379 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
2380 break;
2381
2382 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2383 if (!streq(signature, "s"))
2384 return -EBADMSG;
2385
6693860f 2386 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
2387 break;
2388
2389 case SD_BUS_MESSAGE_HEADER_MEMBER:
2390 if (!streq(signature, "s"))
2391 return -EBADMSG;
2392
6693860f 2393 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
2394 break;
2395
2396 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2397 if (!streq(signature, "s"))
2398 return -EBADMSG;
2399
6693860f 2400 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
2401 break;
2402
2403 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2404 if (!streq(signature, "s"))
2405 return -EBADMSG;
2406
6693860f 2407 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
2408 break;
2409
2410 case SD_BUS_MESSAGE_HEADER_SENDER:
2411 if (!streq(signature, "s"))
2412 return -EBADMSG;
2413
6693860f 2414 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
2415 break;
2416
2417
2418 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
2419 const char *s;
2420 char *c;
2421
2422 if (!streq(signature, "g"))
2423 return -EBADMSG;
2424
2425 r = message_peek_field_signature(m, &ri, &s);
2426 if (r < 0)
2427 return r;
2428
2429 c = strdup(s);
2430 if (!c)
2431 return -ENOMEM;
2432
2433 free(m->root_container.signature);
2434 m->root_container.signature = c;
2435
2436 r = 0;
2437 break;
2438 }
2439
2440 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2441 if (!streq(signature, "u"))
2442 return -EBADMSG;
2443
2444 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
2445 if (r < 0)
2446 return r;
2447
2448 if (m->reply_serial == 0)
2449 return -EBADMSG;
2450
80a46c73
LP
2451 break;
2452
2453 default:
2454 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
2455 }
2456
2457 if (r < 0)
2458 return r;
2459 }
2460
2461 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
2462 return -EBADMSG;
2463
2464 switch (m->header->type) {
2465
2466 case SD_BUS_MESSAGE_TYPE_SIGNAL:
2467 if (!m->path || !m->interface || !m->member)
2468 return -EBADMSG;
2469 break;
2470
2471 case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
2472
2473 if (!m->path || !m->member)
2474 return -EBADMSG;
2475
2476 break;
2477
2478 case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
2479
2480 if (m->reply_serial == 0)
2481 return -EBADMSG;
2482 break;
2483
2484 case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
2485
2486 if (m->reply_serial == 0 || !m->error.name)
2487 return -EBADMSG;
2488 break;
2489 }
9a17484d 2490
89ffcd2a
LP
2491 /* Try to read the error message, but if we can't it's a non-issue */
2492 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
2493 sd_bus_message_read(m, "s", &m->error.message);
2494
9a17484d
LP
2495 return 0;
2496}
2497
2498static void setup_iovec(sd_bus_message *m) {
2499 assert(m);
2500 assert(m->sealed);
2501
2502 m->n_iovec = 0;
e3017af9 2503 m->size = 0;
9a17484d
LP
2504
2505 m->iovec[m->n_iovec].iov_base = m->header;
2506 m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
e3017af9 2507 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2508 m->n_iovec++;
2509
2510 if (m->fields) {
2511 m->iovec[m->n_iovec].iov_base = m->fields;
2512 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
e3017af9 2513 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2514 m->n_iovec++;
2515
2516 if (m->header->fields_size % 8 != 0) {
2517 static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
2518
2519 m->iovec[m->n_iovec].iov_base = (void*) padding;
2520 m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
e3017af9 2521 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2522 m->n_iovec++;
2523 }
2524 }
2525
2526 if (m->body) {
2527 m->iovec[m->n_iovec].iov_base = m->body;
2528 m->iovec[m->n_iovec].iov_len = m->header->body_size;
e3017af9 2529 m->size += m->iovec[m->n_iovec].iov_len;
9a17484d
LP
2530 m->n_iovec++;
2531 }
2532}
2533
2534int bus_message_seal(sd_bus_message *m, uint64_t serial) {
2535 int r;
2536
2537 assert(m);
2538
2539 if (m->sealed)
2540 return -EPERM;
2541
2542 if (m->n_containers > 0)
2543 return -EBADMSG;
2544
2545 /* If there's a non-trivial signature set, then add it in here */
2546 if (!isempty(m->root_container.signature)) {
80a46c73 2547 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
2548 if (r < 0)
2549 return r;
2550 }
2551
2552 if (m->n_fds > 0) {
2553 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
2554 if (r < 0)
2555 return r;
2556 }
2557
2558 m->header->serial = serial;
2559 m->sealed = true;
2560
2561 setup_iovec(m);
2562
2563 return 0;
2564}
2565
2566int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
2567 if (!m)
2568 return -EINVAL;
2569 if (!destination)
2570 return -EINVAL;
2571 if (m->sealed)
2572 return -EPERM;
2573 if (m->destination)
2574 return -EEXIST;
2575
2576 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
2577}
2578
2579int bus_message_dump(sd_bus_message *m) {
2580 unsigned level = 1;
2581 int r;
2582
2583 assert(m);
2584
2585 printf("Message %p\n"
2586 "\tn_ref=%u\n"
2587 "\tendian=%c\n"
2588 "\ttype=%i\n"
2589 "\tflags=%u\n"
2590 "\tversion=%u\n"
2591 "\tserial=%u\n"
2592 "\tfields_size=%u\n"
2593 "\tbody_size=%u\n"
2594 "\tpath=%s\n"
2595 "\tinterface=%s\n"
2596 "\tmember=%s\n"
2597 "\tdestination=%s\n"
2598 "\tsender=%s\n"
2599 "\tsignature=%s\n"
2600 "\treply_serial=%u\n"
2601 "\terror.name=%s\n"
2602 "\terror.message=%s\n"
2603 "\tsealed=%s\n",
2604 m,
2605 m->n_ref,
2606 m->header->endian,
2607 m->header->type,
2608 m->header->flags,
2609 m->header->version,
2610 BUS_MESSAGE_SERIAL(m),
2611 BUS_MESSAGE_FIELDS_SIZE(m),
2612 BUS_MESSAGE_BODY_SIZE(m),
2613 strna(m->path),
2614 strna(m->interface),
2615 strna(m->member),
2616 strna(m->destination),
2617 strna(m->sender),
80a46c73 2618 strna(m->root_container.signature),
9a17484d
LP
2619 m->reply_serial,
2620 strna(m->error.name),
2621 strna(m->error.message),
2622 yes_no(m->sealed));
2623
2624 r = sd_bus_message_rewind(m, true);
2625 if (r < 0) {
2626 log_error("Failed to rewind: %s", strerror(-r));
2627 return r;
2628 }
2629
80a46c73 2630 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
2631
2632 for(;;) {
2633 _cleanup_free_ char *prefix = NULL;
2634 const char *contents = NULL;
2635 char type;
2636 union {
2637 uint8_t u8;
2638 uint16_t u16;
2639 int16_t s16;
2640 uint32_t u32;
2641 int32_t s32;
2642 uint64_t u64;
2643 int64_t s64;
2644 double d64;
2645 const char *string;
2646 int i;
2647 } basic;
2648
2649 r = sd_bus_message_peek_type(m, &type, &contents);
2650 if (r < 0) {
2651 log_error("Failed to peek type: %s", strerror(-r));
2652 return r;
2653 }
2654 if (r == 0) {
2655 if (level <= 1)
2656 break;
2657
2658 r = sd_bus_message_exit_container(m);
2659 if (r < 0) {
2660 log_error("Failed to exit container: %s", strerror(-r));
2661 return r;
2662 }
2663
2664 level--;
2665
2666 prefix = strrep("\t", level);
2667 if (!prefix)
2668 return log_oom();
2669
2670 if (type == SD_BUS_TYPE_ARRAY)
2671 printf("%s} END_ARRAY \n", prefix);
2672 else if (type == SD_BUS_TYPE_VARIANT)
2673 printf("%s} END_VARIANT\n", prefix);
2674 else if (type == SD_BUS_TYPE_STRUCT)
2675 printf("%s} END_STRUCT\n", prefix);
2676 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2677 printf("%s} END_DICT_ENTRY\n", prefix);
2678
2679 continue;
2680 }
2681
2682 prefix = strrep("\t", level);
2683 if (!prefix)
2684 return log_oom();
2685
2686 if (bus_type_is_container(type) > 0) {
2687 r = sd_bus_message_enter_container(m, type, contents);
2688 if (r < 0) {
2689 log_error("Failed to enter container: %s", strerror(-r));
2690 return r;
2691 }
2692
2693 if (type == SD_BUS_TYPE_ARRAY)
2694 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
2695 else if (type == SD_BUS_TYPE_VARIANT)
2696 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
2697 else if (type == SD_BUS_TYPE_STRUCT)
2698 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
2699 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2700 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
2701
2702 level ++;
2703
2704 continue;
2705 }
2706
2707 r = sd_bus_message_read_basic(m, type, &basic);
2708 if (r < 0) {
2709 log_error("Failed to get basic: %s", strerror(-r));
2710 return r;
2711 }
2712
2713 switch (type) {
2714
2715 case SD_BUS_TYPE_BYTE:
2716 printf("%sBYTE: %u\n", prefix, basic.u8);
2717 break;
2718
2719 case SD_BUS_TYPE_BOOLEAN:
2720 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
2721 break;
2722
2723 case SD_BUS_TYPE_INT16:
2724 printf("%sINT16: %i\n", prefix, basic.s16);
2725 break;
2726
2727 case SD_BUS_TYPE_UINT16:
2728 printf("%sUINT16: %u\n", prefix, basic.u16);
2729 break;
2730
2731 case SD_BUS_TYPE_INT32:
2732 printf("%sINT32: %i\n", prefix, basic.s32);
2733 break;
2734
2735 case SD_BUS_TYPE_UINT32:
2736 printf("%sUINT32: %u\n", prefix, basic.u32);
2737 break;
2738
2739 case SD_BUS_TYPE_INT64:
2740 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
2741 break;
2742
2743 case SD_BUS_TYPE_UINT64:
2744 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
2745 break;
2746
2747 case SD_BUS_TYPE_DOUBLE:
2748 printf("%sDOUBLE: %g\n", prefix, basic.d64);
2749 break;
2750
2751 case SD_BUS_TYPE_STRING:
2752 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
2753 break;
2754
2755 case SD_BUS_TYPE_OBJECT_PATH:
2756 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
2757 break;
2758
2759 case SD_BUS_TYPE_SIGNATURE:
2760 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
2761 break;
2762
2763 case SD_BUS_TYPE_UNIX_FD:
2764 printf("%sUNIX_FD: %i\n", prefix, basic.i);
2765 break;
2766
2767 default:
2768 assert_not_reached("Unknown basic type.");
2769 }
2770 }
2771
2772 printf("} END_MESSAGE\n");
2773 return 0;
de1c301e
LP
2774}
2775
2776int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
2777 size_t total;
2778 unsigned i;
2779 void *p, *e;
2780
2781 assert(m);
2782 assert(buffer);
2783 assert(sz);
2784
2785 for (i = 0, total = 0; i < m->n_iovec; i++)
2786 total += m->iovec[i].iov_len;
2787
2788 p = malloc(total);
2789 if (!p)
2790 return -ENOMEM;
2791
2792 for (i = 0, e = p; i < m->n_iovec; i++)
2793 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);
2794
2795 *buffer = p;
2796 *sz = total;
2797
2798 return 0;
2799}
89ffcd2a
LP
2800
2801int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
2802 int r;
2803
2804 assert(m);
2805 assert(l);
2806
2807 r = sd_bus_message_enter_container(m, 'a', "s");
2808 if (r < 0)
2809 return r;
2810
2811 for (;;) {
2812 const char *s;
2813
2814 r = sd_bus_message_read_basic(m, 's', &s);
2815 if (r < 0)
2816 return r;
2817 if (r == 0)
2818 break;
2819
2820 r = strv_extend(l, s);
2821 if (r < 0)
2822 return r;
2823 }
2824
2825 r = sd_bus_message_exit_container(m);
2826 if (r < 0)
2827 return r;
2828
2829 return 0;
2830}