1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
23 #include "capability.h"
28 #include "bus-message.h"
29 #include "bus-internal.h"
33 static char *indent(unsigned level, unsigned flags) {
39 if (flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY && level > 0)
42 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER)
45 p = new(char, n + level*8 + 1);
49 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
54 memset(p + i, ' ', level*8);
60 int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
69 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
71 "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64,
72 m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
73 m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
74 m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
75 ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
81 /* Display synthetic message serial number in a more readable
82 * format than (uint32_t) -1 */
83 if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL)
84 fprintf(f, " Cookie=-1");
86 fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m));
88 if (m->reply_cookie != 0)
89 fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie);
94 fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
96 fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
98 fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
100 fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
102 fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
104 if (m->sender || m->destination || m->path || m->interface || m->member)
107 if (sd_bus_error_is_set(&m->error))
110 " ErrorMessage=%s\"%s\"%s\n",
111 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
112 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
114 if (m->monotonic != 0)
115 fprintf(f, " Monotonic="USEC_FMT, m->monotonic);
116 if (m->realtime != 0)
117 fprintf(f, " Realtime="USEC_FMT, m->realtime);
119 fprintf(f, " SequenceNumber=%"PRIu64, m->seqnum);
121 if (m->monotonic != 0 || m->realtime != 0 || m->seqnum != 0)
124 bus_creds_dump(&m->creds, f, true);
127 r = sd_bus_message_rewind(m, !(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY));
129 return log_error_errno(r, "Failed to rewind: %m");
131 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
132 _cleanup_free_ char *prefix = NULL;
134 prefix = indent(0, flags);
138 fprintf(f, "%sMESSAGE \"%s\" {\n", prefix, strempty(m->root_container.signature));
142 _cleanup_free_ char *prefix = NULL;
143 const char *contents = NULL;
158 r = sd_bus_message_peek_type(m, &type, &contents);
160 return log_error_errno(r, "Failed to peek type: %m");
166 r = sd_bus_message_exit_container(m);
168 return log_error_errno(r, "Failed to exit container: %m");
172 prefix = indent(level, flags);
176 fprintf(f, "%s};\n", prefix);
180 prefix = indent(level, flags);
184 if (bus_type_is_container(type) > 0) {
185 r = sd_bus_message_enter_container(m, type, contents);
187 return log_error_errno(r, "Failed to enter container: %m");
189 if (type == SD_BUS_TYPE_ARRAY)
190 fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
191 else if (type == SD_BUS_TYPE_VARIANT)
192 fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
193 else if (type == SD_BUS_TYPE_STRUCT)
194 fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
195 else if (type == SD_BUS_TYPE_DICT_ENTRY)
196 fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
203 r = sd_bus_message_read_basic(m, type, &basic);
205 return log_error_errno(r, "Failed to get basic: %m");
211 case SD_BUS_TYPE_BYTE:
212 fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
215 case SD_BUS_TYPE_BOOLEAN:
216 fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_highlight_off());
219 case SD_BUS_TYPE_INT16:
220 fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
223 case SD_BUS_TYPE_UINT16:
224 fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
227 case SD_BUS_TYPE_INT32:
228 fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
231 case SD_BUS_TYPE_UINT32:
232 fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
235 case SD_BUS_TYPE_INT64:
236 fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_highlight_off());
239 case SD_BUS_TYPE_UINT64:
240 fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_highlight_off());
243 case SD_BUS_TYPE_DOUBLE:
244 fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
247 case SD_BUS_TYPE_STRING:
248 fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
251 case SD_BUS_TYPE_OBJECT_PATH:
252 fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
255 case SD_BUS_TYPE_SIGNATURE:
256 fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
259 case SD_BUS_TYPE_UNIX_FD:
260 fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
264 assert_not_reached("Unknown basic type.");
268 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
269 _cleanup_free_ char *prefix = NULL;
271 prefix = indent(0, flags);
275 fprintf(f, "%s};\n\n", prefix);
281 static void dump_capabilities(
286 int (*has)(sd_bus_creds *c, int capability)) {
288 unsigned long i, last_cap;
302 fprintf(f, "%s%s=%s", terse ? " " : "", name, terse ? "" : ansi_highlight());
303 last_cap = cap_last_cap();
311 fprintf(f, terse ? "\n " : "\n ");
313 fprintf(f, "%s", strna(capability_to_name(i)));
328 fputs(ansi_highlight_off(), f);
331 int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
332 bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
333 const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
334 uid_t owner, audit_loginuid;
335 uint32_t audit_sessionid;
336 char **cmdline = NULL, **well_known = NULL;
337 const char *prefix, *color, *suffix;
353 color = ansi_highlight();
355 off = ansi_highlight_off();
356 suffix = strjoina(off, "\n");
359 if (c->mask & SD_BUS_CREDS_PID)
360 fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix);
361 if (c->mask & SD_BUS_CREDS_TID)
362 fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
364 if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID))))
367 if (c->mask & SD_BUS_CREDS_UID)
368 fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix);
369 if (c->mask & SD_BUS_CREDS_EUID)
370 fprintf(f, "%sEUID=%s"UID_FMT"%s", prefix, color, c->euid, suffix);
371 if (c->mask & SD_BUS_CREDS_SUID)
372 fprintf(f, "%sSUID=%s"UID_FMT"%s", prefix, color, c->suid, suffix);
373 if (c->mask & SD_BUS_CREDS_FSUID)
374 fprintf(f, "%sFSUID=%s"UID_FMT"%s", prefix, color, c->fsuid, suffix);
375 r = sd_bus_creds_get_owner_uid(c, &owner);
377 fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix);
378 if (c->mask & SD_BUS_CREDS_GID)
379 fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix);
380 if (c->mask & SD_BUS_CREDS_EGID)
381 fprintf(f, "%sEGID=%s"GID_FMT"%s", prefix, color, c->egid, suffix);
382 if (c->mask & SD_BUS_CREDS_SGID)
383 fprintf(f, "%sSGID=%s"GID_FMT"%s", prefix, color, c->sgid, suffix);
384 if (c->mask & SD_BUS_CREDS_FSGID)
385 fprintf(f, "%sFSGID=%s"GID_FMT"%s", prefix, color, c->fsgid, suffix);
387 if (c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
390 fprintf(f, "%sSupplementaryGIDs=%s", prefix, color);
391 for (i = 0; i < c->n_supplementary_gids; i++)
392 fprintf(f, "%s" GID_FMT, i > 0 ? " " : "", c->supplementary_gids[i]);
393 fprintf(f, "%s", suffix);
396 if (terse && ((c->mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
397 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
398 SD_BUS_CREDS_SUPPLEMENTARY_GIDS)) || r >= 0))
401 if (c->mask & SD_BUS_CREDS_COMM)
402 fprintf(f, "%sComm=%s%s%s", prefix, color, c->comm, suffix);
403 if (c->mask & SD_BUS_CREDS_TID_COMM)
404 fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix);
405 if (c->mask & SD_BUS_CREDS_EXE)
406 fprintf(f, "%sExe=%s%s%s", prefix, color, c->exe, suffix);
408 if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)))
411 if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
414 fprintf(f, "%sCommandLine=%s", prefix, color);
415 STRV_FOREACH(i, cmdline) {
422 fprintf(f, "%s", suffix);
425 if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
426 fprintf(f, "%sLabel=%s%s%s", prefix, color, c->label, suffix);
427 if (c->mask & SD_BUS_CREDS_DESCRIPTION)
428 fprintf(f, "%sDescription=%s%s%s", prefix, color, c->description, suffix);
430 if (terse && (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION)))
433 if (c->mask & SD_BUS_CREDS_CGROUP)
434 fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix);
435 (void) sd_bus_creds_get_unit(c, &u);
437 fprintf(f, "%sUnit=%s%s%s", prefix, color, u, suffix);
438 (void) sd_bus_creds_get_user_unit(c, &uu);
440 fprintf(f, "%sUserUnit=%s%s%s", prefix, color, uu, suffix);
441 (void) sd_bus_creds_get_slice(c, &sl);
443 fprintf(f, "%sSlice=%s%s%s", prefix, color, sl, suffix);
444 (void) sd_bus_creds_get_session(c, &s);
446 fprintf(f, "%sSession=%s%s%s", prefix, color, s, suffix);
448 if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s))
451 if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
452 audit_loginuid_is_set = true;
453 fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix);
455 if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
456 audit_sessionid_is_set = true;
457 fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix);
460 if (terse && (audit_loginuid_is_set || audit_sessionid_is_set))
463 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
464 fprintf(f, "%sUniqueName=%s%s%s", prefix, color, c->unique_name, suffix);
466 if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
469 fprintf(f, "%sWellKnownNames=%s", prefix, color);
470 STRV_FOREACH(i, well_known) {
477 fprintf(f, "%s", suffix);
480 if (terse && (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known))
483 dump_capabilities(c, f, "EffectiveCapabilities", terse, sd_bus_creds_has_effective_cap);
484 dump_capabilities(c, f, "PermittedCapabilities", terse, sd_bus_creds_has_permitted_cap);
485 dump_capabilities(c, f, "InheritableCapabilities", terse, sd_bus_creds_has_inheritable_cap);
486 dump_capabilities(c, f, "BoundingCapabilities", terse, sd_bus_creds_has_bounding_cap);
492 * For details about the file format, see:
494 * http://wiki.wireshark.org/Development/LibpcapFileFormat
497 typedef struct _packed_ pcap_hdr_s {
498 uint32_t magic_number; /* magic number */
499 uint16_t version_major; /* major version number */
500 uint16_t version_minor; /* minor version number */
501 int32_t thiszone; /* GMT to local correction */
502 uint32_t sigfigs; /* accuracy of timestamps */
503 uint32_t snaplen; /* max length of captured packets, in octets */
504 uint32_t network; /* data link type */
507 typedef struct _packed_ pcaprec_hdr_s {
508 uint32_t ts_sec; /* timestamp seconds */
509 uint32_t ts_usec; /* timestamp microseconds */
510 uint32_t incl_len; /* number of octets of packet saved in file */
511 uint32_t orig_len; /* actual length of packet */
514 int bus_pcap_header(size_t snaplen, FILE *f) {
517 .magic_number = 0xa1b2c3d4U,
520 .thiszone = 0, /* UTC */
522 .network = 231, /* D-Bus */
529 assert((size_t) (uint32_t) snaplen == snaplen);
531 hdr.snaplen = (uint32_t) snaplen;
533 fwrite(&hdr, 1, sizeof(hdr), f);
539 int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
540 struct bus_body_part *part;
541 pcaprec_hdr_t hdr = {};
551 assert((size_t) (uint32_t) snaplen == snaplen);
553 if (m->realtime != 0)
554 timeval_store(&tv, m->realtime);
556 assert_se(gettimeofday(&tv, NULL) >= 0);
558 hdr.ts_sec = tv.tv_sec;
559 hdr.ts_usec = tv.tv_usec;
560 hdr.orig_len = BUS_MESSAGE_SIZE(m);
561 hdr.incl_len = MIN(hdr.orig_len, snaplen);
563 /* write the pcap header */
564 fwrite(&hdr, 1, sizeof(hdr), f);
566 /* write the dbus header */
567 w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen);
568 fwrite(m->header, 1, w, f);
571 /* write the dbus body */
572 MESSAGE_FOREACH_PART(part, i, m) {
576 w = MIN(part->size, snaplen);
577 fwrite(part->data, 1, w, f);