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=%lli",
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(),
79 (long long) m->priority);
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 log_error("Failed to rewind: %s", strerror(-r));
133 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY))
134 fprintf(f, "%sMESSAGE \"%s\" {\n", indent(0, flags), strempty(m->root_container.signature));
137 _cleanup_free_ char *prefix = NULL;
138 const char *contents = NULL;
153 r = sd_bus_message_peek_type(m, &type, &contents);
155 log_error("Failed to peek type: %s", strerror(-r));
163 r = sd_bus_message_exit_container(m);
165 log_error("Failed to exit container: %s", strerror(-r));
171 prefix = indent(level, flags);
175 fprintf(f, "%s};\n", prefix);
179 prefix = indent(level, flags);
183 if (bus_type_is_container(type) > 0) {
184 r = sd_bus_message_enter_container(m, type, contents);
186 log_error("Failed to enter container: %s", strerror(-r));
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 log_error("Failed to get basic: %s", strerror(-r));
214 case SD_BUS_TYPE_BYTE:
215 fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
218 case SD_BUS_TYPE_BOOLEAN:
219 fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_highlight_off());
222 case SD_BUS_TYPE_INT16:
223 fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
226 case SD_BUS_TYPE_UINT16:
227 fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
230 case SD_BUS_TYPE_INT32:
231 fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
234 case SD_BUS_TYPE_UINT32:
235 fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
238 case SD_BUS_TYPE_INT64:
239 fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_highlight_off());
242 case SD_BUS_TYPE_UINT64:
243 fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_highlight_off());
246 case SD_BUS_TYPE_DOUBLE:
247 fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
250 case SD_BUS_TYPE_STRING:
251 fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
254 case SD_BUS_TYPE_OBJECT_PATH:
255 fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
258 case SD_BUS_TYPE_SIGNATURE:
259 fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
262 case SD_BUS_TYPE_UNIX_FD:
263 fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
267 assert_not_reached("Unknown basic type.");
271 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY))
272 fprintf(f, "%s};\n\n", indent(0, flags));
277 static void dump_capabilities(
282 int (*has)(sd_bus_creds *c, int capability)) {
284 unsigned long i, last_cap;
298 fprintf(f, "%s%s=%s", terse ? " " : "", name, terse ? "" : ansi_highlight());
299 last_cap = cap_last_cap();
303 _cleanup_cap_free_charp_ char *t;
308 fprintf(f, terse ? "\n " : "\n ");
326 fputs(ansi_highlight_off(), f);
329 int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
330 bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
331 const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
332 uid_t owner, audit_loginuid;
333 uint32_t audit_sessionid;
334 char **cmdline = NULL, **well_known = NULL;
335 const char *prefix, *color, *suffix;
351 color = ansi_highlight();
353 off = ansi_highlight_off();
354 suffix = strappenda(off, "\n");
357 if (c->mask & SD_BUS_CREDS_PID)
358 fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix);
359 if (c->mask & SD_BUS_CREDS_PID_STARTTIME)
360 fprintf(f, "%sPIDStartTime=%s"USEC_FMT"%s", prefix, color, c->pid_starttime, suffix);
361 if (c->mask & SD_BUS_CREDS_TID)
362 fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
363 if (c->mask & SD_BUS_CREDS_UID)
364 fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix);
365 r = sd_bus_creds_get_owner_uid(c, &owner);
367 fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix);
368 if (c->mask & SD_BUS_CREDS_GID)
369 fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix);
371 if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID)) || r >= 0))
374 if (c->mask & SD_BUS_CREDS_EXE)
375 fprintf(f, "%sExe=%s%s%s", prefix, color, c->exe, suffix);
376 if (c->mask & SD_BUS_CREDS_COMM)
377 fprintf(f, "%sComm=%s%s%s", prefix, color, c->comm, suffix);
378 if (c->mask & SD_BUS_CREDS_TID_COMM)
379 fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix);
381 if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)))
384 if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
385 fprintf(f, "%sLabel=%s%s%s", prefix, color, c->label, suffix);
386 if (c->mask & SD_BUS_CREDS_DESCRIPTION)
387 fprintf(f, "%sDescription=%s%s%s", prefix, color, c->description, suffix);
389 if (terse && (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION)))
392 if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
395 fprintf(f, "%sCommandLine=%s", prefix, color);
396 STRV_FOREACH(i, cmdline) {
403 fprintf(f, "%s", suffix);
406 if (c->mask & SD_BUS_CREDS_CGROUP)
407 fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix);
408 sd_bus_creds_get_unit(c, &u);
410 fprintf(f, "%sUnit=%s%s%s", prefix, color, u, suffix);
411 sd_bus_creds_get_user_unit(c, &uu);
413 fprintf(f, "%sUserUnit=%s%s%s", prefix, color, uu, suffix);
414 sd_bus_creds_get_slice(c, &sl);
416 fprintf(f, "%sSlice=%s%s%s", prefix, color, sl, suffix);
417 sd_bus_creds_get_session(c, &s);
419 fprintf(f, "%sSession=%s%s%s", prefix, color, s, suffix);
421 if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s))
424 if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
425 audit_loginuid_is_set = true;
426 fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix);
428 if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
429 audit_sessionid_is_set = true;
430 fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix);
433 if (terse && (audit_loginuid_is_set || audit_sessionid_is_set))
436 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
437 fprintf(f, "%sUniqueName=%s%s%s", prefix, color, c->unique_name, suffix);
439 if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
442 fprintf(f, "%sWellKnownNames=%s", prefix, color);
443 STRV_FOREACH(i, well_known) {
450 fprintf(f, "%s", suffix);
453 if (terse && (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known))
456 dump_capabilities(c, f, "EffectiveCapabilities", terse, sd_bus_creds_has_effective_cap);
457 dump_capabilities(c, f, "PermittedCapabilities", terse, sd_bus_creds_has_permitted_cap);
458 dump_capabilities(c, f, "InheritableCapabilities", terse, sd_bus_creds_has_inheritable_cap);
459 dump_capabilities(c, f, "BoundingCapabilities", terse, sd_bus_creds_has_bounding_cap);
465 * For details about the file format, see:
467 * http://wiki.wireshark.org/Development/LibpcapFileFormat
470 typedef struct _packed_ pcap_hdr_s {
471 uint32_t magic_number; /* magic number */
472 uint16_t version_major; /* major version number */
473 uint16_t version_minor; /* minor version number */
474 int32_t thiszone; /* GMT to local correction */
475 uint32_t sigfigs; /* accuracy of timestamps */
476 uint32_t snaplen; /* max length of captured packets, in octets */
477 uint32_t network; /* data link type */
480 typedef struct _packed_ pcaprec_hdr_s {
481 uint32_t ts_sec; /* timestamp seconds */
482 uint32_t ts_usec; /* timestamp microseconds */
483 uint32_t incl_len; /* number of octets of packet saved in file */
484 uint32_t orig_len; /* actual length of packet */
487 int bus_pcap_header(size_t snaplen, FILE *f) {
490 .magic_number = 0xa1b2c3d4U,
493 .thiszone = 0, /* UTC */
495 .network = 231, /* D-Bus */
502 assert((size_t) (uint32_t) snaplen == snaplen);
504 hdr.snaplen = (uint32_t) snaplen;
506 fwrite(&hdr, 1, sizeof(hdr), f);
512 int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
513 struct bus_body_part *part;
514 pcaprec_hdr_t hdr = {};
524 assert((size_t) (uint32_t) snaplen == snaplen);
526 if (m->realtime != 0)
527 timeval_store(&tv, m->realtime);
529 assert_se(gettimeofday(&tv, NULL) >= 0);
531 hdr.ts_sec = tv.tv_sec;
532 hdr.ts_usec = tv.tv_usec;
533 hdr.orig_len = BUS_MESSAGE_SIZE(m);
534 hdr.incl_len = MIN(hdr.orig_len, snaplen);
536 /* write the pcap header */
537 fwrite(&hdr, 1, sizeof(hdr), f);
539 /* write the dbus header */
540 w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen);
541 fwrite(m->header, 1, w, f);
544 /* write the dbus body */
545 MESSAGE_FOREACH_PART(part, i, m) {
549 w = MIN(part->size, snaplen);
550 fwrite(part->data, 1, w, f);