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"
29 #include "bus-message.h"
30 #include "bus-internal.h"
34 static char *indent(unsigned level, unsigned flags) {
40 if (flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY && level > 0)
43 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER)
46 p = new(char, n + level*8 + 1);
50 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
55 memset(p + i, ' ', level*8);
61 int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
70 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
72 "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64,
73 m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
74 m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
75 m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
76 ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
82 /* Display synthetic message serial number in a more readable
83 * format than (uint32_t) -1 */
84 if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL)
85 fprintf(f, " Cookie=-1");
87 fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m));
89 if (m->reply_cookie != 0)
90 fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie);
95 fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
97 fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
99 fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
101 fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
103 fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
105 if (m->sender || m->destination || m->path || m->interface || m->member)
108 if (sd_bus_error_is_set(&m->error))
111 " ErrorMessage=%s\"%s\"%s\n",
112 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
113 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
115 if (m->monotonic != 0)
116 fprintf(f, " Monotonic="USEC_FMT, m->monotonic);
117 if (m->realtime != 0)
118 fprintf(f, " Realtime="USEC_FMT, m->realtime);
120 fprintf(f, " SequenceNumber=%"PRIu64, m->seqnum);
122 if (m->monotonic != 0 || m->realtime != 0 || m->seqnum != 0)
125 bus_creds_dump(&m->creds, f, true);
128 r = sd_bus_message_rewind(m, !(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY));
130 return log_error_errno(r, "Failed to rewind: %m");
132 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
133 _cleanup_free_ char *prefix = NULL;
135 prefix = indent(0, flags);
139 fprintf(f, "%sMESSAGE \"%s\" {\n", prefix, strempty(m->root_container.signature));
143 _cleanup_free_ char *prefix = NULL;
144 const char *contents = NULL;
159 r = sd_bus_message_peek_type(m, &type, &contents);
161 return log_error_errno(r, "Failed to peek type: %m");
167 r = sd_bus_message_exit_container(m);
169 return log_error_errno(r, "Failed to exit container: %m");
173 prefix = indent(level, flags);
177 fprintf(f, "%s};\n", prefix);
181 prefix = indent(level, flags);
185 if (bus_type_is_container(type) > 0) {
186 r = sd_bus_message_enter_container(m, type, contents);
188 return log_error_errno(r, "Failed to enter container: %m");
190 if (type == SD_BUS_TYPE_ARRAY)
191 fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
192 else if (type == SD_BUS_TYPE_VARIANT)
193 fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
194 else if (type == SD_BUS_TYPE_STRUCT)
195 fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
196 else if (type == SD_BUS_TYPE_DICT_ENTRY)
197 fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
204 r = sd_bus_message_read_basic(m, type, &basic);
206 return log_error_errno(r, "Failed to get basic: %m");
212 case SD_BUS_TYPE_BYTE:
213 fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
216 case SD_BUS_TYPE_BOOLEAN:
217 fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_highlight_off());
220 case SD_BUS_TYPE_INT16:
221 fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
224 case SD_BUS_TYPE_UINT16:
225 fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
228 case SD_BUS_TYPE_INT32:
229 fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
232 case SD_BUS_TYPE_UINT32:
233 fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
236 case SD_BUS_TYPE_INT64:
237 fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_highlight_off());
240 case SD_BUS_TYPE_UINT64:
241 fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_highlight_off());
244 case SD_BUS_TYPE_DOUBLE:
245 fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
248 case SD_BUS_TYPE_STRING:
249 fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
252 case SD_BUS_TYPE_OBJECT_PATH:
253 fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
256 case SD_BUS_TYPE_SIGNATURE:
257 fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
260 case SD_BUS_TYPE_UNIX_FD:
261 fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
265 assert_not_reached("Unknown basic type.");
269 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
270 _cleanup_free_ char *prefix = NULL;
272 prefix = indent(0, flags);
276 fprintf(f, "%s};\n\n", prefix);
282 static void dump_capabilities(
287 int (*has)(sd_bus_creds *c, int capability)) {
289 unsigned long i, last_cap;
303 fprintf(f, "%s%s=%s", terse ? " " : "", name, terse ? "" : ansi_highlight());
304 last_cap = cap_last_cap();
312 fprintf(f, terse ? "\n " : "\n ");
314 fprintf(f, "%s", strna(capability_to_name(i)));
329 fputs(ansi_highlight_off(), f);
332 int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
333 bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
334 const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
335 uid_t owner, audit_loginuid;
336 uint32_t audit_sessionid;
337 char **cmdline = NULL, **well_known = NULL;
338 const char *prefix, *color, *suffix;
354 color = ansi_highlight();
356 off = ansi_highlight_off();
357 suffix = strjoina(off, "\n");
360 if (c->mask & SD_BUS_CREDS_PID)
361 fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix);
362 if (c->mask & SD_BUS_CREDS_TID)
363 fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
365 if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID))))
368 if (c->mask & SD_BUS_CREDS_UID)
369 fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix);
370 if (c->mask & SD_BUS_CREDS_EUID)
371 fprintf(f, "%sEUID=%s"UID_FMT"%s", prefix, color, c->euid, suffix);
372 if (c->mask & SD_BUS_CREDS_SUID)
373 fprintf(f, "%sSUID=%s"UID_FMT"%s", prefix, color, c->suid, suffix);
374 if (c->mask & SD_BUS_CREDS_FSUID)
375 fprintf(f, "%sFSUID=%s"UID_FMT"%s", prefix, color, c->fsuid, suffix);
376 r = sd_bus_creds_get_owner_uid(c, &owner);
378 fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix);
379 if (c->mask & SD_BUS_CREDS_GID)
380 fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix);
381 if (c->mask & SD_BUS_CREDS_EGID)
382 fprintf(f, "%sEGID=%s"GID_FMT"%s", prefix, color, c->egid, suffix);
383 if (c->mask & SD_BUS_CREDS_SGID)
384 fprintf(f, "%sSGID=%s"GID_FMT"%s", prefix, color, c->sgid, suffix);
385 if (c->mask & SD_BUS_CREDS_FSGID)
386 fprintf(f, "%sFSGID=%s"GID_FMT"%s", prefix, color, c->fsgid, suffix);
388 if (c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
391 fprintf(f, "%sSupplementaryGIDs=%s", prefix, color);
392 for (i = 0; i < c->n_supplementary_gids; i++)
393 fprintf(f, "%s" GID_FMT, i > 0 ? " " : "", c->supplementary_gids[i]);
394 fprintf(f, "%s", suffix);
397 if (terse && ((c->mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
398 SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
399 SD_BUS_CREDS_SUPPLEMENTARY_GIDS)) || r >= 0))
402 if (c->mask & SD_BUS_CREDS_COMM)
403 fprintf(f, "%sComm=%s%s%s", prefix, color, c->comm, suffix);
404 if (c->mask & SD_BUS_CREDS_TID_COMM)
405 fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix);
406 if (c->mask & SD_BUS_CREDS_EXE)
407 fprintf(f, "%sExe=%s%s%s", prefix, color, c->exe, suffix);
409 if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)))
412 if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
415 fprintf(f, "%sCommandLine=%s", prefix, color);
416 STRV_FOREACH(i, cmdline) {
423 fprintf(f, "%s", suffix);
426 if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
427 fprintf(f, "%sLabel=%s%s%s", prefix, color, c->label, suffix);
428 if (c->mask & SD_BUS_CREDS_DESCRIPTION)
429 fprintf(f, "%sDescription=%s%s%s", prefix, color, c->description, suffix);
431 if (terse && (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION)))
434 if (c->mask & SD_BUS_CREDS_CGROUP)
435 fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix);
436 (void) sd_bus_creds_get_unit(c, &u);
438 fprintf(f, "%sUnit=%s%s%s", prefix, color, u, suffix);
439 (void) sd_bus_creds_get_user_unit(c, &uu);
441 fprintf(f, "%sUserUnit=%s%s%s", prefix, color, uu, suffix);
442 (void) sd_bus_creds_get_slice(c, &sl);
444 fprintf(f, "%sSlice=%s%s%s", prefix, color, sl, suffix);
445 (void) sd_bus_creds_get_session(c, &s);
447 fprintf(f, "%sSession=%s%s%s", prefix, color, s, suffix);
449 if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s))
452 if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
453 audit_loginuid_is_set = true;
454 fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix);
456 if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
457 audit_sessionid_is_set = true;
458 fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix);
461 if (terse && (audit_loginuid_is_set || audit_sessionid_is_set))
464 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
465 fprintf(f, "%sUniqueName=%s%s%s", prefix, color, c->unique_name, suffix);
467 if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
470 fprintf(f, "%sWellKnownNames=%s", prefix, color);
471 STRV_FOREACH(i, well_known) {
478 fprintf(f, "%s", suffix);
481 if (terse && (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known))
484 dump_capabilities(c, f, "EffectiveCapabilities", terse, sd_bus_creds_has_effective_cap);
485 dump_capabilities(c, f, "PermittedCapabilities", terse, sd_bus_creds_has_permitted_cap);
486 dump_capabilities(c, f, "InheritableCapabilities", terse, sd_bus_creds_has_inheritable_cap);
487 dump_capabilities(c, f, "BoundingCapabilities", terse, sd_bus_creds_has_bounding_cap);
493 * For details about the file format, see:
495 * http://wiki.wireshark.org/Development/LibpcapFileFormat
498 typedef struct _packed_ pcap_hdr_s {
499 uint32_t magic_number; /* magic number */
500 uint16_t version_major; /* major version number */
501 uint16_t version_minor; /* minor version number */
502 int32_t thiszone; /* GMT to local correction */
503 uint32_t sigfigs; /* accuracy of timestamps */
504 uint32_t snaplen; /* max length of captured packets, in octets */
505 uint32_t network; /* data link type */
508 typedef struct _packed_ pcaprec_hdr_s {
509 uint32_t ts_sec; /* timestamp seconds */
510 uint32_t ts_usec; /* timestamp microseconds */
511 uint32_t incl_len; /* number of octets of packet saved in file */
512 uint32_t orig_len; /* actual length of packet */
515 int bus_pcap_header(size_t snaplen, FILE *f) {
518 .magic_number = 0xa1b2c3d4U,
521 .thiszone = 0, /* UTC */
523 .network = 231, /* D-Bus */
530 assert((size_t) (uint32_t) snaplen == snaplen);
532 hdr.snaplen = (uint32_t) snaplen;
534 fwrite(&hdr, 1, sizeof(hdr), f);
540 int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
541 struct bus_body_part *part;
542 pcaprec_hdr_t hdr = {};
552 assert((size_t) (uint32_t) snaplen == snaplen);
554 if (m->realtime != 0)
555 timeval_store(&tv, m->realtime);
557 assert_se(gettimeofday(&tv, NULL) >= 0);
559 hdr.ts_sec = tv.tv_sec;
560 hdr.ts_usec = tv.tv_usec;
561 hdr.orig_len = BUS_MESSAGE_SIZE(m);
562 hdr.incl_len = MIN(hdr.orig_len, snaplen);
564 /* write the pcap header */
565 fwrite(&hdr, 1, sizeof(hdr), f);
567 /* write the dbus header */
568 w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen);
569 fwrite(m->header, 1, w, f);
572 /* write the dbus body */
573 MESSAGE_FOREACH_PART(part, i, m) {
577 w = MIN(part->size, snaplen);
578 fwrite(part->data, 1, w, f);