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