chiark / gitweb /
bus: suppress reply messages to method calls with no_reply set
[elogind.git] / src / libsystemd-bus / bus-message.c
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>
23
24 #include "util.h"
25
26 #include "bus-message.h"
27 #include "sd-bus.h"
28 #include "bus-internal.h"
29 #include "bus-type.h"
30 #include "bus-signature.h"
31
32 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
33
34 static void message_free(sd_bus_message *m) {
35         unsigned i;
36
37         assert(m);
38
39         if (m->free_header)
40                 free(m->header);
41
42         if (m->free_fields)
43                 free(m->fields);
44
45         if (m->free_body)
46                 free(m->body);
47
48         for (i = 0; i < m->n_fds; i++)
49                 close_nointr_nofail(m->fds[i]);
50
51         for (i = 0; i < m->n_containers; i++)
52                 free(m->sub_containers[i].signature);
53
54         free(m->sub_containers);
55         free(m);
56 }
57
58 static void* buffer_extend(void **p, uint32_t *sz, size_t align, size_t extend) {
59         size_t start, n;
60         void *k;
61
62         assert(p);
63         assert(sz);
64         assert(align > 0);
65
66         start = ALIGN_TO((size_t) *sz, align);
67         n = start + extend;
68
69         if (n == *sz)
70                 return (uint8_t*) *p + start;
71
72         if (n > (size_t) ((uint32_t) -1))
73                 return NULL;
74
75         k = realloc(*p, n);
76         if (!k)
77                 return NULL;
78
79         /* Zero out padding */
80         if (start > *sz)
81                 memset((uint8_t*) k + *sz, 0, start - *sz);
82
83         *p = k;
84         *sz = n;
85
86         return (uint8_t*) k + start;
87 }
88
89 static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz) {
90         void *p, *o;
91
92         assert(m);
93
94         o = m->fields;
95         p = buffer_extend(&m->fields, &m->header->fields_size, align, sz);
96         if (!p)
97                 return NULL;
98
99         if (o != m->fields) {
100                 /* Adjust quick access pointers */
101
102                 if (m->path)
103                         m->path = (const char*) m->fields + (m->path - (const char*) o);
104                 if (m->interface)
105                         m->interface = (const char*) m->fields + (m->interface - (const char*) o);
106                 if (m->member)
107                         m->member = (const char*) m->fields + (m->member - (const char*) o);
108                 if (m->destination)
109                         m->destination = (const char*) m->fields + (m->destination - (const char*) o);
110                 if (m->sender)
111                         m->sender = (const char*) m->fields + (m->sender - (const char*) o);
112                 if (m->signature)
113                         m->signature = (const char*) m->fields + (m->signature - (const char*) o);
114                 if (m->error.name)
115                         m->error.name = (const char*) m->fields + (m->error.name - (const char*) o);
116         }
117
118         m->free_fields = true;
119
120         return p;
121 }
122
123 static int message_append_field_string(
124                 sd_bus_message *m,
125                 uint8_t h,
126                 char type,
127                 const char *s,
128                 const char **ret) {
129
130         size_t l;
131         uint8_t *p;
132
133         assert(m);
134
135         l = strlen(s);
136         if (l > (size_t) (uint32_t) -1)
137                 return -EINVAL;
138
139         /* field id byte + signature length + signature 's' + NUL + string length + string + NUL */
140         p = message_extend_fields(m, 8, 4 + 4 + l + 1);
141         if (!p)
142                 return -ENOMEM;
143
144         p[0] = h;
145         p[1] = 1;
146         p[2] = type;
147         p[3] = 0;
148
149         ((uint32_t*) p)[1] = l;
150         memcpy(p + 8, s, l + 1);
151
152         if (ret)
153                 *ret = (const char*) p + 8;
154
155         return 0;
156 }
157
158 static int message_append_field_signature(
159                 sd_bus_message *m,
160                 uint8_t h,
161                 const char *s,
162                 const char **ret) {
163
164         size_t l;
165         uint8_t *p;
166
167         assert(m);
168
169         l = strlen(s);
170         if (l > 255)
171                 return -EINVAL;
172
173         /* field id byte + signature length + signature 'g' + NUL + string length + string + NUL */
174         p = message_extend_fields(m, 8, 4 + 1 + l + 1);
175         if (!p)
176                 return -ENOMEM;
177
178         p[0] = h;
179         p[1] = 1;
180         p[2] = SD_BUS_TYPE_SIGNATURE;
181         p[3] = 0;
182         p[4] = l;
183         memcpy(p + 5, s, l + 1);
184
185         if (ret)
186                 *ret = (const char*) p + 5;
187
188         return 0;
189 }
190
191 static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) {
192         uint8_t *p;
193
194         assert(m);
195
196         /* field id byte + signature length + signature 'u' + NUL + value */
197         p = message_extend_fields(m, 8, 4 + 4);
198         if (!p)
199                 return -ENOMEM;
200
201         p[0] = h;
202         p[1] = 1;
203         p[2] = SD_BUS_TYPE_UINT32;
204         p[3] = 0;
205
206         ((uint32_t*) p)[1] = x;
207
208         return 0;
209 }
210
211 static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
212         sd_bus_message *m;
213
214         m = malloc0(ALIGN(sizeof(struct sd_bus_message)) + sizeof(struct bus_header));
215         if (!m)
216                 return NULL;
217
218         m->n_ref = 1;
219         m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
220
221 #if __BYTE_ORDER == __BIG_ENDIAN
222         m->header->endian = SD_BUS_BIG_ENDIAN;
223 #else
224         m->header->endian = SD_BUS_LITTLE_ENDIAN;
225 #endif
226         m->header->type = type;
227         m->header->version = bus ? bus->message_version : 1;
228
229         return m;
230 }
231
232 int sd_bus_message_new_signal(
233                 sd_bus *bus,
234                 const char *path,
235                 const char *interface,
236                 const char *member,
237                 sd_bus_message **m) {
238
239         sd_bus_message *t;
240         int r;
241
242         if (!path)
243                 return -EINVAL;
244         if (!interface)
245                 return -EINVAL;
246         if (!member)
247                 return -EINVAL;
248         if (!m)
249                 return -EINVAL;
250
251         t = message_new(bus, SD_BUS_MESSAGE_TYPE_SIGNAL);
252         if (!t)
253                 return -ENOMEM;
254
255         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
256         if (r < 0)
257                 goto fail;
258         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
259         if (r < 0)
260                 goto fail;
261         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
262         if (r < 0)
263                 goto fail;
264
265         *m = t;
266         return 0;
267
268 fail:
269         sd_bus_message_unref(t);
270         return r;
271 }
272
273 int sd_bus_message_new_method_call(
274                 sd_bus *bus,
275                 const char *destination,
276                 const char *path,
277                 const char *interface,
278                 const char *member,
279                 sd_bus_message **m) {
280
281         sd_bus_message *t;
282         int r;
283
284         if (!path)
285                 return -EINVAL;
286         if (!member)
287                 return -EINVAL;
288         if (!m)
289                 return -EINVAL;
290
291         t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_CALL);
292         if (!t)
293                 return -ENOMEM;
294
295         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
296         if (r < 0)
297                 goto fail;
298         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
299         if (r < 0)
300                 goto fail;
301
302         if (interface) {
303                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
304                 if (r < 0)
305                         goto fail;
306         }
307
308         if (destination) {
309                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
310                 if (r < 0)
311                         goto fail;
312         }
313
314         *m = t;
315         return 0;
316
317 fail:
318         message_free(t);
319         return r;
320 }
321
322 static int message_new_reply(
323                 sd_bus *bus,
324                 sd_bus_message *call,
325                 uint8_t type,
326                 sd_bus_message **m) {
327
328         sd_bus_message *t;
329         int r;
330
331         if (!call)
332                 return -EINVAL;
333         if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
334                 return -EINVAL;
335         if (!m)
336                 return -EINVAL;
337
338         t = message_new(bus, type);
339         if (!t)
340                 return -ENOMEM;
341
342         t->reply_serial = BUS_MESSAGE_SERIAL(call);
343
344         r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
345         if (r < 0)
346                 goto fail;
347
348         if (call->sender) {
349                 r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->sender);
350                 if (r < 0)
351                         goto fail;
352         }
353
354         t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
355
356         *m = t;
357
358 fail:
359         message_free(t);
360         return r;
361 }
362
363 int sd_bus_message_new_method_return(
364                 sd_bus *bus,
365                 sd_bus_message *call,
366                 sd_bus_message **m) {
367
368         return message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_RETURN, m);
369 }
370
371 int sd_bus_message_new_method_error(
372                 sd_bus *bus,
373                 sd_bus_message *call,
374                 const sd_bus_error *e,
375                 sd_bus_message **m) {
376
377         sd_bus_message *t;
378         int r;
379
380         if (!e)
381                 return -EINVAL;
382         if (!e->name)
383                 return -EINVAL;
384         if (!m)
385                 return -EINVAL;
386
387         r = message_new_reply(bus, call, SD_BUS_MESSAGE_TYPE_METHOD_ERROR, &t);
388         if (r < 0)
389                 return r;
390
391         r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
392         if (r < 0)
393                 goto fail;
394
395         if (e->message) {
396                 r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
397                 if (r < 0)
398                         goto fail;
399         }
400
401         *m = t;
402         return 0;
403
404 fail:
405         message_free(t);
406         return r;
407 }
408
409 sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
410         if (!m)
411                 return NULL;
412
413         assert(m->n_ref > 0);
414         m->n_ref++;
415
416         return m;
417 }
418
419 sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
420         if (!m)
421                 return NULL;
422
423         assert(m->n_ref > 0);
424         m->n_ref--;
425
426         if (m->n_ref <= 0)
427                 message_free(m);
428
429         return NULL;
430 }
431
432 int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
433         if (!m)
434                 return -EINVAL;
435         if (!type)
436                 return -EINVAL;
437
438         *type = m->header->type;
439         return 0;
440 }
441
442 int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) {
443         if (!m)
444                 return -EINVAL;
445         if (!serial)
446                 return -EINVAL;
447         if (m->header->serial == 0)
448                 return -ENOENT;
449
450         *serial = BUS_MESSAGE_SERIAL(m);
451         return 0;
452 }
453
454 int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) {
455         if (!m)
456                 return -EINVAL;
457         if (!serial)
458                 return -EINVAL;
459         if (m->reply_serial == 0)
460                 return -ENOENT;
461
462         *serial = m->reply_serial;
463         return 0;
464 }
465
466 int sd_bus_message_get_no_reply(sd_bus_message *m) {
467         if (!m)
468                 return -EINVAL;
469
470         return m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL ? !!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) : 0;
471 }
472
473 const char *sd_bus_message_get_path(sd_bus_message *m) {
474         if (!m)
475                 return NULL;
476
477         return m->path;
478 }
479
480 const char *sd_bus_message_get_interface(sd_bus_message *m) {
481         if (!m)
482                 return NULL;
483
484         return m->interface;
485 }
486
487 const char *sd_bus_message_get_member(sd_bus_message *m) {
488         if (!m)
489                 return NULL;
490
491         return m->member;
492 }
493 const char *sd_bus_message_get_destination(sd_bus_message *m) {
494         if (!m)
495                 return NULL;
496
497         return m->destination;
498 }
499
500 const char *sd_bus_message_get_sender(sd_bus_message *m) {
501         if (!m)
502                 return NULL;
503
504         return m->sender;
505 }
506
507 const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
508         if (!m)
509                 return NULL;
510
511         if (!sd_bus_error_is_set(&m->error))
512                 return NULL;
513
514         return &m->error;
515 }
516
517 int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) {
518         if (!m)
519                 return -EINVAL;
520         if (!m->uid_valid)
521                 return -ENOENT;
522
523         *uid = m->uid;
524         return 0;
525 }
526
527 int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) {
528         if (!m)
529                 return -EINVAL;
530         if (!m->gid_valid)
531                 return -ENOENT;
532
533         *gid = m->gid;
534         return 0;
535 }
536
537 int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) {
538         if (!m)
539                 return -EINVAL;
540         if (m->pid <= 0)
541                 return -ENOENT;
542
543         *pid = m->pid;
544         return 0;
545 }
546
547 int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) {
548         if (!m)
549                 return -EINVAL;
550         if (m->tid <= 0)
551                 return -ENOENT;
552
553         *tid = m->tid;
554         return 0;
555 }
556
557 int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) {
558         if (!m)
559                 return -EINVAL;
560
561         if (m->header->type != SD_BUS_MESSAGE_TYPE_SIGNAL)
562                 return 0;
563
564         if (interface && (!m->interface || !streq(m->interface, interface)))
565                 return 0;
566
567         if (member &&  (!m->member || !streq(m->member, member)))
568                 return 0;
569
570         return 1;
571 }
572
573 int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member) {
574         if (!m)
575                 return -EINVAL;
576
577         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
578                 return 0;
579
580         if (interface && (!m->interface || !streq(m->interface, interface)))
581                 return 0;
582
583         if (member &&  (!m->member || !streq(m->member, member)))
584                 return 0;
585
586         return 1;
587 }
588
589 int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
590         if (!m)
591                 return -EINVAL;
592
593         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
594                 return 0;
595
596         if (name && (!m->error.name || !streq(m->error.name, name)))
597                 return 0;
598
599         return 1;
600 }
601
602 int sd_bus_message_set_no_reply(sd_bus_message *m, int b) {
603         if (!m)
604                 return -EINVAL;
605         if (m->sealed)
606                 return -EPERM;
607         if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
608                 return -EPERM;
609
610         if (b)
611                 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
612         else
613                 m->header->flags &= ~SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
614
615         return 0;
616 }
617
618 static struct bus_container *message_get_container(sd_bus_message *m) {
619         assert(m);
620
621         if (m->n_containers == 0)
622                 return &m->root_container;
623
624         assert(m->sub_containers);
625         return m->sub_containers + m->n_containers - 1;
626 }
627
628 static void *message_extend_body(sd_bus_message *m, size_t align, size_t sz) {
629         void *p, *o;
630         size_t added;
631         struct bus_container *c;
632
633         assert(m);
634
635         o = m->body;
636         added = m->header->body_size;
637
638         p = buffer_extend(&m->body, &m->header->body_size, align, sz);
639         if (!p)
640                 return NULL;
641
642         added = m->header->body_size - added;
643
644         for (c = m->sub_containers; c < m->sub_containers + m->n_containers; c++)
645                 if (c->array_size) {
646                         c->array_size = (uint32_t*) ((uint8_t*) m->body + ((uint8_t*) c->array_size - (uint8_t*) o));
647                         *c->array_size += added;
648                 }
649
650         if (o != m->body) {
651                 if (m->error.message)
652                         m->error.message = (const char*) m->body + (m->error.message - (const char*) o);
653         }
654
655         m->free_body = true;
656
657         return p;
658 }
659
660 int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
661         struct bus_container *c;
662         size_t sz, align, nindex;
663         uint32_t k;
664         void *a;
665         char *e = NULL;
666
667         if (!m)
668                 return -EINVAL;
669         if (m->sealed)
670                 return -EPERM;
671         if (!bus_type_is_basic(type))
672                 return -EINVAL;
673
674         c = message_get_container(m);
675
676         if (c->signature && c->signature[c->index]) {
677                 /* Container signature is already set */
678
679                 if (c->signature[c->index] != type)
680                         return -EINVAL;
681         } else {
682                 /* Maybe we can append to the signature? But only if this is the top-level container*/
683                 if (c->enclosing != 0)
684                         return -EINVAL;
685
686                 e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
687                 if (!e)
688                         return -ENOMEM;
689         }
690
691         nindex = c->index + 1;
692
693         switch (type) {
694
695         case SD_BUS_TYPE_STRING:
696         case SD_BUS_TYPE_OBJECT_PATH:
697                 align = 4;
698                 sz = 4 + strlen(p) + 1;
699                 break;
700
701         case SD_BUS_TYPE_SIGNATURE:
702                 align = 1;
703                 sz = 1 + strlen(p) + 1;
704                 break;
705
706         case SD_BUS_TYPE_BOOLEAN:
707                 align = sz = 4;
708
709                 assert_cc(sizeof(int) == sizeof(uint32_t));
710                 memcpy(&k, p, 4);
711                 k = !!k;
712                 p = &k;
713                 break;
714
715         default:
716                 align = bus_type_get_alignment(type);
717                 sz = bus_type_get_size(type);
718                 break;
719         }
720
721         assert(align > 0);
722         assert(sz > 0);
723
724         a = message_extend_body(m, align, sz);
725         if (!a) {
726                 /* Truncate extended signature again */
727                 if (e)
728                         c->signature[c->index] = 0;
729
730                 return -ENOMEM;
731         }
732
733         if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
734                 *(uint32_t*) a = sz - 5;
735                 memcpy((uint8_t*) a + 4, p, sz - 4);
736
737                 if (stored)
738                         *stored = (const uint8_t*) a + 4;
739
740         } else if (type == SD_BUS_TYPE_SIGNATURE) {
741                 *(uint8_t*) a = sz - 1;
742                 memcpy((uint8_t*) a + 1, p, sz - 1);
743
744                 if (stored)
745                         *stored = (const uint8_t*) a + 1;
746
747         } else {
748                 memcpy(a, p, sz);
749
750                 if (stored)
751                         *stored = a;
752         }
753
754         if (c->enclosing != SD_BUS_TYPE_ARRAY)
755                 c->index = nindex;
756
757         return 0;
758 }
759
760 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
761         return message_append_basic(m, type, p, NULL);
762 }
763
764 static int bus_message_open_array(
765                 sd_bus_message *m,
766                 struct bus_container *c,
767                 const char *contents,
768                 uint32_t **array_size) {
769
770         char *e = NULL;
771         size_t nindex;
772         void *a, *b;
773         int alignment;
774         size_t saved;
775
776         assert(m);
777         assert(c);
778         assert(contents);
779         assert(array_size);
780
781         if (!signature_is_single(contents))
782                 return -EINVAL;
783
784         alignment = bus_type_get_alignment(contents[0]);
785         if (alignment < 0)
786                 return alignment;
787
788         if (c->signature && c->signature[c->index]) {
789
790                 /* Verify the existing signature */
791
792                 if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
793                         return -EINVAL;
794
795                 if (!startswith(c->signature + c->index + 1, contents))
796                         return -EINVAL;
797
798                 nindex = c->index + 1 + strlen(contents);
799         } else {
800                 if (c->enclosing != 0)
801                         return -EINVAL;
802
803                 /* Extend the existing signature */
804
805                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
806                 if (!e)
807                         return -ENOMEM;
808
809                 nindex = e - c->signature;
810         }
811
812         saved = m->header->body_size;
813         a = message_extend_body(m, 4, 4);
814         if (!a) {
815                 /* Truncate extended signature again */
816                 if (e)
817                         c->signature[c->index] = 0;
818
819                 return -ENOMEM;
820         }
821         b = m->body;
822
823         if (!message_extend_body(m, alignment, 0)) {
824                 /* Add alignment between size and first element */
825                 if (e)
826                         c->signature[c->index] = 0;
827
828                 m->header->body_size = saved;
829                 return -ENOMEM;
830         }
831
832         if (c->enclosing != SD_BUS_TYPE_ARRAY)
833                 c->index = nindex;
834
835         /* m->body might have changed so let's readjust a */
836         a = (uint8_t*) m->body + ((uint8_t*) a - (uint8_t*) b);
837         *(uint32_t*) a = 0;
838
839         *array_size = a;
840         return 0;
841 }
842
843 static int bus_message_open_variant(
844                 sd_bus_message *m,
845                 struct bus_container *c,
846                 const char *contents) {
847
848         char *e = NULL;
849         size_t l, nindex;
850         void *a;
851
852         assert(m);
853         assert(c);
854         assert(contents);
855
856         if (!signature_is_single(contents))
857                 return -EINVAL;
858
859         if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
860                 return -EINVAL;
861
862         if (c->signature && c->signature[c->index]) {
863
864                 if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
865                         return -EINVAL;
866
867         } else {
868                 if (c->enclosing != 0)
869                         return -EINVAL;
870
871                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
872                 if (!e)
873                         return -ENOMEM;
874         }
875
876         nindex = c->index + 1;
877
878         l = strlen(contents);
879         a = message_extend_body(m, 1, 1 + l + 1);
880         if (!a) {
881                 /* Truncate extended signature again */
882                 if (e)
883                         c->signature[c->index] = 0;
884
885                 return -ENOMEM;
886         }
887
888         *(uint8_t*) a = l;
889         memcpy((uint8_t*) a + 1, contents, l + 1);
890
891         if (c->enclosing != SD_BUS_TYPE_ARRAY)
892                 c->index = nindex;
893
894         return 0;
895 }
896
897 static int bus_message_open_struct(
898                 sd_bus_message *m,
899                 struct bus_container *c,
900                 const char *contents) {
901
902         size_t nindex;
903         char *e = NULL;
904
905         assert(m);
906         assert(c);
907         assert(contents);
908
909         if (!signature_is_valid(contents, false))
910                 return -EINVAL;
911
912         if (c->signature && c->signature[c->index]) {
913                 size_t l;
914
915                 l = strlen(contents);
916
917                 if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
918                     !startswith(c->signature + c->index + 1, contents) ||
919                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
920                         return -EINVAL;
921
922                 nindex = c->index + 1 + l + 1;
923         } else {
924                 if (c->enclosing != 0)
925                         return -EINVAL;
926
927                 e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
928                 if (!e)
929                         return -ENOMEM;
930
931                 nindex = e - c->signature;
932         }
933
934         /* Align contents to 8 byte boundary */
935         if (!message_extend_body(m, 8, 0)) {
936                 if (e)
937                         c->signature[c->index] = 0;
938
939                 return -ENOMEM;
940         }
941
942         if (c->enclosing != SD_BUS_TYPE_ARRAY)
943                 c->index = nindex;
944
945         return 0;
946 }
947
948 static int bus_message_open_dict_entry(
949                 sd_bus_message *m,
950                 struct bus_container *c,
951                 const char *contents) {
952
953         size_t nindex;
954
955         assert(m);
956         assert(c);
957         assert(contents);
958
959         if (!signature_is_pair(contents))
960                 return -EINVAL;
961
962         if (c->enclosing != SD_BUS_TYPE_ARRAY)
963                 return -EINVAL;
964
965         if (c->signature && c->signature[c->index]) {
966                 size_t l;
967
968                 l = strlen(contents);
969
970                 if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
971                     !startswith(c->signature + c->index + 1, contents) ||
972                     c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
973                         return -EINVAL;
974
975                 nindex = c->index + 1 + l + 1;
976         } else
977                 return -EINVAL;
978
979         /* Align contents to 8 byte boundary */
980         if (!message_extend_body(m, 8, 0))
981                 return -ENOMEM;
982
983         if (c->enclosing != SD_BUS_TYPE_ARRAY)
984                 c->index = nindex;
985
986         return 0;
987 }
988
989 int sd_bus_message_open_container(
990                 sd_bus_message *m,
991                 char type,
992                 const char *contents) {
993
994         struct bus_container *c, *sub;
995         char *signature;
996         uint32_t *array_size = NULL;
997         int r;
998
999         if (!m)
1000                 return -EINVAL;
1001         if (m->sealed)
1002                 return -EPERM;
1003         if (!contents)
1004                 return -EINVAL;
1005
1006         /* Make sure we have space for one more container */
1007         sub = realloc(m->sub_containers, sizeof(struct bus_container) * (m->n_containers + 1));
1008         if (!sub)
1009                 return -ENOMEM;
1010
1011         m->sub_containers = sub;
1012
1013         c = message_get_container(m);
1014
1015         signature = strdup(contents);
1016         if (!signature)
1017                 return -ENOMEM;
1018
1019         if (type == SD_BUS_TYPE_ARRAY)
1020                 r = bus_message_open_array(m, c, contents, &array_size);
1021         else if (type == SD_BUS_TYPE_VARIANT)
1022                 r = bus_message_open_variant(m, c, contents);
1023         else if (type == SD_BUS_TYPE_STRUCT)
1024                 r = bus_message_open_struct(m, c, contents);
1025         else if (type == SD_BUS_TYPE_DICT_ENTRY)
1026                 r = bus_message_open_dict_entry(m, c, contents);
1027         else
1028                 r = -EINVAL;
1029
1030         if (r < 0) {
1031                 free(signature);
1032                 return r;
1033         }
1034
1035         /* OK, let's fill it in */
1036         sub += m->n_containers++;
1037
1038         sub->enclosing = type;
1039         sub->signature = signature;
1040         sub->index = 0;
1041         sub->array_size = array_size;
1042
1043         return 0;
1044 }
1045
1046 int sd_bus_message_close_container(sd_bus_message *m) {
1047         struct bus_container *c;
1048
1049         if (!m)
1050                 return -EINVAL;
1051         if (m->sealed)
1052                 return -EPERM;
1053         if (m->n_containers <= 0)
1054                 return -EINVAL;
1055
1056         c = message_get_container(m);
1057
1058         if (!c->signature)
1059                 return -EINVAL;
1060
1061         if (c->enclosing != SD_BUS_TYPE_ARRAY)
1062                 if (c->signature[c->index] != 0)
1063                         return -EINVAL;
1064
1065         free(c->signature);
1066         m->n_containers--;
1067
1068         return 0;
1069 }
1070
1071 static int message_append_ap(
1072                 sd_bus_message *m,
1073                 const char *types,
1074                 va_list ap) {
1075
1076         const char *t;
1077         int r;
1078
1079         assert(m);
1080         assert(types);
1081
1082         for (t = types; *t; t++) {
1083                 switch (*t) {
1084
1085                 case SD_BUS_TYPE_BYTE: {
1086                         uint8_t x;
1087
1088                         x = (uint8_t) va_arg(ap, int);
1089                         r = sd_bus_message_append_basic(m, *t, &x);
1090                         break;
1091                 }
1092
1093                 case SD_BUS_TYPE_BOOLEAN:
1094                 case SD_BUS_TYPE_INT32:
1095                 case SD_BUS_TYPE_UINT32: {
1096                         uint32_t x;
1097
1098                         x = va_arg(ap, uint32_t);
1099                         r = sd_bus_message_append_basic(m, *t, &x);
1100                         break;
1101                 }
1102
1103                 case SD_BUS_TYPE_INT16:
1104                 case SD_BUS_TYPE_UINT16: {
1105                         uint16_t x;
1106
1107                         x = (uint16_t) va_arg(ap, int);
1108                         r = sd_bus_message_append_basic(m, *t, &x);
1109                         break;
1110                 }
1111
1112                 case SD_BUS_TYPE_INT64:
1113                 case SD_BUS_TYPE_UINT64:
1114                 case SD_BUS_TYPE_DOUBLE: {
1115                         uint64_t x;
1116
1117                         x = va_arg(ap, uint64_t);
1118                         r = sd_bus_message_append_basic(m, *t, &x);
1119                         break;
1120                 }
1121
1122                 case SD_BUS_TYPE_STRING:
1123                 case SD_BUS_TYPE_OBJECT_PATH:
1124                 case SD_BUS_TYPE_SIGNATURE: {
1125                         const char *x;
1126
1127                         x = va_arg(ap, const char*);
1128                         r = sd_bus_message_append_basic(m, *t, x);
1129                         break;
1130                 }
1131
1132                 case SD_BUS_TYPE_UNIX_FD: {
1133                         int x;
1134
1135                         x = va_arg(ap, int);
1136                         r = sd_bus_message_append_basic(m, *t, &x);
1137                         break;
1138                 }
1139
1140                 case SD_BUS_TYPE_ARRAY: {
1141                         unsigned i, n;
1142                         size_t k;
1143
1144                         r = signature_element_length(t + 1, &k);
1145                         if (r < 0)
1146                                 return r;
1147
1148                         {
1149                                 char s[k + 1];
1150
1151                                 memcpy(s, t + 1, k);
1152                                 s[k] = 0;
1153                                 t += k;
1154
1155                                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
1156                                 if (r < 0)
1157                                         return r;
1158
1159                                 n = va_arg(ap, unsigned);
1160
1161                                 for (i = 0; i < n; i++) {
1162                                         r = message_append_ap(m, s, ap);
1163                                         if (r < 0)
1164                                                 return r;
1165                                 }
1166
1167                                 r = sd_bus_message_close_container(m);
1168                         }
1169
1170                         break;
1171                 }
1172
1173                 case SD_BUS_TYPE_VARIANT: {
1174                         const char *s;
1175
1176                         s = va_arg(ap, const char*);
1177                         if (!s)
1178                                 return -EINVAL;
1179
1180                         r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
1181                         if (r < 0)
1182                                 return r;
1183
1184                         r = message_append_ap(m, s, ap);
1185                         if (r < 0)
1186                                 return r;
1187
1188                         r = sd_bus_message_close_container(m);
1189                         break;
1190                 }
1191
1192                 case SD_BUS_TYPE_STRUCT_BEGIN:
1193                 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
1194                         size_t k;
1195
1196                         r = signature_element_length(t, &k);
1197                         if (r < 0)
1198                                 return r;
1199
1200                         {
1201                                 char s[k - 1];
1202
1203                                 memcpy(s, t + 1, k - 2);
1204                                 s[k - 2] = 0;
1205
1206                                 r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
1207                                 if (r < 0)
1208                                         return r;
1209
1210                                 t += k - 1;
1211
1212                                 r = message_append_ap(m, s, ap);
1213                                 if (r < 0)
1214                                         return r;
1215
1216                                 r = sd_bus_message_close_container(m);
1217                         }
1218
1219                         break;
1220                 }
1221
1222                 default:
1223                         r = -EINVAL;
1224                 }
1225
1226                 if (r < 0)
1227                         return r;
1228         }
1229
1230         return 0;
1231 }
1232
1233 int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
1234         va_list ap;
1235         int r;
1236
1237         if (!m)
1238                 return -EINVAL;
1239         if (m->sealed)
1240                 return -EPERM;
1241         if (!types)
1242                 return -EINVAL;
1243
1244         va_start(ap, types);
1245         r = message_append_ap(m, types, ap);
1246         va_end(ap);
1247
1248         return r;
1249 }
1250
1251 int sd_bus_message_read_type(sd_bus_message *m, char *type, char *element, size_t *length) {
1252         return -ENOTSUP;
1253 }
1254
1255 int sd_bus_message_read_basic(sd_bus_message *m, char type, char element, const void **p, size_t *length) {
1256         return -ENOTSUP;
1257 }
1258
1259 int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
1260         return -ENOTSUP;
1261 }
1262
1263 int message_parse(sd_bus_message *m) {
1264         assert(m);
1265
1266         if (m->header->version != 1)
1267                 return -EIO;
1268
1269         if (m->header->endian != SD_BUS_BIG_ENDIAN &&
1270             m->header->endian != SD_BUS_LITTLE_ENDIAN)
1271                 return -EIO;
1272
1273         return 0;
1274 }
1275
1276 static void setup_iovec(sd_bus_message *m) {
1277         assert(m);
1278         assert(m->sealed);
1279
1280         m->n_iovec = 0;
1281
1282         m->iovec[m->n_iovec].iov_base = m->header;
1283         m->iovec[m->n_iovec].iov_len = sizeof(*m->header);
1284         m->n_iovec++;
1285
1286         if (m->fields) {
1287                 m->iovec[m->n_iovec].iov_base = m->fields;
1288                 m->iovec[m->n_iovec].iov_len = m->header->fields_size;
1289                 m->n_iovec++;
1290
1291                 if (m->header->fields_size % 8 != 0) {
1292                         static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
1293
1294                         m->iovec[m->n_iovec].iov_base = (void*) padding;
1295                         m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8;
1296                         m->n_iovec++;
1297                 }
1298         }
1299
1300         if (m->body) {
1301                 m->iovec[m->n_iovec].iov_base = m->body;
1302                 m->iovec[m->n_iovec].iov_len = m->header->body_size;
1303                 m->n_iovec++;
1304         }
1305 }
1306
1307 int message_seal(sd_bus_message *m, uint64_t serial) {
1308         int r;
1309
1310         assert(m);
1311
1312         if (m->sealed)
1313                 return -EPERM;
1314
1315         if (m->n_containers > 0)
1316                 return -EBADMSG;
1317
1318         /* If there's a non-trivial signature set, then add it in here */
1319         if (!isempty(m->root_container.signature)) {
1320                 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, &m->signature);
1321                 if (r < 0)
1322                         return r;
1323         }
1324
1325         if (m->n_fds > 0) {
1326                 r = message_append_field_uint32(m, SD_BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
1327                 if (r < 0)
1328                         return r;
1329         }
1330
1331         m->header->serial = serial;
1332         m->sealed = true;
1333
1334         setup_iovec(m);
1335
1336         return 0;
1337 }
1338
1339 int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
1340         if (!m)
1341                 return -EINVAL;
1342         if (!destination)
1343                 return -EINVAL;
1344         if (m->sealed)
1345                 return -EPERM;
1346         if (m->destination)
1347                 return -EEXIST;
1348
1349         return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
1350 }
1351
1352 void message_dump(sd_bus_message *m) {
1353
1354         log_info("Message %p\n"
1355                  "\tn_ref=%u\n"
1356                  "\tendian=%c\n"
1357                  "\ttype=%i\n"
1358                  "\tflags=%u\n"
1359                  "\tversion=%u\n"
1360                  "\tserial=%u\n"
1361                  "\tfields_size=%u\n"
1362                  "\tbody_size=%u\n"
1363                  "\tpath=%s\n"
1364                  "\tinterface=%s\n"
1365                  "\tmember=%s\n"
1366                  "\tdestination=%s\n"
1367                  "\tsender=%s\n"
1368                  "\tsignature=%s\n"
1369                  "\treply_serial=%u\n"
1370                  "\terror.name=%s\n"
1371                  "\terror.message=%s\n"
1372                  "\tsealed=%s\n",
1373                  m,
1374                  m->n_ref,
1375                  m->header->endian,
1376                  m->header->type,
1377                  m->header->flags,
1378                  m->header->version,
1379                  BUS_MESSAGE_SERIAL(m),
1380                  BUS_MESSAGE_FIELDS_SIZE(m),
1381                  BUS_MESSAGE_BODY_SIZE(m),
1382                  strna(m->path),
1383                  strna(m->interface),
1384                  strna(m->member),
1385                  strna(m->destination),
1386                  strna(m->sender),
1387                  strna(m->signature),
1388                  m->reply_serial,
1389                  strna(m->error.name),
1390                  strna(m->error.message),
1391                  yes_no(m->sealed));
1392 }
1393
1394 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
1395         size_t total;
1396         unsigned i;
1397         void *p, *e;
1398
1399         assert(m);
1400         assert(buffer);
1401         assert(sz);
1402
1403         for (i = 0, total = 0; i < m->n_iovec; i++)
1404                 total += m->iovec[i].iov_len;
1405
1406         p = malloc(total);
1407         if (!p)
1408                 return -ENOMEM;
1409
1410         for (i = 0, e = p; i < m->n_iovec; i++)
1411                 e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len);
1412
1413         *buffer = p;
1414         *sz = total;
1415
1416         return 0;
1417 }