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