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) {
36 p = new(char, 2 + level + 1);
41 memset(p + 2, '\t', level);
47 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
58 "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%lli",
59 m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
60 m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
61 m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
62 ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
66 (long long) m->priority);
68 /* Display synthetic message serial number in a more readable
69 * format than (uint32_t) -1 */
70 if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL)
71 fprintf(f, " Cookie=-1");
73 fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m));
75 if (m->reply_cookie != 0)
76 fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie);
81 fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
83 fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
85 fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
87 fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
89 fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
91 if (m->sender || m->destination || m->path || m->interface || m->member)
94 if (sd_bus_error_is_set(&m->error))
97 " ErrorMessage=%s\"%s\"%s\n",
98 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
99 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
101 if (m->monotonic != 0)
102 fprintf(f, " Monotonic="USEC_FMT, m->monotonic);
103 if (m->realtime != 0)
104 fprintf(f, " Realtime="USEC_FMT, m->realtime);
106 fprintf(f, " SequenceNumber=%"PRIu64, m->seqnum);
108 if (m->monotonic != 0 || m->realtime != 0 || m->seqnum != 0)
111 bus_creds_dump(&m->creds, f);
114 r = sd_bus_message_rewind(m, true);
116 log_error("Failed to rewind: %s", strerror(-r));
120 fprintf(f, " MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
123 _cleanup_free_ char *prefix = NULL;
124 const char *contents = NULL;
139 r = sd_bus_message_peek_type(m, &type, &contents);
141 log_error("Failed to peek type: %s", strerror(-r));
149 r = sd_bus_message_exit_container(m);
151 log_error("Failed to exit container: %s", strerror(-r));
157 prefix = indent(level);
161 fprintf(f, "%s};\n", prefix);
165 prefix = indent(level);
169 if (bus_type_is_container(type) > 0) {
170 r = sd_bus_message_enter_container(m, type, contents);
172 log_error("Failed to enter container: %s", strerror(-r));
176 if (type == SD_BUS_TYPE_ARRAY)
177 fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
178 else if (type == SD_BUS_TYPE_VARIANT)
179 fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
180 else if (type == SD_BUS_TYPE_STRUCT)
181 fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
182 else if (type == SD_BUS_TYPE_DICT_ENTRY)
183 fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
190 r = sd_bus_message_read_basic(m, type, &basic);
192 log_error("Failed to get basic: %s", strerror(-r));
200 case SD_BUS_TYPE_BYTE:
201 fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
204 case SD_BUS_TYPE_BOOLEAN:
205 fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_highlight_off());
208 case SD_BUS_TYPE_INT16:
209 fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
212 case SD_BUS_TYPE_UINT16:
213 fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
216 case SD_BUS_TYPE_INT32:
217 fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
220 case SD_BUS_TYPE_UINT32:
221 fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
224 case SD_BUS_TYPE_INT64:
225 fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_highlight_off());
228 case SD_BUS_TYPE_UINT64:
229 fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_highlight_off());
232 case SD_BUS_TYPE_DOUBLE:
233 fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
236 case SD_BUS_TYPE_STRING:
237 fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
240 case SD_BUS_TYPE_OBJECT_PATH:
241 fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
244 case SD_BUS_TYPE_SIGNATURE:
245 fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
248 case SD_BUS_TYPE_UNIX_FD:
249 fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
253 assert_not_reached("Unknown basic type.");
257 fprintf(f, " };\n\n");
261 static void dump_capabilities(
265 int (*has)(sd_bus_creds *c, int capability)) {
267 unsigned long i, last_cap;
281 fprintf(f, " %s=", name);
282 last_cap = cap_last_cap();
286 _cleanup_cap_free_charp_ char *t;
309 int bus_creds_dump(sd_bus_creds *c, FILE *f) {
310 bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
311 const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
312 uid_t owner, audit_loginuid;
313 uint32_t audit_sessionid;
314 char **cmdline = NULL, **well_known = NULL;
322 if (c->mask & SD_BUS_CREDS_PID)
323 fprintf(f, " PID="PID_FMT, c->pid);
324 if (c->mask & SD_BUS_CREDS_PID_STARTTIME)
325 fprintf(f, " PIDStartTime="USEC_FMT, c->pid_starttime);
326 if (c->mask & SD_BUS_CREDS_TID)
327 fprintf(f, " TID="PID_FMT, c->tid);
328 if (c->mask & SD_BUS_CREDS_UID)
329 fprintf(f, " UID="UID_FMT, c->uid);
330 r = sd_bus_creds_get_owner_uid(c, &owner);
332 fprintf(f, " OwnerUID="UID_FMT, owner);
333 if (c->mask & SD_BUS_CREDS_GID)
334 fprintf(f, " GID="GID_FMT, c->gid);
336 if ((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)
339 if (c->mask & SD_BUS_CREDS_EXE)
340 fprintf(f, " Exe=%s", c->exe);
341 if (c->mask & SD_BUS_CREDS_COMM)
342 fprintf(f, " Comm=%s", c->comm);
343 if (c->mask & SD_BUS_CREDS_TID_COMM)
344 fprintf(f, " TIDComm=%s", c->tid_comm);
346 if (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))
349 if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
350 fprintf(f, " Label=%s", c->label);
351 if (c->mask & SD_BUS_CREDS_DESCRIPTION)
352 fprintf(f, " Description=%s", c->description);
354 if (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION))
357 if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
360 fputs(" CommandLine={", f);
361 STRV_FOREACH(i, cmdline) {
371 if (c->mask & SD_BUS_CREDS_CGROUP)
372 fprintf(f, " CGroup=%s", c->cgroup);
373 sd_bus_creds_get_unit(c, &u);
375 fprintf(f, " Unit=%s", u);
376 sd_bus_creds_get_user_unit(c, &uu);
378 fprintf(f, " UserUnit=%s", uu);
379 sd_bus_creds_get_slice(c, &sl);
381 fprintf(f, " Slice=%s", sl);
382 sd_bus_creds_get_session(c, &s);
384 fprintf(f, " Session=%s", s);
386 if ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s)
389 if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
390 audit_loginuid_is_set = true;
391 fprintf(f, " AuditLoginUID="UID_FMT, audit_loginuid);
393 if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
394 audit_sessionid_is_set = true;
395 fprintf(f, " AuditSessionID=%"PRIu32, audit_sessionid);
398 if (audit_loginuid_is_set || audit_sessionid_is_set)
401 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
402 fprintf(f, " UniqueName=%s", c->unique_name);
404 if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
407 fputs(" WellKnownNames={", f);
408 STRV_FOREACH(i, well_known) {
418 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known)
421 dump_capabilities(c, f, "EffectiveCapabilities", sd_bus_creds_has_effective_cap);
422 dump_capabilities(c, f, "PermittedCapabilities", sd_bus_creds_has_permitted_cap);
423 dump_capabilities(c, f, "InheritableCapabilities", sd_bus_creds_has_inheritable_cap);
424 dump_capabilities(c, f, "BoundingCapabilities", sd_bus_creds_has_bounding_cap);
430 * For details about the file format, see:
432 * http://wiki.wireshark.org/Development/LibpcapFileFormat
435 typedef struct _packed_ pcap_hdr_s {
436 uint32_t magic_number; /* magic number */
437 uint16_t version_major; /* major version number */
438 uint16_t version_minor; /* minor version number */
439 int32_t thiszone; /* GMT to local correction */
440 uint32_t sigfigs; /* accuracy of timestamps */
441 uint32_t snaplen; /* max length of captured packets, in octets */
442 uint32_t network; /* data link type */
445 typedef struct _packed_ pcaprec_hdr_s {
446 uint32_t ts_sec; /* timestamp seconds */
447 uint32_t ts_usec; /* timestamp microseconds */
448 uint32_t incl_len; /* number of octets of packet saved in file */
449 uint32_t orig_len; /* actual length of packet */
452 int bus_pcap_header(size_t snaplen, FILE *f) {
455 .magic_number = 0xa1b2c3d4U,
458 .thiszone = 0, /* UTC */
460 .network = 231, /* D-Bus */
467 assert((size_t) (uint32_t) snaplen == snaplen);
469 hdr.snaplen = (uint32_t) snaplen;
471 fwrite(&hdr, 1, sizeof(hdr), f);
477 int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
478 struct bus_body_part *part;
479 pcaprec_hdr_t hdr = {};
489 assert((size_t) (uint32_t) snaplen == snaplen);
491 if (m->realtime != 0)
492 timeval_store(&tv, m->realtime);
494 assert_se(gettimeofday(&tv, NULL) >= 0);
496 hdr.ts_sec = tv.tv_sec;
497 hdr.ts_usec = tv.tv_usec;
498 hdr.orig_len = BUS_MESSAGE_SIZE(m);
499 hdr.incl_len = MIN(hdr.orig_len, snaplen);
501 /* write the pcap header */
502 fwrite(&hdr, 1, sizeof(hdr), f);
504 /* write the dbus header */
505 w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen);
506 fwrite(m->header, 1, w, f);
509 /* write the dbus body */
510 MESSAGE_FOREACH_PART(part, i, m) {
514 w = MIN(part->size, snaplen);
515 fwrite(part->data, 1, w, f);