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