]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-message.c
bus: add sd_bus_message_append_string_space() for zero-copy string appending
[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
f8e013f8
LP
1210int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) {
1211 struct bus_container *c;
1212 char *e;
1213 void *a;
1214 int r;
1215
1216 if (!m)
1217 return -EINVAL;
1218 if (!s)
1219 return -EINVAL;
1220 if (m->sealed)
1221 return -EPERM;
1222
1223 c = message_get_container(m);
1224
1225 if (c->signature && c->signature[c->index]) {
1226 /* Container signature is already set */
1227
1228 if (c->signature[c->index] != SD_BUS_TYPE_STRING)
1229 return -ENXIO;
1230 } else {
1231 /* Maybe we can append to the signature? But only if this is the top-level container*/
1232 if (c->enclosing != 0)
1233 return -ENXIO;
1234
1235 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
1236 if (!e)
1237 return -ENOMEM;
1238 }
1239
1240
1241 a = message_extend_body(m, 4, 4 + size + 1);
1242 if (!a) {
1243 r = -ENOMEM;
1244 goto fail;
1245 }
1246
1247 *(uint32_t*) a = size;
1248 *s = (char*) a + 4;
1249
1250 (*s)[size] = 0;
1251
1252 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1253 c->index++;
1254
1255 return 0;
1256
1257fail:
1258 if (e)
1259 c->signature[c->index] = 0;
1260
1261 return r;
1262}
1263
de1c301e
LP
1264static int bus_message_open_array(
1265 sd_bus_message *m,
1266 struct bus_container *c,
1267 const char *contents,
1268 uint32_t **array_size) {
1269
9a17484d 1270 unsigned nindex;
de1c301e 1271 char *e = NULL;
de1c301e
LP
1272 void *a, *b;
1273 int alignment;
1274 size_t saved;
1275
1276 assert(m);
1277 assert(c);
1278 assert(contents);
1279 assert(array_size);
1280
1281 if (!signature_is_single(contents))
1282 return -EINVAL;
1283
1284 alignment = bus_type_get_alignment(contents[0]);
1285 if (alignment < 0)
1286 return alignment;
1287
1288 if (c->signature && c->signature[c->index]) {
1289
1290 /* Verify the existing signature */
1291
1292 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
9a17484d 1293 return -ENXIO;
de1c301e
LP
1294
1295 if (!startswith(c->signature + c->index + 1, contents))
9a17484d 1296 return -ENXIO;
de1c301e
LP
1297
1298 nindex = c->index + 1 + strlen(contents);
1299 } else {
1300 if (c->enclosing != 0)
9a17484d 1301 return -ENXIO;
de1c301e
LP
1302
1303 /* Extend the existing signature */
1304
1305 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
1306 if (!e)
1307 return -ENOMEM;
1308
1309 nindex = e - c->signature;
1310 }
1311
1312 saved = m->header->body_size;
1313 a = message_extend_body(m, 4, 4);
1314 if (!a) {
1315 /* Truncate extended signature again */
1316 if (e)
1317 c->signature[c->index] = 0;
1318
1319 return -ENOMEM;
1320 }
1321 b = m->body;
1322
1323 if (!message_extend_body(m, alignment, 0)) {
1324 /* Add alignment between size and first element */
1325 if (e)
1326 c->signature[c->index] = 0;
1327
1328 m->header->body_size = saved;
1329 return -ENOMEM;
1330 }
1331
1332 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1333 c->index = nindex;
1334
1335 /* m->body might have changed so let's readjust a */
1336 a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
1337 *(uint32_t*) a = 0;
1338
1339 *array_size = a;
1340 return 0;
1341}
1342
1343static int bus_message_open_variant(
1344 sd_bus_message *m,
1345 struct bus_container *c,
1346 const char *contents) {
1347
1348 char *e = NULL;
9a17484d 1349 size_t l;
de1c301e
LP
1350 void *a;
1351
1352 assert(m);
1353 assert(c);
1354 assert(contents);
1355
1356 if (!signature_is_single(contents))
1357 return -EINVAL;
1358
1359 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
1360 return -EINVAL;
1361
1362 if (c->signature && c->signature[c->index]) {
1363
1364 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
9a17484d 1365 return -ENXIO;
de1c301e
LP
1366
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_VARIANT), NULL);
1372 if (!e)
1373 return -ENOMEM;
1374 }
1375
de1c301e
LP
1376 l = strlen(contents);
1377 a = message_extend_body(m, 1, 1 + l + 1);
1378 if (!a) {
1379 /* Truncate extended signature again */
1380 if (e)
1381 c->signature[c->index] = 0;
1382
1383 return -ENOMEM;
1384 }
1385
1386 *(uint8_t*) a = l;
1387 memcpy((uint8_t*) a + 1, contents, l + 1);
1388
1389 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1390 c->index++;
de1c301e
LP
1391
1392 return 0;
1393}
1394
1395static int bus_message_open_struct(
1396 sd_bus_message *m,
1397 struct bus_container *c,
1398 const char *contents) {
1399
1400 size_t nindex;
1401 char *e = NULL;
1402
1403 assert(m);
1404 assert(c);
1405 assert(contents);
1406
1407 if (!signature_is_valid(contents, false))
1408 return -EINVAL;
1409
1410 if (c->signature && c->signature[c->index]) {
1411 size_t l;
1412
1413 l = strlen(contents);
1414
1415 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
1416 !startswith(c->signature + c->index + 1, contents) ||
1417 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
9a17484d 1418 return -ENXIO;
de1c301e
LP
1419
1420 nindex = c->index + 1 + l + 1;
1421 } else {
1422 if (c->enclosing != 0)
9a17484d 1423 return -ENXIO;
de1c301e
LP
1424
1425 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
1426 if (!e)
1427 return -ENOMEM;
1428
1429 nindex = e - c->signature;
1430 }
1431
1432 /* Align contents to 8 byte boundary */
1433 if (!message_extend_body(m, 8, 0)) {
1434 if (e)
1435 c->signature[c->index] = 0;
1436
1437 return -ENOMEM;
1438 }
1439
1440 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1441 c->index = nindex;
1442
1443 return 0;
1444}
1445
1446static int bus_message_open_dict_entry(
1447 sd_bus_message *m,
1448 struct bus_container *c,
1449 const char *contents) {
1450
1451 size_t nindex;
1452
1453 assert(m);
1454 assert(c);
1455 assert(contents);
1456
1457 if (!signature_is_pair(contents))
1458 return -EINVAL;
1459
1460 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1461 return -ENXIO;
de1c301e
LP
1462
1463 if (c->signature && c->signature[c->index]) {
1464 size_t l;
1465
1466 l = strlen(contents);
1467
1468 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
1469 !startswith(c->signature + c->index + 1, contents) ||
1470 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
9a17484d 1471 return -ENXIO;
de1c301e
LP
1472
1473 nindex = c->index + 1 + l + 1;
1474 } else
9a17484d 1475 return -ENXIO;
de1c301e
LP
1476
1477 /* Align contents to 8 byte boundary */
1478 if (!message_extend_body(m, 8, 0))
1479 return -ENOMEM;
1480
1481 if (c->enclosing != SD_BUS_TYPE_ARRAY)
1482 c->index = nindex;
1483
1484 return 0;
1485}
1486
1487int sd_bus_message_open_container(
1488 sd_bus_message *m,
1489 char type,
1490 const char *contents) {
1491
9a17484d 1492 struct bus_container *c, *w;
de1c301e 1493 uint32_t *array_size = NULL;
9a17484d 1494 char *signature;
b3af9646 1495 size_t before;
de1c301e
LP
1496 int r;
1497
1498 if (!m)
1499 return -EINVAL;
1500 if (m->sealed)
1501 return -EPERM;
1502 if (!contents)
1503 return -EINVAL;
1504
1505 /* Make sure we have space for one more container */
9a17484d
LP
1506 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
1507 if (!w)
de1c301e 1508 return -ENOMEM;
9a17484d 1509 m->containers = w;
de1c301e
LP
1510
1511 c = message_get_container(m);
1512
1513 signature = strdup(contents);
1514 if (!signature)
1515 return -ENOMEM;
1516
b3af9646
LP
1517 /* Save old index in the parent container, in case we have to
1518 * abort this container */
1519 c->saved_index = c->index;
1520 before = m->header->body_size;
1521
de1c301e
LP
1522 if (type == SD_BUS_TYPE_ARRAY)
1523 r = bus_message_open_array(m, c, contents, &array_size);
1524 else if (type == SD_BUS_TYPE_VARIANT)
1525 r = bus_message_open_variant(m, c, contents);
1526 else if (type == SD_BUS_TYPE_STRUCT)
1527 r = bus_message_open_struct(m, c, contents);
1528 else if (type == SD_BUS_TYPE_DICT_ENTRY)
1529 r = bus_message_open_dict_entry(m, c, contents);
1530 else
1531 r = -EINVAL;
1532
1533 if (r < 0) {
1534 free(signature);
1535 return r;
1536 }
1537
1538 /* OK, let's fill it in */
9a17484d
LP
1539 w += m->n_containers++;
1540 w->enclosing = type;
1541 w->signature = signature;
1542 w->index = 0;
1543 w->array_size = array_size;
b3af9646
LP
1544 w->before = before;
1545 w->begin = m->rindex;
de1c301e
LP
1546
1547 return 0;
1548}
1549
1550int sd_bus_message_close_container(sd_bus_message *m) {
1551 struct bus_container *c;
1552
1553 if (!m)
1554 return -EINVAL;
1555 if (m->sealed)
1556 return -EPERM;
1557 if (m->n_containers <= 0)
1558 return -EINVAL;
1559
1560 c = message_get_container(m);
de1c301e 1561 if (c->enclosing != SD_BUS_TYPE_ARRAY)
9a17484d 1562 if (c->signature && c->signature[c->index] != 0)
de1c301e
LP
1563 return -EINVAL;
1564
1565 free(c->signature);
1566 m->n_containers--;
1567
1568 return 0;
1569}
1570
b3af9646
LP
1571static void message_abort_container(sd_bus_message *m) {
1572 struct bus_container *c;
1573 size_t delta;
1574
1575 assert(m);
1576 assert(!m->sealed);
1577 assert(m->n_containers > 0);
1578
1579 c = message_get_container(m);
1580
1581 /* Undo appends */
1582 assert(m->header->body_size >= c->before);
1583 delta = m->header->body_size - c->before;
1584 m->header->body_size = c->before;
1585
1586 /* Free container */
1587 free(c->signature);
1588 m->n_containers--;
1589
1590 /* Correct index of new top-level container */
1591 c = message_get_container(m);
1592 c->index = c->saved_index;
1593
1594 /* Correct array sizes all the way up */
1595 for (c = m->containers; c < m->containers + m->n_containers; c++)
1596 if (c->array_size) {
1597 assert(*c->array_size >= delta);
1598 *c->array_size -= delta;
1599 }
1600}
1b492614
LP
1601
1602typedef struct {
1603 const char *types;
1604 unsigned n_struct;
1605 unsigned n_array;
1606} TypeStack;
1607
1608static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
1609 assert(stack);
1610 assert(max > 0);
1611
1612 if (*i >= max)
1613 return -EINVAL;
1614
1615 stack[*i].types = types;
1616 stack[*i].n_struct = n_struct;
1617 stack[*i].n_array = n_array;
1618 (*i)++;
1619
1620 return 0;
1621}
1622
1623static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
1624 assert(stack);
1625 assert(max > 0);
1626 assert(types);
1627 assert(n_struct);
1628 assert(n_array);
1629
1630 if (*i <= 0)
1631 return 0;
1632
1633 (*i)--;
1634 *types = stack[*i].types;
1635 *n_struct = stack[*i].n_struct;
1636 *n_array = stack[*i].n_array;
1637
1638 return 1;
1639}
1640
917b5dc7 1641int bus_message_append_ap(
de1c301e
LP
1642 sd_bus_message *m,
1643 const char *types,
1644 va_list ap) {
1645
1b492614
LP
1646 unsigned n_array, n_struct;
1647 TypeStack stack[BUS_CONTAINER_DEPTH];
1648 unsigned stack_ptr = 0;
de1c301e
LP
1649 int r;
1650
1651 assert(m);
88d331d5
LP
1652
1653 if (!types)
1654 return 0;
de1c301e 1655
1b492614
LP
1656 n_array = (unsigned) -1;
1657 n_struct = strlen(types);
1658
1659 for (;;) {
1660 const char *t;
1661
1662 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
1663 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
1664 if (r < 0)
1665 return r;
1666 if (r == 0)
1667 break;
1668
1669 r = sd_bus_message_close_container(m);
1670 if (r < 0)
1671 return r;
1672
1673 continue;
1674 }
1675
1676 t = types;
1677 if (n_array != (unsigned) -1)
1678 n_array --;
1679 else {
1680 types ++;
1681 n_struct--;
1682 }
1683
de1c301e
LP
1684 switch (*t) {
1685
1686 case SD_BUS_TYPE_BYTE: {
1687 uint8_t x;
1688
1689 x = (uint8_t) va_arg(ap, int);
1690 r = sd_bus_message_append_basic(m, *t, &x);
1691 break;
1692 }
1693
1694 case SD_BUS_TYPE_BOOLEAN:
1695 case SD_BUS_TYPE_INT32:
9a17484d
LP
1696 case SD_BUS_TYPE_UINT32:
1697 case SD_BUS_TYPE_UNIX_FD: {
de1c301e
LP
1698 uint32_t x;
1699
9a17484d
LP
1700 /* We assume a boolean is the same as int32_t */
1701 assert_cc(sizeof(int32_t) == sizeof(int));
1702
de1c301e
LP
1703 x = va_arg(ap, uint32_t);
1704 r = sd_bus_message_append_basic(m, *t, &x);
1705 break;
1706 }
1707
1708 case SD_BUS_TYPE_INT16:
1709 case SD_BUS_TYPE_UINT16: {
1710 uint16_t x;
1711
1712 x = (uint16_t) va_arg(ap, int);
1713 r = sd_bus_message_append_basic(m, *t, &x);
1714 break;
1715 }
1716
1717 case SD_BUS_TYPE_INT64:
1718 case SD_BUS_TYPE_UINT64:
1719 case SD_BUS_TYPE_DOUBLE: {
1720 uint64_t x;
1721
1722 x = va_arg(ap, uint64_t);
1723 r = sd_bus_message_append_basic(m, *t, &x);
1724 break;
1725 }
1726
1727 case SD_BUS_TYPE_STRING:
1728 case SD_BUS_TYPE_OBJECT_PATH:
1729 case SD_BUS_TYPE_SIGNATURE: {
1730 const char *x;
1731
1732 x = va_arg(ap, const char*);
1733 r = sd_bus_message_append_basic(m, *t, x);
1734 break;
1735 }
1736
de1c301e 1737 case SD_BUS_TYPE_ARRAY: {
de1c301e
LP
1738 size_t k;
1739
1740 r = signature_element_length(t + 1, &k);
1741 if (r < 0)
1742 return r;
1743
1744 {
1745 char s[k + 1];
de1c301e
LP
1746 memcpy(s, t + 1, k);
1747 s[k] = 0;
de1c301e
LP
1748
1749 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1750 if (r < 0)
1751 return r;
1b492614 1752 }
de1c301e 1753
1b492614
LP
1754 if (n_array == (unsigned) -1) {
1755 types += k;
1756 n_struct -= k;
de1c301e
LP
1757 }
1758
1b492614
LP
1759 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1760 if (r < 0)
1761 return r;
1762
1763 types = t + 1;
1764 n_struct = k;
1765 n_array = va_arg(ap, unsigned);
1766
de1c301e
LP
1767 break;
1768 }
1769
1770 case SD_BUS_TYPE_VARIANT: {
1771 const char *s;
1772
1773 s = va_arg(ap, const char*);
1774 if (!s)
1775 return -EINVAL;
1776
1777 r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1778 if (r < 0)
1779 return r;
1780
1b492614 1781 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
de1c301e
LP
1782 if (r < 0)
1783 return r;
1784
1b492614
LP
1785 types = s;
1786 n_struct = strlen(s);
1787 n_array = (unsigned) -1;
1788
de1c301e
LP
1789 break;
1790 }
1791
1792 case SD_BUS_TYPE_STRUCT_BEGIN:
1793 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1794 size_t k;
1795
1796 r = signature_element_length(t, &k);
1797 if (r < 0)
1798 return r;
1799
1800 {
1801 char s[k - 1];
1802
1803 memcpy(s, t + 1, k - 2);
1804 s[k - 2] = 0;
1805
1806 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1807 if (r < 0)
1808 return r;
1b492614 1809 }
de1c301e 1810
1b492614
LP
1811 if (n_array == (unsigned) -1) {
1812 types += k - 1;
1813 n_struct -= k - 1;
1814 }
de1c301e 1815
1b492614
LP
1816 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
1817 if (r < 0)
1818 return r;
de1c301e 1819
1b492614
LP
1820 types = t + 1;
1821 n_struct = k - 2;
1822 n_array = (unsigned) -1;
de1c301e
LP
1823
1824 break;
1825 }
1826
1827 default:
1828 r = -EINVAL;
1829 }
1830
1831 if (r < 0)
1832 return r;
1833 }
1834
1835 return 0;
1836}
1837
1838int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1839 va_list ap;
1840 int r;
1841
1842 if (!m)
1843 return -EINVAL;
1844 if (m->sealed)
1845 return -EPERM;
1846 if (!types)
917b5dc7 1847 return 0;
de1c301e
LP
1848
1849 va_start(ap, types);
917b5dc7 1850 r = bus_message_append_ap(m, types, ap);
de1c301e
LP
1851 va_end(ap);
1852
1853 return r;
1854}
1855
f8e013f8 1856int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr) {
b3af9646
LP
1857 ssize_t align, sz;
1858 void *a;
1859 int r;
1860
1861 if (!m)
1862 return -EINVAL;
1863 if (m->sealed)
1864 return -EPERM;
1865 if (!bus_type_is_trivial(type))
1866 return -EINVAL;
1867 if (!ptr && size > 0)
1868 return -EINVAL;
1869
1870 align = bus_type_get_alignment(type);
1871 sz = bus_type_get_size(type);
1872
1873 assert_se(align > 0);
1874 assert_se(sz > 0);
1875
1876 if (size % sz != 0)
1877 return -EINVAL;
1878
1879 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
1880 if (r < 0)
1881 return r;
1882
1883 a = message_extend_body(m, align, size);
1884 if (!a) {
1885 r = -ENOMEM;
1886 goto fail;
1887 }
1888
1889 r = sd_bus_message_close_container(m);
1890 if (r < 0)
1891 goto fail;
1892
1893 *ptr = a;
1894 return 0;
1895
1896fail:
1897 message_abort_container(m);
1898 return r;
1899}
1900
1901int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size) {
1902 int r;
1903 void *p;
1904
1905 if (!ptr && size > 0)
1906 return -EINVAL;
1907
f8e013f8 1908 r = sd_bus_message_append_array_space(m, type, size, &p);
b3af9646
LP
1909 if (r < 0)
1910 return r;
1911
1912 if (size > 0)
1913 memcpy(p, ptr, size);
1914
1915 return 0;
1916}
1917
9a17484d
LP
1918static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
1919 size_t k, start, n;
de1c301e 1920
9a17484d
LP
1921 assert(rindex);
1922 assert(align > 0);
de1c301e 1923
9a17484d
LP
1924 start = ALIGN_TO((size_t) *rindex, align);
1925 n = start + nbytes;
1926
1927 if (n > sz)
1928 return -EBADMSG;
1929
1930 /* Verify that padding is 0 */
1931 for (k = *rindex; k < start; k++)
1932 if (((const uint8_t*) p)[k] != 0)
1933 return -EBADMSG;
1934
1935 if (r)
1936 *r = (uint8_t*) p + start;
1937
1938 *rindex = n;
1939
1940 return 1;
de1c301e
LP
1941}
1942
9a17484d
LP
1943static bool message_end_of_array(sd_bus_message *m, size_t index) {
1944 struct bus_container *c;
de1c301e 1945
9a17484d 1946 assert(m);
de1c301e 1947
9a17484d
LP
1948 c = message_get_container(m);
1949 if (!c->array_size)
1950 return false;
de1c301e 1951
9a17484d 1952 return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
de1c301e
LP
1953}
1954
9a17484d 1955static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, size_t nbytes, void **ret) {
de1c301e 1956 assert(m);
9a17484d
LP
1957 assert(rindex);
1958 assert(align > 0);
de1c301e 1959
9a17484d
LP
1960 if (message_end_of_array(m, *rindex))
1961 return 0;
de1c301e 1962
9a17484d
LP
1963 return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret);
1964}
de1c301e 1965
ac89bf1d 1966static bool validate_nul(const char *s, size_t l) {
de1c301e 1967
9a17484d
LP
1968 /* Check for NUL chars in the string */
1969 if (memchr(s, 0, l))
1970 return false;
de1c301e 1971
9a17484d
LP
1972 /* Check for NUL termination */
1973 if (s[l] != 0)
1974 return false;
de1c301e 1975
ac89bf1d
LP
1976 return true;
1977}
1978
1979static bool validate_string(const char *s, size_t l) {
1980
1981 if (!validate_nul(s, l))
1982 return false;
1983
9a17484d
LP
1984 /* Check if valid UTF8 */
1985 if (!utf8_is_valid(s))
1986 return false;
1987
1988 return true;
de1c301e
LP
1989}
1990
9a17484d 1991static bool validate_signature(const char *s, size_t l) {
de1c301e 1992
ac89bf1d 1993 if (!validate_nul(s, l))
9a17484d 1994 return false;
de1c301e 1995
9a17484d
LP
1996 /* Check if valid signature */
1997 if (!signature_is_valid(s, true))
1998 return false;
1999
2000 return true;
2001}
2002
ac89bf1d
LP
2003static bool validate_object_path(const char *s, size_t l) {
2004
2005 if (!validate_nul(s, l))
2006 return false;
2007
2008 if (!object_path_is_valid(s))
2009 return false;
2010
2011 return true;
2012}
2013
9a17484d
LP
2014int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
2015 struct bus_container *c;
2016 int r;
2017 void *q;
2018
2019 if (!m)
2020 return -EINVAL;
2021 if (!m->sealed)
de1c301e 2022 return -EPERM;
9a17484d
LP
2023 if (!bus_type_is_basic(type))
2024 return -EINVAL;
2c93b4ef
LP
2025 if (!p)
2026 return -EINVAL;
de1c301e 2027
9a17484d 2028 c = message_get_container(m);
de1c301e 2029
9a17484d
LP
2030 if (!c->signature || c->signature[c->index] == 0)
2031 return 0;
2032
2033 if (c->signature[c->index] != type)
2034 return -ENXIO;
2035
2036 switch (type) {
2037
2038 case SD_BUS_TYPE_STRING:
2039 case SD_BUS_TYPE_OBJECT_PATH: {
2040 uint32_t l;
2041 size_t rindex;
2042
2043 rindex = m->rindex;
2044 r = message_peek_body(m, &rindex, 4, 4, &q);
2045 if (r <= 0)
2046 return r;
2047
2048 l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2049 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2050 if (r < 0)
2051 return r;
9a17484d
LP
2052 if (r == 0)
2053 return -EBADMSG;
2054
ac89bf1d
LP
2055 if (type == SD_BUS_TYPE_OBJECT_PATH) {
2056 if (!validate_object_path(q, l))
2057 return -EBADMSG;
2058 } else {
2059 if (!validate_string(q, l))
2060 return -EBADMSG;
2061 }
9a17484d
LP
2062
2063 m->rindex = rindex;
2064 *(const char**) p = q;
2065 break;
de1c301e
LP
2066 }
2067
9a17484d
LP
2068 case SD_BUS_TYPE_SIGNATURE: {
2069 uint8_t l;
2070 size_t rindex;
2071
2072 rindex = m->rindex;
2073 r = message_peek_body(m, &rindex, 1, 1, &q);
2074 if (r <= 0)
2075 return r;
2076
2077 l = *(uint8_t*) q;
2078 r = message_peek_body(m, &rindex, 1, l+1, &q);
de1c301e
LP
2079 if (r < 0)
2080 return r;
9a17484d
LP
2081 if (r == 0)
2082 return -EBADMSG;
2083
2084 if (!validate_signature(q, l))
2085 return -EBADMSG;
2086
2087 m->rindex = rindex;
2088 *(const char**) p = q;
2089 break;
de1c301e
LP
2090 }
2091
9a17484d 2092 default: {
27f6e5c7
ZJS
2093 ssize_t sz, align;
2094 size_t rindex;
de1c301e 2095
9a17484d
LP
2096 align = bus_type_get_alignment(type);
2097 sz = bus_type_get_size(type);
27f6e5c7 2098 assert(align > 0 && sz > 0);
de1c301e 2099
2c93b4ef
LP
2100 rindex = m->rindex;
2101 r = message_peek_body(m, &rindex, align, sz, &q);
9a17484d
LP
2102 if (r <= 0)
2103 return r;
2104
2105 switch (type) {
2106
2107 case SD_BUS_TYPE_BYTE:
2108 *(uint8_t*) p = *(uint8_t*) q;
2109 break;
2110
2111 case SD_BUS_TYPE_BOOLEAN:
2112 *(int*) p = !!*(uint32_t*) q;
2113 break;
2114
2115 case SD_BUS_TYPE_INT16:
2116 case SD_BUS_TYPE_UINT16:
2117 *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
2118 break;
2119
2120 case SD_BUS_TYPE_INT32:
2121 case SD_BUS_TYPE_UINT32:
2122 *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2123 break;
2124
2125 case SD_BUS_TYPE_INT64:
2126 case SD_BUS_TYPE_UINT64:
2127 case SD_BUS_TYPE_DOUBLE:
2128 *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
2129 break;
2130
2c93b4ef 2131 case SD_BUS_TYPE_UNIX_FD: {
2c93b4ef
LP
2132 uint32_t j;
2133
2134 j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2135 if (j >= m->n_fds)
2136 return -EBADMSG;
2137
1ef2af5a 2138 *(int*) p = m->fds[j];
2c93b4ef
LP
2139 break;
2140 }
2141
9a17484d
LP
2142 default:
2143 assert_not_reached("Unknown basic type...");
2144 }
2145
b3af9646 2146 m->rindex = rindex;
2c93b4ef 2147
9a17484d
LP
2148 break;
2149 }
2150 }
2151
2152 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2153 c->index++;
2154
2155 return 1;
de1c301e
LP
2156}
2157
9a17484d
LP
2158static int bus_message_enter_array(
2159 sd_bus_message *m,
2160 struct bus_container *c,
2161 const char *contents,
2162 uint32_t **array_size) {
2163
2164 size_t rindex;
2165 void *q;
2166 int r, alignment;
2167
2168 assert(m);
2169 assert(c);
2170 assert(contents);
2171 assert(array_size);
2172
2173 if (!signature_is_single(contents))
de1c301e 2174 return -EINVAL;
9a17484d
LP
2175
2176 alignment = bus_type_get_alignment(contents[0]);
2177 if (alignment < 0)
2178 return alignment;
2179
2180 if (!c->signature || c->signature[c->index] == 0)
2181 return 0;
2182
2183 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
2184 return -ENXIO;
2185
2186 if (!startswith(c->signature + c->index + 1, contents))
2187 return -ENXIO;
2188
2189 rindex = m->rindex;
2190 r = message_peek_body(m, &rindex, 4, 4, &q);
2191 if (r <= 0)
2192 return r;
2193
ac89bf1d 2194 if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
80a46c73 2195 return -EBADMSG;
9a17484d
LP
2196
2197 r = message_peek_body(m, &rindex, alignment, 0, NULL);
2198 if (r < 0)
2199 return r;
2200 if (r == 0)
2201 return -EBADMSG;
2202
2203 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2204 c->index += 1 + strlen(contents);
2205
2206 m->rindex = rindex;
2207
2208 *array_size = (uint32_t*) q;
2209
2210 return 1;
2211}
2212
2213static int bus_message_enter_variant(
2214 sd_bus_message *m,
2215 struct bus_container *c,
2216 const char *contents) {
2217
2218 size_t rindex;
2219 uint8_t l;
2220 void *q;
2221 int r;
2222
2223 assert(m);
2224 assert(c);
2225 assert(contents);
2226
2227 if (!signature_is_single(contents))
de1c301e 2228 return -EINVAL;
de1c301e 2229
9a17484d
LP
2230 if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
2231 return -EINVAL;
2232
2233 if (!c->signature || c->signature[c->index] == 0)
2234 return 0;
2235
2236 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
2237 return -ENXIO;
2238
2239 rindex = m->rindex;
2240 r = message_peek_body(m, &rindex, 1, 1, &q);
2241 if (r <= 0)
2242 return r;
2243
2244 l = *(uint8_t*) q;
2245 r = message_peek_body(m, &rindex, 1, l+1, &q);
2246 if (r < 0)
2247 return r;
2248 if (r == 0)
2249 return -EBADMSG;
2250
2251 if (!validate_signature(q, l))
2252 return -EBADMSG;
2253
2254 if (!streq(q, contents))
2255 return -ENXIO;
2256
2257 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2258 c->index++;
2259
2260 m->rindex = rindex;
2261
2262 return 1;
de1c301e
LP
2263}
2264
9a17484d
LP
2265static int bus_message_enter_struct(
2266 sd_bus_message *m,
2267 struct bus_container *c,
2268 const char *contents) {
2269
2270 size_t l;
2271 int r;
2272
2273 assert(m);
2274 assert(c);
2275 assert(contents);
2276
2277 if (!signature_is_valid(contents, false))
2278 return -EINVAL;
2279
2280 if (!c->signature || c->signature[c->index] == 0)
2281 return 0;
2282
2283 l = strlen(contents);
2284
2285 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
2286 !startswith(c->signature + c->index + 1, contents) ||
2287 c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
2288 return -ENXIO;
2289
2290 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2291 if (r <= 0)
2292 return r;
2293
2294 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2295 c->index += 1 + l + 1;
2296
2297 return 1;
2298}
2299
2300static int bus_message_enter_dict_entry(
2301 sd_bus_message *m,
2302 struct bus_container *c,
2303 const char *contents) {
2304
2305 size_t l;
2306 int r;
2307
2308 assert(m);
2309 assert(c);
2310 assert(contents);
2311
2312 if (!signature_is_pair(contents))
2313 return -EINVAL;
2314
2315 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2316 return -ENXIO;
2317
2318 if (!c->signature || c->signature[c->index] == 0)
2319 return 0;
2320
2321 l = strlen(contents);
2322
2323 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
2324 !startswith(c->signature + c->index + 1, contents) ||
2325 c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
2326 return -ENXIO;
2327
2328 r = message_peek_body(m, &m->rindex, 8, 0, NULL);
2329 if (r <= 0)
2330 return r;
2331
2332 if (c->enclosing != SD_BUS_TYPE_ARRAY)
2333 c->index += 1 + l + 1;
2334
2335 return 1;
2336}
2337
2338int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents) {
2339 struct bus_container *c, *w;
2340 uint32_t *array_size = NULL;
2341 char *signature;
b3af9646 2342 size_t before;
9a17484d
LP
2343 int r;
2344
2345 if (!m)
2346 return -EINVAL;
2347 if (!m->sealed)
2348 return -EPERM;
2349 if (!contents)
2350 return -EINVAL;
2351
ed205a6b
LP
2352 /*
2353 * We enforce a global limit on container depth, that is much
2354 * higher than the 32 structs and 32 arrays the specification
2355 * mandates. This is simpler to implement for us, and we need
2356 * this only to ensure our container array doesn't grow
2357 * without bounds. We are happy to return any data from a
2358 * message as long as the data itself is valid, even if the
2359 * overall message might be not.
2360 *
2361 * Note that the message signature is validated when
2362 * parsing the headers, and that validation does check the
2363 * 32/32 limit.
2364 *
2365 * Note that the specification defines no limits on the depth
2366 * of stacked variants, but we do.
2367 */
2368 if (m->n_containers >= BUS_CONTAINER_DEPTH)
2369 return -EBADMSG;
2370
9a17484d
LP
2371 w = realloc(m->containers, sizeof(struct bus_container) * (m->n_containers + 1));
2372 if (!w)
2373 return -ENOMEM;
2374 m->containers = w;
2375
2376 c = message_get_container(m);
2377
2378 if (!c->signature || c->signature[c->index] == 0)
2379 return 0;
2380
2381 signature = strdup(contents);
2382 if (!signature)
2383 return -ENOMEM;
2384
b3af9646
LP
2385 c->saved_index = c->index;
2386 before = m->rindex;
2387
9a17484d
LP
2388 if (type == SD_BUS_TYPE_ARRAY)
2389 r = bus_message_enter_array(m, c, contents, &array_size);
2390 else if (type == SD_BUS_TYPE_VARIANT)
2391 r = bus_message_enter_variant(m, c, contents);
2392 else if (type == SD_BUS_TYPE_STRUCT)
2393 r = bus_message_enter_struct(m, c, contents);
2394 else if (type == SD_BUS_TYPE_DICT_ENTRY)
2395 r = bus_message_enter_dict_entry(m, c, contents);
2396 else
2397 r = -EINVAL;
2398
2399 if (r <= 0) {
2400 free(signature);
2401 return r;
2402 }
2403
2404 /* OK, let's fill it in */
2405 w += m->n_containers++;
2406 w->enclosing = type;
2407 w->signature = signature;
2408 w->index = 0;
2409 w->array_size = array_size;
b3af9646 2410 w->before = before;
9a17484d
LP
2411 w->begin = m->rindex;
2412
2413 return 1;
2414}
2415
2416int sd_bus_message_exit_container(sd_bus_message *m) {
2417 struct bus_container *c;
2418
2419 if (!m)
2420 return -EINVAL;
2421 if (!m->sealed)
2422 return -EPERM;
2423 if (m->n_containers <= 0)
2424 return -EINVAL;
2425
2426 c = message_get_container(m);
2427 if (c->enclosing == SD_BUS_TYPE_ARRAY) {
2428 uint32_t l;
2429
2430 l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
2431 if (c->begin + l != m->rindex)
2432 return -EBUSY;
2433
2434 } else {
2435 if (c->signature && c->signature[c->index] != 0)
2436 return -EINVAL;
2437 }
2438
2439 free(c->signature);
2440 m->n_containers--;
2441
2442 return 1;
2443}
2444
b3af9646
LP
2445static void message_quit_container(sd_bus_message *m) {
2446 struct bus_container *c;
2447
2448 assert(m);
2449 assert(m->sealed);
2450 assert(m->n_containers > 0);
2451
2452 c = message_get_container(m);
2453
2454 /* Undo seeks */
2455 assert(m->rindex >= c->before);
2456 m->rindex = c->before;
2457
2458 /* Free container */
2459 free(c->signature);
2460 m->n_containers--;
2461
2462 /* Correct index of new top-level container */
2463 c = message_get_container(m);
2464 c->index = c->saved_index;
2465}
2466
9a17484d
LP
2467int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
2468 struct bus_container *c;
2469 int r;
2470
2471 if (!m)
2472 return -EINVAL;
2473 if (!m->sealed)
2474 return -EPERM;
2475
2476 c = message_get_container(m);
2477
2478 if (!c->signature || c->signature[c->index] == 0)
2479 goto eof;
2480
2481 if (message_end_of_array(m, m->rindex))
2482 goto eof;
2483
2484 if (bus_type_is_basic(c->signature[c->index])) {
2485 if (contents)
2486 *contents = NULL;
2487 if (type)
2488 *type = c->signature[c->index];
2489 return 1;
2490 }
2491
2492 if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
2493
2494 if (contents) {
2495 size_t l;
2496 char *sig;
2497
2498 r = signature_element_length(c->signature+c->index+1, &l);
2499 if (r < 0)
2500 return r;
2501
80a46c73
LP
2502 assert(l >= 1);
2503
9a17484d
LP
2504 sig = strndup(c->signature + c->index + 1, l);
2505 if (!sig)
2506 return -ENOMEM;
2507
2508 free(m->peeked_signature);
2509 m->peeked_signature = sig;
2510
2511 *contents = sig;
2512 }
2513
2514 if (type)
2515 *type = SD_BUS_TYPE_ARRAY;
2516
2517 return 1;
2518 }
2519
2520 if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
2521 c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
2522
2523 if (contents) {
2524 size_t l;
2525 char *sig;
2526
2527 r = signature_element_length(c->signature+c->index, &l);
2528 if (r < 0)
2529 return r;
2530
2531 assert(l >= 2);
2532 sig = strndup(c->signature + c->index + 1, l - 2);
2533 if (!sig)
2534 return -ENOMEM;
2535
2536 free(m->peeked_signature);
2537 m->peeked_signature = sig;
2538
2539 *contents = sig;
2540 }
2541
2542 if (type)
2543 *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
2544
2545 return 1;
2546 }
2547
2548 if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
2549 if (contents) {
2550 size_t rindex, l;
2551 void *q;
2552
2553 rindex = m->rindex;
2554 r = message_peek_body(m, &rindex, 1, 1, &q);
2555 if (r < 0)
2556 return r;
2557 if (r == 0)
2558 goto eof;
2559
2560 l = *(uint8_t*) q;
2561 r = message_peek_body(m, &rindex, 1, l+1, &q);
2562 if (r < 0)
2563 return r;
2564 if (r == 0)
2565 return -EBADMSG;
2566
2567 if (!validate_signature(q, l))
2568 return -EBADMSG;
2569
2570 *contents = q;
2571 }
2572
2573 if (type)
2574 *type = SD_BUS_TYPE_VARIANT;
2575
2576 return 1;
2577 }
2578
2579 return -EINVAL;
2580
2581eof:
2582 if (type)
2583 *type = c->enclosing;
2584 if (contents)
2585 *contents = NULL;
2586 return 0;
2587}
2588
89ffcd2a 2589int sd_bus_message_rewind(sd_bus_message *m, int complete) {
9a17484d
LP
2590 struct bus_container *c;
2591
2592 if (!m)
2593 return -EINVAL;
2594 if (!m->sealed)
2595 return -EPERM;
2596
2597 if (complete) {
2598 reset_containers(m);
2599 m->rindex = 0;
2600 m->root_container.index = 0;
2601
2602 c = message_get_container(m);
2603 } else {
2604 c = message_get_container(m);
2605
2606 c->index = 0;
2607 m->rindex = c->begin;
2608 }
2609
2610 return !isempty(c->signature);
2611}
1b492614
LP
2612static int message_read_ap(
2613 sd_bus_message *m,
2614 const char *types,
2615 va_list ap) {
9a17484d 2616
fe1d424d
LP
2617 unsigned n_array, n_struct;
2618 TypeStack stack[BUS_CONTAINER_DEPTH];
2619 unsigned stack_ptr = 0;
9a17484d
LP
2620 int r;
2621
2622 assert(m);
1b492614
LP
2623
2624 if (!types)
2625 return 0;
9a17484d 2626
fe1d424d
LP
2627 /* Ideally, we'd just call ourselves recursively on every
2628 * complex type. However, the state of a va_list that is
2629 * passed to a function is undefined after that function
2630 * returns. This means we need to docode the va_list linearly
2631 * in a single stackframe. We hence implement our own
2632 * home-grown stack in an array. */
2633
2634 n_array = (unsigned) -1;
2635 n_struct = strlen(types);
2636
2637 for (;;) {
2638 const char *t;
2639
1b492614 2640 if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
fe1d424d
LP
2641 r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
2642 if (r < 0)
2643 return r;
2644 if (r == 0)
2645 break;
2646
2647 r = sd_bus_message_exit_container(m);
2648 if (r < 0)
2649 return r;
2650
2651 continue;
2652 }
2653
2654 t = types;
2655 if (n_array != (unsigned) -1)
2656 n_array --;
2657 else {
2658 types ++;
2659 n_struct--;
2660 }
2661
9a17484d
LP
2662 switch (*t) {
2663
2664 case SD_BUS_TYPE_BYTE:
2665 case SD_BUS_TYPE_BOOLEAN:
2666 case SD_BUS_TYPE_INT16:
2667 case SD_BUS_TYPE_UINT16:
2668 case SD_BUS_TYPE_INT32:
2669 case SD_BUS_TYPE_UINT32:
2670 case SD_BUS_TYPE_INT64:
2671 case SD_BUS_TYPE_UINT64:
2672 case SD_BUS_TYPE_DOUBLE:
2673 case SD_BUS_TYPE_STRING:
2674 case SD_BUS_TYPE_OBJECT_PATH:
2c93b4ef
LP
2675 case SD_BUS_TYPE_SIGNATURE:
2676 case SD_BUS_TYPE_UNIX_FD: {
9a17484d
LP
2677 void *p;
2678
2679 p = va_arg(ap, void*);
2680 r = sd_bus_message_read_basic(m, *t, p);
fe1d424d
LP
2681 if (r < 0)
2682 return r;
2683 if (r == 0)
2684 return -ENXIO;
2685
9a17484d
LP
2686 break;
2687 }
2688
2689 case SD_BUS_TYPE_ARRAY: {
2690 size_t k;
2691
2692 r = signature_element_length(t + 1, &k);
2693 if (r < 0)
2694 return r;
2695
2696 {
9a17484d 2697 char s[k + 1];
9a17484d
LP
2698 memcpy(s, t + 1, k);
2699 s[k] = 0;
9a17484d
LP
2700
2701 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
2702 if (r < 0)
2703 return r;
2704 if (r == 0)
2705 return -ENXIO;
fe1d424d 2706 }
9a17484d 2707
fe1d424d
LP
2708 if (n_array == (unsigned) -1) {
2709 types += k;
2710 n_struct -= k;
9a17484d
LP
2711 }
2712
fe1d424d
LP
2713 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2714 if (r < 0)
2715 return r;
2716
2717 types = t + 1;
2718 n_struct = k;
2719 n_array = va_arg(ap, unsigned);
2720
9a17484d
LP
2721 break;
2722 }
2723
2724 case SD_BUS_TYPE_VARIANT: {
2725 const char *s;
2726
2727 s = va_arg(ap, const char *);
2728 if (!s)
2729 return -EINVAL;
2730
2731 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
2732 if (r < 0)
2733 return r;
2734 if (r == 0)
2735 return -ENXIO;
2736
fe1d424d 2737 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
9a17484d
LP
2738 if (r < 0)
2739 return r;
9a17484d 2740
fe1d424d
LP
2741 types = s;
2742 n_struct = strlen(s);
2743 n_array = (unsigned) -1;
2744
9a17484d
LP
2745 break;
2746 }
2747
2748 case SD_BUS_TYPE_STRUCT_BEGIN:
2749 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
2750 size_t k;
2751
2752 r = signature_element_length(t, &k);
2753 if (r < 0)
2754 return r;
2755
2756 {
2757 char s[k - 1];
2758 memcpy(s, t + 1, k - 2);
2759 s[k - 2] = 0;
2760
2761 r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
2762 if (r < 0)
2763 return r;
2764 if (r == 0)
2765 return -ENXIO;
fe1d424d 2766 }
9a17484d 2767
fe1d424d
LP
2768 if (n_array == (unsigned) -1) {
2769 types += k - 1;
2770 n_struct -= k - 1;
2771 }
9a17484d 2772
fe1d424d
LP
2773 r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
2774 if (r < 0)
2775 return r;
9a17484d 2776
fe1d424d
LP
2777 types = t + 1;
2778 n_struct = k - 2;
2779 n_array = (unsigned) -1;
9a17484d
LP
2780
2781 break;
2782 }
2783
2784 default:
fe1d424d 2785 return -EINVAL;
9a17484d 2786 }
9a17484d
LP
2787 }
2788
2789 return 1;
2790}
2791
2792int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
2793 va_list ap;
2794 int r;
2795
2796 if (!m)
2797 return -EINVAL;
2798 if (!m->sealed)
2799 return -EPERM;
2800 if (!types)
2801 return -EINVAL;
2802
2803 va_start(ap, types);
2804 r = message_read_ap(m, types, ap);
2805 va_end(ap);
2806
2807 return r;
2808}
2809
b3af9646
LP
2810int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size) {
2811 struct bus_container *c;
2812 void *p;
2813 size_t sz;
2814 ssize_t align;
2815 int r;
2816
2817 if (!m)
2818 return -EINVAL;
2819 if (!m->sealed)
2820 return -EPERM;
2821 if (!bus_type_is_trivial(type))
2822 return -EINVAL;
2823 if (!ptr)
2824 return -EINVAL;
2825 if (!size)
2826 return -EINVAL;
2827 if (BUS_MESSAGE_NEED_BSWAP(m))
2828 return -ENOTSUP;
2829
2830 align = bus_type_get_alignment(type);
2831 if (align < 0)
2832 return align;
2833
2834 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
2835 if (r < 0)
2836 return r;
2837
2838 c = message_get_container(m);
2839 sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
2840
2841 r = message_peek_body(m, &m->rindex, align, sz, &p);
2842 if (r < 0)
2843 goto fail;
2844 if (r == 0) {
2845 r = -EBADMSG;
2846 goto fail;
2847 }
2848
2849 r = sd_bus_message_exit_container(m);
2850 if (r < 0)
2851 goto fail;
2852
2853 *ptr = (const void*) p;
2854 *size = sz;
2855
2856 return 1;
2857
2858fail:
2859 message_quit_container(m);
2860 return r;
2861}
2862
80a46c73
LP
2863static int message_peek_fields(
2864 sd_bus_message *m,
2865 size_t *rindex,
2866 size_t align,
2867 size_t nbytes,
2868 void **ret) {
2869
2870 assert(m);
2871 assert(rindex);
2872 assert(align > 0);
2873
2874 return buffer_peek(m->fields, BUS_MESSAGE_FIELDS_SIZE(m), rindex, align, nbytes, ret);
2875}
2876
9f26c90c
LP
2877static int message_peek_field_uint32(
2878 sd_bus_message *m,
2879 size_t *ri,
2880 uint32_t *ret) {
2881
2882 int r;
2883 void *q;
2884
2885 assert(m);
2886 assert(ri);
2887
2888 r = message_peek_fields(m, ri, 4, 4, &q);
2889 if (r < 0)
2890 return r;
2891
2892 if (ret)
2893 *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
2894
2895 return 0;
2896}
2897
80a46c73
LP
2898static int message_peek_field_string(
2899 sd_bus_message *m,
6693860f 2900 bool (*validate)(const char *p),
80a46c73
LP
2901 size_t *ri,
2902 const char **ret) {
2903
9f26c90c 2904 uint32_t l;
80a46c73
LP
2905 int r;
2906 void *q;
2907
9a17484d 2908 assert(m);
80a46c73
LP
2909 assert(ri);
2910
9f26c90c 2911 r = message_peek_field_uint32(m, ri, &l);
80a46c73
LP
2912 if (r < 0)
2913 return r;
2914
80a46c73
LP
2915 r = message_peek_fields(m, ri, 1, l+1, &q);
2916 if (r < 0)
2917 return r;
9a17484d 2918
6693860f
LP
2919 if (validate) {
2920 if (!validate_nul(q, l))
2921 return -EBADMSG;
2922
2923 if (!validate(q))
ac89bf1d
LP
2924 return -EBADMSG;
2925 } else {
2926 if (!validate_string(q, l))
2927 return -EBADMSG;
2928 }
80a46c73
LP
2929
2930 if (ret)
2931 *ret = q;
2932
2933 return 0;
2934}
2935
2936static int message_peek_field_signature(
2937 sd_bus_message *m,
2938 size_t *ri,
2939 const char **ret) {
2940
2941 size_t l;
2942 int r;
2943 void *q;
2944
2945 assert(m);
2946 assert(ri);
2947
2948 r = message_peek_fields(m, ri, 1, 1, &q);
2949 if (r < 0)
2950 return r;
2951
2952 l = *(uint8_t*) q;
2953 r = message_peek_fields(m, ri, 1, l+1, &q);
2954 if (r < 0)
2955 return r;
2956
2957 if (!validate_signature(q, l))
2958 return -EBADMSG;
2959
2960 if (ret)
2961 *ret = q;
2962
2963 return 0;
2964}
2965
80a46c73
LP
2966static int message_skip_fields(
2967 sd_bus_message *m,
2968 size_t *ri,
2969 uint32_t array_size,
2970 const char **signature) {
2971
2972 size_t original_index;
2973 int r;
2974
2975 assert(m);
2976 assert(ri);
2977 assert(signature);
2978
2979 original_index = *ri;
2980
2981 for (;;) {
2982 char t;
80a46c73
LP
2983 size_t l;
2984
2985 if (array_size != (uint32_t) -1 &&
2986 array_size <= *ri - original_index)
2987 return 0;
2988
2989 t = **signature;
2990 if (!t)
2991 return 0;
2992
6693860f
LP
2993 if (t == SD_BUS_TYPE_STRING) {
2994
2995 r = message_peek_field_string(m, NULL, ri, NULL);
2996 if (r < 0)
2997 return r;
2998
2999 (*signature)++;
3000
3001 } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
80a46c73 3002
6693860f 3003 r = message_peek_field_string(m, object_path_is_valid, ri, NULL);
80a46c73
LP
3004 if (r < 0)
3005 return r;
3006
3007 (*signature)++;
3008
3009 } else if (t == SD_BUS_TYPE_SIGNATURE) {
3010
3011 r = message_peek_field_signature(m, ri, NULL);
3012 if (r < 0)
3013 return r;
3014
3015 (*signature)++;
3016
3017 } else if (bus_type_is_basic(t)) {
27f6e5c7 3018 ssize_t align, k;
80a46c73 3019
c66a2e0c
TG
3020 align = bus_type_get_alignment(t);
3021 k = bus_type_get_size(t);
27f6e5c7 3022 assert(align > 0 && k > 0);
80a46c73
LP
3023
3024 r = message_peek_fields(m, ri, align, k, NULL);
3025 if (r < 0)
3026 return r;
9a17484d 3027
80a46c73
LP
3028 (*signature)++;
3029
3030 } else if (t == SD_BUS_TYPE_ARRAY) {
3031
3032 r = signature_element_length(*signature+1, &l);
3033 if (r < 0)
3034 return r;
3035
3036 assert(l >= 1);
3037 {
3038 char sig[l-1], *s;
9f26c90c 3039 uint32_t nas;
80a46c73
LP
3040 int alignment;
3041
3042 strncpy(sig, *signature + 1, l-1);
3043 s = sig;
3044
3045 alignment = bus_type_get_alignment(sig[0]);
3046 if (alignment < 0)
3047 return alignment;
3048
9f26c90c 3049 r = message_peek_field_uint32(m, ri, &nas);
80a46c73
LP
3050 if (r < 0)
3051 return r;
ac89bf1d 3052 if (nas > BUS_ARRAY_MAX_SIZE)
80a46c73
LP
3053 return -EBADMSG;
3054
3055 r = message_peek_fields(m, ri, alignment, 0, NULL);
3056 if (r < 0)
3057 return r;
3058
3059 r = message_skip_fields(m, ri, nas, (const char**) &s);
3060 if (r < 0)
3061 return r;
3062 }
3063
3064 (*signature) += 1 + l;
3065
3066 } else if (t == SD_BUS_TYPE_VARIANT) {
3067 const char *s;
3068
3069 r = message_peek_field_signature(m, ri, &s);
3070 if (r < 0)
3071 return r;
3072
3073 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3074 if (r < 0)
3075 return r;
3076
3077 (*signature)++;
3078
3079 } else if (t == SD_BUS_TYPE_STRUCT ||
3080 t == SD_BUS_TYPE_DICT_ENTRY) {
3081
3082 r = signature_element_length(*signature, &l);
3083 if (r < 0)
3084 return r;
3085
3086 assert(l >= 2);
3087 {
3088 char sig[l-1], *s;
3089 strncpy(sig, *signature + 1, l-1);
3090 s = sig;
3091
3092 r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
3093 if (r < 0)
3094 return r;
3095 }
3096
3097 *signature += l;
3098 } else
3099 return -EINVAL;
3100 }
3101}
3102
6629161f 3103int bus_message_parse_fields(sd_bus_message *m) {
80a46c73
LP
3104 size_t ri;
3105 int r;
2c93b4ef 3106 uint32_t unix_fds = 0;
80a46c73
LP
3107
3108 assert(m);
3109
3110 for (ri = 0; ri < BUS_MESSAGE_FIELDS_SIZE(m); ) {
3111 const char *signature;
3112 uint8_t *header;
3113
3114 r = message_peek_fields(m, &ri, 8, 1, (void**) &header);
3115 if (r < 0)
3116 return r;
3117
3118 r = message_peek_field_signature(m, &ri, &signature);
3119 if (r < 0)
3120 return r;
3121
3122 switch (*header) {
3123 case _SD_BUS_MESSAGE_HEADER_INVALID:
3124 return -EBADMSG;
3125
3126 case SD_BUS_MESSAGE_HEADER_PATH:
2c93b4ef
LP
3127
3128 if (m->path)
3129 return -EBADMSG;
3130
80a46c73
LP
3131 if (!streq(signature, "o"))
3132 return -EBADMSG;
3133
6693860f 3134 r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path);
80a46c73
LP
3135 break;
3136
3137 case SD_BUS_MESSAGE_HEADER_INTERFACE:
2c93b4ef
LP
3138
3139 if (m->interface)
3140 return -EBADMSG;
3141
80a46c73
LP
3142 if (!streq(signature, "s"))
3143 return -EBADMSG;
3144
6693860f 3145 r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface);
80a46c73
LP
3146 break;
3147
3148 case SD_BUS_MESSAGE_HEADER_MEMBER:
2c93b4ef
LP
3149
3150 if (m->member)
3151 return -EBADMSG;
3152
80a46c73
LP
3153 if (!streq(signature, "s"))
3154 return -EBADMSG;
3155
6693860f 3156 r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member);
80a46c73
LP
3157 break;
3158
3159 case SD_BUS_MESSAGE_HEADER_ERROR_NAME:
2c93b4ef
LP
3160
3161 if (m->error.name)
3162 return -EBADMSG;
3163
80a46c73
LP
3164 if (!streq(signature, "s"))
3165 return -EBADMSG;
3166
6693860f 3167 r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name);
80a46c73
LP
3168 break;
3169
3170 case SD_BUS_MESSAGE_HEADER_DESTINATION:
2c93b4ef
LP
3171
3172 if (m->destination)
3173 return -EBADMSG;
3174
80a46c73
LP
3175 if (!streq(signature, "s"))
3176 return -EBADMSG;
3177
6693860f 3178 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination);
80a46c73
LP
3179 break;
3180
3181 case SD_BUS_MESSAGE_HEADER_SENDER:
2c93b4ef
LP
3182
3183 if (m->sender)
3184 return -EBADMSG;
3185
80a46c73
LP
3186 if (!streq(signature, "s"))
3187 return -EBADMSG;
3188
6693860f 3189 r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender);
80a46c73
LP
3190 break;
3191
3192
3193 case SD_BUS_MESSAGE_HEADER_SIGNATURE: {
3194 const char *s;
3195 char *c;
3196
2c93b4ef
LP
3197 if (m->root_container.signature)
3198 return -EBADMSG;
3199
80a46c73
LP
3200 if (!streq(signature, "g"))
3201 return -EBADMSG;
3202
3203 r = message_peek_field_signature(m, &ri, &s);
3204 if (r < 0)
3205 return r;
3206
3207 c = strdup(s);
3208 if (!c)
3209 return -ENOMEM;
3210
3211 free(m->root_container.signature);
3212 m->root_container.signature = c;
80a46c73
LP
3213 break;
3214 }
3215
3216 case SD_BUS_MESSAGE_HEADER_REPLY_SERIAL:
2c93b4ef
LP
3217 if (m->reply_serial != 0)
3218 return -EBADMSG;
3219
80a46c73
LP
3220 if (!streq(signature, "u"))
3221 return -EBADMSG;
3222
3223 r = message_peek_field_uint32(m, &ri, &m->reply_serial);
6693860f
LP
3224 if (r < 0)
3225 return r;
3226
3227 if (m->reply_serial == 0)
3228 return -EBADMSG;
3229
80a46c73
LP
3230 break;
3231
2c93b4ef
LP
3232 case SD_BUS_MESSAGE_HEADER_UNIX_FDS:
3233 if (unix_fds != 0)
3234 return -EBADMSG;
3235
3236 if (!streq(signature, "u"))
3237 return -EBADMSG;
3238
3239 r = message_peek_field_uint32(m, &ri, &unix_fds);
3240 if (r < 0)
3241 return -EBADMSG;
3242
3243 if (unix_fds == 0)
3244 return -EBADMSG;
3245
3246 break;
3247
80a46c73
LP
3248 default:
3249 r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
3250 }
3251
3252 if (r < 0)
3253 return r;
3254 }
3255
2c93b4ef
LP
3256 if (m->n_fds != unix_fds)
3257 return -EBADMSG;
3258
80a46c73
LP
3259 if (isempty(m->root_container.signature) != (BUS_MESSAGE_BODY_SIZE(m) == 0))
3260 return -EBADMSG;
3261
3262 switch (m->header->type) {
3263
3264 case SD_BUS_MESSAGE_TYPE_SIGNAL:
3265 if (!m->path || !m->interface || !m->member)
3266 return -EBADMSG;
3267 break;
3268
3269 case SD_BUS_MESSAGE_TYPE_METHOD_CALL:
3270
3271 if (!m->path || !m->member)
3272 return -EBADMSG;
3273
3274 break;
3275
3276 case SD_BUS_MESSAGE_TYPE_METHOD_RETURN:
3277
3278 if (m->reply_serial == 0)
3279 return -EBADMSG;
3280 break;
3281
3282 case SD_BUS_MESSAGE_TYPE_METHOD_ERROR:
3283
3284 if (m->reply_serial == 0 || !m->error.name)
3285 return -EBADMSG;
3286 break;
3287 }
9a17484d 3288
89ffcd2a
LP
3289 /* Try to read the error message, but if we can't it's a non-issue */
3290 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
3291 sd_bus_message_read(m, "s", &m->error.message);
3292
9a17484d
LP
3293 return 0;
3294}
3295
9a17484d
LP
3296int bus_message_seal(sd_bus_message *m, uint64_t serial) {
3297 int r;
69aec65c 3298 size_t l, a;
9a17484d
LP
3299
3300 assert(m);
3301
3302 if (m->sealed)
3303 return -EPERM;
3304
3305 if (m->n_containers > 0)
3306 return -EBADMSG;
3307
3308 /* If there's a non-trivial signature set, then add it in here */
3309 if (!isempty(m->root_container.signature)) {
80a46c73 3310 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
9a17484d
LP
3311 if (r < 0)
3312 return r;
3313 }
3314
3315 if (m->n_fds > 0) {
3316 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
3317 if (r < 0)
3318 return r;
3319 }
3320
69aec65c
LP
3321 l = BUS_MESSAGE_FIELDS_SIZE(m);
3322 a = ALIGN8(l) - l;
3323
3324 if (a > 0) {
3325 /* Add padding at the end, since we know the body
3326 * needs to start at an 8 byte alignment. */
3327 void *p;
3328
3329 p = message_extend_fields(m, 1, a);
3330 if (!p)
3331 return -ENOMEM;
3332
3333 memset(p, 0, a);
3334 m->header->fields_size -= a;
3335 }
3336
9a17484d
LP
3337 m->header->serial = serial;
3338 m->sealed = true;
3339
9a17484d
LP
3340 return 0;
3341}
3342
3343int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
3344 if (!m)
3345 return -EINVAL;
3346 if (!destination)
3347 return -EINVAL;
3348 if (m->sealed)
3349 return -EPERM;
3350 if (m->destination)
3351 return -EEXIST;
3352
3353 return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
3354}
3355
3356int bus_message_dump(sd_bus_message *m) {
d8d3d8a7 3357 const char *u = NULL, *uu = NULL, *s = NULL;
77930f11 3358 char **cmdline = NULL;
9a17484d
LP
3359 unsigned level = 1;
3360 int r;
120f919e
LP
3361 uid_t owner, audit_loginuid;
3362 uint32_t audit_sessionid;
9a17484d
LP
3363
3364 assert(m);
3365
3366 printf("Message %p\n"
3367 "\tn_ref=%u\n"
3368 "\tendian=%c\n"
3369 "\ttype=%i\n"
3370 "\tflags=%u\n"
3371 "\tversion=%u\n"
3372 "\tserial=%u\n"
3373 "\tfields_size=%u\n"
3374 "\tbody_size=%u\n"
3375 "\tpath=%s\n"
3376 "\tinterface=%s\n"
3377 "\tmember=%s\n"
3378 "\tdestination=%s\n"
3379 "\tsender=%s\n"
3380 "\tsignature=%s\n"
3381 "\treply_serial=%u\n"
3382 "\terror.name=%s\n"
3383 "\terror.message=%s\n"
3384 "\tsealed=%s\n",
3385 m,
3386 m->n_ref,
3387 m->header->endian,
3388 m->header->type,
3389 m->header->flags,
3390 m->header->version,
3391 BUS_MESSAGE_SERIAL(m),
3392 BUS_MESSAGE_FIELDS_SIZE(m),
3393 BUS_MESSAGE_BODY_SIZE(m),
3394 strna(m->path),
3395 strna(m->interface),
3396 strna(m->member),
3397 strna(m->destination),
3398 strna(m->sender),
80a46c73 3399 strna(m->root_container.signature),
9a17484d
LP
3400 m->reply_serial,
3401 strna(m->error.name),
3402 strna(m->error.message),
3403 yes_no(m->sealed));
3404
f9be01f3
LP
3405 if (m->pid != 0)
3406 printf("\tpid=%lu\n", (unsigned long) m->pid);
3407 if (m->tid != 0)
3408 printf("\ttid=%lu\n", (unsigned long) m->tid);
3409 if (m->uid_valid)
3410 printf("\tuid=%lu\n", (unsigned long) m->uid);
3411 if (m->gid_valid)
3412 printf("\tgid=%lu\n", (unsigned long) m->gid);
8323bc1f
LP
3413 if (m->pid_starttime != 0)
3414 printf("\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
69aec65c
LP
3415 if (m->monotonic != 0)
3416 printf("\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
3417 if (m->realtime != 0)
3418 printf("\trealtime=%llu\n", (unsigned long long) m->realtime);
3419 if (m->exe)
3420 printf("\texe=[%s]\n", m->exe);
3421 if (m->comm)
3422 printf("\tcomm=[%s]\n", m->comm);
3423 if (m->tid_comm)
3424 printf("\ttid_comm=[%s]\n", m->tid_comm);
3425 if (m->label)
3426 printf("\tlabel=[%s]\n", m->label);
4a875b61
LP
3427 if (m->cgroup)
3428 printf("\tcgroup=[%s]\n", m->cgroup);
f9be01f3 3429
d8d3d8a7
LP
3430 sd_bus_message_get_unit(m, &u);
3431 if (u)
3432 printf("\tunit=[%s]\n", u);
3433 sd_bus_message_get_user_unit(m, &uu);
3434 if (uu)
3435 printf("\tuser_unit=[%s]\n", uu);
3436 sd_bus_message_get_session(m, &s);
3437 if (s)
3438 printf("\tsession=[%s]\n", s);
bc7f3beb
LP
3439 if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
3440 printf("\towner_uid=%lu\n", (unsigned long) owner);
120f919e
LP
3441 if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
3442 printf("\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
3443 if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
3444 printf("\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
d8d3d8a7 3445
102ea8e4
LP
3446 printf("\tCAP_KILL=%i\n", sd_bus_message_has_effective_cap(m, 5));
3447
77930f11
LP
3448 if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
3449 char **c;
3450
3451 fputs("\tcmdline=[", stdout);
3452 STRV_FOREACH(c, cmdline) {
3453 if (c != cmdline)
3454 putchar(' ');
3455
3456 fputs(*c, stdout);
3457 }
3458
3459 fputs("]\n", stdout);
3460 }
3461
9a17484d
LP
3462 r = sd_bus_message_rewind(m, true);
3463 if (r < 0) {
3464 log_error("Failed to rewind: %s", strerror(-r));
3465 return r;
3466 }
3467
80a46c73 3468 printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
9a17484d
LP
3469
3470 for(;;) {
3471 _cleanup_free_ char *prefix = NULL;
3472 const char *contents = NULL;
3473 char type;
3474 union {
3475 uint8_t u8;
3476 uint16_t u16;
3477 int16_t s16;
3478 uint32_t u32;
3479 int32_t s32;
3480 uint64_t u64;
3481 int64_t s64;
3482 double d64;
3483 const char *string;
3484 int i;
3485 } basic;
3486
3487 r = sd_bus_message_peek_type(m, &type, &contents);
3488 if (r < 0) {
3489 log_error("Failed to peek type: %s", strerror(-r));
3490 return r;
3491 }
3492 if (r == 0) {
3493 if (level <= 1)
3494 break;
3495
3496 r = sd_bus_message_exit_container(m);
3497 if (r < 0) {
3498 log_error("Failed to exit container: %s", strerror(-r));
3499 return r;
3500 }
3501
3502 level--;
3503
3504 prefix = strrep("\t", level);
3505 if (!prefix)
3506 return log_oom();
3507
3508 if (type == SD_BUS_TYPE_ARRAY)
3509 printf("%s} END_ARRAY \n", prefix);
3510 else if (type == SD_BUS_TYPE_VARIANT)
3511 printf("%s} END_VARIANT\n", prefix);
3512 else if (type == SD_BUS_TYPE_STRUCT)
3513 printf("%s} END_STRUCT\n", prefix);
3514 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3515 printf("%s} END_DICT_ENTRY\n", prefix);
3516
3517 continue;
3518 }
3519
3520 prefix = strrep("\t", level);
3521 if (!prefix)
3522 return log_oom();
3523
3524 if (bus_type_is_container(type) > 0) {
3525 r = sd_bus_message_enter_container(m, type, contents);
3526 if (r < 0) {
3527 log_error("Failed to enter container: %s", strerror(-r));
3528 return r;
3529 }
3530
3531 if (type == SD_BUS_TYPE_ARRAY)
3532 printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
3533 else if (type == SD_BUS_TYPE_VARIANT)
3534 printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
3535 else if (type == SD_BUS_TYPE_STRUCT)
3536 printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
3537 else if (type == SD_BUS_TYPE_DICT_ENTRY)
3538 printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
3539
3540 level ++;
3541
3542 continue;
3543 }
3544
3545 r = sd_bus_message_read_basic(m, type, &basic);
3546 if (r < 0) {
3547 log_error("Failed to get basic: %s", strerror(-r));
3548 return r;
3549 }
3550
3551 switch (type) {
3552
3553 case SD_BUS_TYPE_BYTE:
3554 printf("%sBYTE: %u\n", prefix, basic.u8);
3555 break;
3556
3557 case SD_BUS_TYPE_BOOLEAN:
3558 printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
3559 break;
3560
3561 case SD_BUS_TYPE_INT16:
3562 printf("%sINT16: %i\n", prefix, basic.s16);
3563 break;
3564
3565 case SD_BUS_TYPE_UINT16:
3566 printf("%sUINT16: %u\n", prefix, basic.u16);
3567 break;
3568
3569 case SD_BUS_TYPE_INT32:
3570 printf("%sINT32: %i\n", prefix, basic.s32);
3571 break;
3572
3573 case SD_BUS_TYPE_UINT32:
3574 printf("%sUINT32: %u\n", prefix, basic.u32);
3575 break;
3576
3577 case SD_BUS_TYPE_INT64:
3578 printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
3579 break;
3580
3581 case SD_BUS_TYPE_UINT64:
3582 printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
3583 break;
3584
3585 case SD_BUS_TYPE_DOUBLE:
3586 printf("%sDOUBLE: %g\n", prefix, basic.d64);
3587 break;
3588
3589 case SD_BUS_TYPE_STRING:
3590 printf("%sSTRING: \"%s\"\n", prefix, basic.string);
3591 break;
3592
3593 case SD_BUS_TYPE_OBJECT_PATH:
3594 printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
3595 break;
3596
3597 case SD_BUS_TYPE_SIGNATURE:
3598 printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
3599 break;
3600
3601 case SD_BUS_TYPE_UNIX_FD:
3602 printf("%sUNIX_FD: %i\n", prefix, basic.i);
3603 break;
3604
3605 default:
3606 assert_not_reached("Unknown basic type.");
3607 }
3608 }
3609
3610 printf("} END_MESSAGE\n");
3611 return 0;
de1c301e
LP
3612}
3613
3614int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
3615 size_t total;
de1c301e
LP
3616 void *p, *e;
3617
3618 assert(m);
3619 assert(buffer);
3620 assert(sz);
3621
6629161f 3622 total = BUS_MESSAGE_SIZE(m);
de1c301e
LP
3623
3624 p = malloc(total);
3625 if (!p)
3626 return -ENOMEM;
3627
2100fa10
LP
3628 e = mempcpy(p, m->header, sizeof(*m->header));
3629
3630 if (m->fields) {
3631 e = mempcpy(e, m->fields, m->header->fields_size);
3632
3633 if (m->header->fields_size % 8 != 0)
3634 e = mempset(e, 0, 8 - (m->header->fields_size % 8));
3635 }
3636
3637 if (m->body)
3638 e = mempcpy(e, m->body, m->header->body_size);
3639
3640 assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
de1c301e
LP
3641
3642 *buffer = p;
3643 *sz = total;
3644
3645 return 0;
3646}
89ffcd2a
LP
3647
3648int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
3649 int r;
3650
3651 assert(m);
3652 assert(l);
3653
3654 r = sd_bus_message_enter_container(m, 'a', "s");
3655 if (r < 0)
3656 return r;
3657
3658 for (;;) {
3659 const char *s;
3660
3661 r = sd_bus_message_read_basic(m, 's', &s);
3662 if (r < 0)
3663 return r;
3664 if (r == 0)
3665 break;
3666
3667 r = strv_extend(l, s);
3668 if (r < 0)
3669 return r;
3670 }
3671
3672 r = sd_bus_message_exit_container(m);
3673 if (r < 0)
3674 return r;
3675
3676 return 0;
3677}
392d5b37
LP
3678
3679const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
3680 int r;
42c5aaf3
LP
3681 const char *t = NULL;
3682 unsigned j;
392d5b37
LP
3683
3684 assert(m);
3685
3686 r = sd_bus_message_rewind(m, true);
3687 if (r < 0)
3688 return NULL;
3689
42c5aaf3
LP
3690 for (j = 0; j <= i; j++) {
3691 char type;
3692
392d5b37
LP
3693 r = sd_bus_message_peek_type(m, &type, NULL);
3694 if (r < 0)
3695 return NULL;
3696
3697 if (type != SD_BUS_TYPE_STRING &&
3698 type != SD_BUS_TYPE_OBJECT_PATH &&
3699 type != SD_BUS_TYPE_SIGNATURE)
3700 return NULL;
3701
3702 r = sd_bus_message_read_basic(m, type, &t);
3703 if (r < 0)
3704 return NULL;
392d5b37
LP
3705 }
3706
392d5b37
LP
3707 return t;
3708}
2100fa10 3709
6629161f
LP
3710int bus_header_size(struct bus_header *h, size_t *sum) {
3711 size_t fs, bs;
3712
3713 assert(h);
3714 assert(sum);
3715
3716 if (h->endian == SD_BUS_NATIVE_ENDIAN) {
3717 fs = h->fields_size;
3718 bs = h->body_size;
3719 } else if (h->endian == SD_BUS_REVERSE_ENDIAN) {
3720 fs = bswap_32(h->fields_size);
3721 bs = bswap_32(h->body_size);
3722 } else
3723 return -EBADMSG;
2100fa10 3724
6629161f
LP
3725 *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
3726 return 0;
2100fa10 3727}