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