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