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"
27 #include "formats-util.h"
28 #include "terminal-util.h"
30 #include "bus-message.h"
31 #include "bus-internal.h"
35 static char *indent(unsigned level
, unsigned flags
) {
41 if (flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
&& level
> 0)
44 if (flags
& BUS_MESSAGE_DUMP_WITH_HEADER
)
47 p
= new(char, n
+ level
*8 + 1);
51 if (flags
& BUS_MESSAGE_DUMP_WITH_HEADER
) {
56 memset(p
+ i
, ' ', level
*8);
62 int bus_message_dump(sd_bus_message
*m
, FILE *f
, unsigned flags
) {
71 if (flags
& BUS_MESSAGE_DUMP_WITH_HEADER
) {
73 "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64
,
74 m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
? ansi_highlight_red() :
75 m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
? ansi_highlight_green() :
76 m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET
), ansi_highlight_off(),
77 ansi_highlight(), bus_message_type_to_string(m
->header
->type
), ansi_highlight_off(),
83 /* Display synthetic message serial number in a more readable
84 * format than (uint32_t) -1 */
85 if (BUS_MESSAGE_COOKIE(m
) == 0xFFFFFFFFULL
)
86 fprintf(f
, " Cookie=-1");
88 fprintf(f
, " Cookie=%" PRIu64
, BUS_MESSAGE_COOKIE(m
));
90 if (m
->reply_cookie
!= 0)
91 fprintf(f
, " ReplyCookie=%" PRIu64
, m
->reply_cookie
);
96 fprintf(f
, " Sender=%s%s%s", ansi_highlight(), m
->sender
, ansi_highlight_off());
98 fprintf(f
, " Destination=%s%s%s", ansi_highlight(), m
->destination
, ansi_highlight_off());
100 fprintf(f
, " Path=%s%s%s", ansi_highlight(), m
->path
, ansi_highlight_off());
102 fprintf(f
, " Interface=%s%s%s", ansi_highlight(), m
->interface
, ansi_highlight_off());
104 fprintf(f
, " Member=%s%s%s", ansi_highlight(), m
->member
, ansi_highlight_off());
106 if (m
->sender
|| m
->destination
|| m
->path
|| m
->interface
|| m
->member
)
109 if (sd_bus_error_is_set(&m
->error
))
112 " ErrorMessage=%s\"%s\"%s\n",
113 ansi_highlight_red(), strna(m
->error
.name
), ansi_highlight_off(),
114 ansi_highlight_red(), strna(m
->error
.message
), ansi_highlight_off());
116 if (m
->monotonic
!= 0)
117 fprintf(f
, " Monotonic="USEC_FMT
, m
->monotonic
);
118 if (m
->realtime
!= 0)
119 fprintf(f
, " Realtime="USEC_FMT
, m
->realtime
);
121 fprintf(f
, " SequenceNumber=%"PRIu64
, m
->seqnum
);
123 if (m
->monotonic
!= 0 || m
->realtime
!= 0 || m
->seqnum
!= 0)
126 bus_creds_dump(&m
->creds
, f
, true);
129 r
= sd_bus_message_rewind(m
, !(flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
));
131 return log_error_errno(r
, "Failed to rewind: %m");
133 if (!(flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
)) {
134 _cleanup_free_
char *prefix
= NULL
;
136 prefix
= indent(0, flags
);
140 fprintf(f
, "%sMESSAGE \"%s\" {\n", prefix
, strempty(m
->root_container
.signature
));
144 _cleanup_free_
char *prefix
= NULL
;
145 const char *contents
= NULL
;
160 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
162 return log_error_errno(r
, "Failed to peek type: %m");
168 r
= sd_bus_message_exit_container(m
);
170 return log_error_errno(r
, "Failed to exit container: %m");
174 prefix
= indent(level
, flags
);
178 fprintf(f
, "%s};\n", prefix
);
182 prefix
= indent(level
, flags
);
186 if (bus_type_is_container(type
) > 0) {
187 r
= sd_bus_message_enter_container(m
, type
, contents
);
189 return log_error_errno(r
, "Failed to enter container: %m");
191 if (type
== SD_BUS_TYPE_ARRAY
)
192 fprintf(f
, "%sARRAY \"%s\" {\n", prefix
, contents
);
193 else if (type
== SD_BUS_TYPE_VARIANT
)
194 fprintf(f
, "%sVARIANT \"%s\" {\n", prefix
, contents
);
195 else if (type
== SD_BUS_TYPE_STRUCT
)
196 fprintf(f
, "%sSTRUCT \"%s\" {\n", prefix
, contents
);
197 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
198 fprintf(f
, "%sDICT_ENTRY \"%s\" {\n", prefix
, contents
);
205 r
= sd_bus_message_read_basic(m
, type
, &basic
);
207 return log_error_errno(r
, "Failed to get basic: %m");
213 case SD_BUS_TYPE_BYTE
:
214 fprintf(f
, "%sBYTE %s%u%s;\n", prefix
, ansi_highlight(), basic
.u8
, ansi_highlight_off());
217 case SD_BUS_TYPE_BOOLEAN
:
218 fprintf(f
, "%sBOOLEAN %s%s%s;\n", prefix
, ansi_highlight(), true_false(basic
.i
), ansi_highlight_off());
221 case SD_BUS_TYPE_INT16
:
222 fprintf(f
, "%sINT16 %s%i%s;\n", prefix
, ansi_highlight(), basic
.s16
, ansi_highlight_off());
225 case SD_BUS_TYPE_UINT16
:
226 fprintf(f
, "%sUINT16 %s%u%s;\n", prefix
, ansi_highlight(), basic
.u16
, ansi_highlight_off());
229 case SD_BUS_TYPE_INT32
:
230 fprintf(f
, "%sINT32 %s%i%s;\n", prefix
, ansi_highlight(), basic
.s32
, ansi_highlight_off());
233 case SD_BUS_TYPE_UINT32
:
234 fprintf(f
, "%sUINT32 %s%u%s;\n", prefix
, ansi_highlight(), basic
.u32
, ansi_highlight_off());
237 case SD_BUS_TYPE_INT64
:
238 fprintf(f
, "%sINT64 %s%"PRIi64
"%s;\n", prefix
, ansi_highlight(), basic
.s64
, ansi_highlight_off());
241 case SD_BUS_TYPE_UINT64
:
242 fprintf(f
, "%sUINT64 %s%"PRIu64
"%s;\n", prefix
, ansi_highlight(), basic
.u64
, ansi_highlight_off());
245 case SD_BUS_TYPE_DOUBLE
:
246 fprintf(f
, "%sDOUBLE %s%g%s;\n", prefix
, ansi_highlight(), basic
.d64
, ansi_highlight_off());
249 case SD_BUS_TYPE_STRING
:
250 fprintf(f
, "%sSTRING \"%s%s%s\";\n", prefix
, ansi_highlight(), basic
.string
, ansi_highlight_off());
253 case SD_BUS_TYPE_OBJECT_PATH
:
254 fprintf(f
, "%sOBJECT_PATH \"%s%s%s\";\n", prefix
, ansi_highlight(), basic
.string
, ansi_highlight_off());
257 case SD_BUS_TYPE_SIGNATURE
:
258 fprintf(f
, "%sSIGNATURE \"%s%s%s\";\n", prefix
, ansi_highlight(), basic
.string
, ansi_highlight_off());
261 case SD_BUS_TYPE_UNIX_FD
:
262 fprintf(f
, "%sUNIX_FD %s%i%s;\n", prefix
, ansi_highlight(), basic
.i
, ansi_highlight_off());
266 assert_not_reached("Unknown basic type.");
270 if (!(flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
)) {
271 _cleanup_free_
char *prefix
= NULL
;
273 prefix
= indent(0, flags
);
277 fprintf(f
, "%s};\n\n", prefix
);
283 static void dump_capabilities(
288 int (*has
)(sd_bus_creds
*c
, int capability
)) {
290 unsigned long i
, last_cap
;
304 fprintf(f
, "%s%s=%s", terse
? " " : "", name
, terse
? "" : ansi_highlight());
305 last_cap
= cap_last_cap();
313 fprintf(f
, terse
? "\n " : "\n ");
315 fprintf(f
, "%s", strna(capability_to_name(i
)));
330 fputs(ansi_highlight_off(), f
);
333 int bus_creds_dump(sd_bus_creds
*c
, FILE *f
, bool terse
) {
334 bool audit_sessionid_is_set
= false, audit_loginuid_is_set
= false;
335 const char *u
= NULL
, *uu
= NULL
, *s
= NULL
, *sl
= NULL
;
336 uid_t owner
, audit_loginuid
;
337 uint32_t audit_sessionid
;
338 char **cmdline
= NULL
, **well_known
= NULL
;
339 const char *prefix
, *color
, *suffix
;
355 color
= ansi_highlight();
357 off
= ansi_highlight_off();
358 suffix
= strjoina(off
, "\n");
361 if (c
->mask
& SD_BUS_CREDS_PID
)
362 fprintf(f
, "%sPID=%s"PID_FMT
"%s", prefix
, color
, c
->pid
, suffix
);
363 if (c
->mask
& SD_BUS_CREDS_TID
)
364 fprintf(f
, "%sTID=%s"PID_FMT
"%s", prefix
, color
, c
->tid
, suffix
);
366 if (terse
&& ((c
->mask
& (SD_BUS_CREDS_PID
|SD_BUS_CREDS_TID
))))
369 if (c
->mask
& SD_BUS_CREDS_UID
)
370 fprintf(f
, "%sUID=%s"UID_FMT
"%s", prefix
, color
, c
->uid
, suffix
);
371 if (c
->mask
& SD_BUS_CREDS_EUID
)
372 fprintf(f
, "%sEUID=%s"UID_FMT
"%s", prefix
, color
, c
->euid
, suffix
);
373 if (c
->mask
& SD_BUS_CREDS_SUID
)
374 fprintf(f
, "%sSUID=%s"UID_FMT
"%s", prefix
, color
, c
->suid
, suffix
);
375 if (c
->mask
& SD_BUS_CREDS_FSUID
)
376 fprintf(f
, "%sFSUID=%s"UID_FMT
"%s", prefix
, color
, c
->fsuid
, suffix
);
377 r
= sd_bus_creds_get_owner_uid(c
, &owner
);
379 fprintf(f
, "%sOwnerUID=%s"UID_FMT
"%s", prefix
, color
, owner
, suffix
);
380 if (c
->mask
& SD_BUS_CREDS_GID
)
381 fprintf(f
, "%sGID=%s"GID_FMT
"%s", prefix
, color
, c
->gid
, suffix
);
382 if (c
->mask
& SD_BUS_CREDS_EGID
)
383 fprintf(f
, "%sEGID=%s"GID_FMT
"%s", prefix
, color
, c
->egid
, suffix
);
384 if (c
->mask
& SD_BUS_CREDS_SGID
)
385 fprintf(f
, "%sSGID=%s"GID_FMT
"%s", prefix
, color
, c
->sgid
, suffix
);
386 if (c
->mask
& SD_BUS_CREDS_FSGID
)
387 fprintf(f
, "%sFSGID=%s"GID_FMT
"%s", prefix
, color
, c
->fsgid
, suffix
);
389 if (c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
392 fprintf(f
, "%sSupplementaryGIDs=%s", prefix
, color
);
393 for (i
= 0; i
< c
->n_supplementary_gids
; i
++)
394 fprintf(f
, "%s" GID_FMT
, i
> 0 ? " " : "", c
->supplementary_gids
[i
]);
395 fprintf(f
, "%s", suffix
);
398 if (terse
&& ((c
->mask
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
399 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
400 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
)) || r
>= 0))
403 if (c
->mask
& SD_BUS_CREDS_COMM
)
404 fprintf(f
, "%sComm=%s%s%s", prefix
, color
, c
->comm
, suffix
);
405 if (c
->mask
& SD_BUS_CREDS_TID_COMM
)
406 fprintf(f
, "%sTIDComm=%s%s%s", prefix
, color
, c
->tid_comm
, suffix
);
407 if (c
->mask
& SD_BUS_CREDS_EXE
)
408 fprintf(f
, "%sExe=%s%s%s", prefix
, color
, c
->exe
, suffix
);
410 if (terse
&& (c
->mask
& (SD_BUS_CREDS_EXE
|SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
)))
413 if (sd_bus_creds_get_cmdline(c
, &cmdline
) >= 0) {
416 fprintf(f
, "%sCommandLine=%s", prefix
, color
);
417 STRV_FOREACH(i
, cmdline
) {
424 fprintf(f
, "%s", suffix
);
427 if (c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
)
428 fprintf(f
, "%sLabel=%s%s%s", prefix
, color
, c
->label
, suffix
);
429 if (c
->mask
& SD_BUS_CREDS_DESCRIPTION
)
430 fprintf(f
, "%sDescription=%s%s%s", prefix
, color
, c
->description
, suffix
);
432 if (terse
&& (c
->mask
& (SD_BUS_CREDS_SELINUX_CONTEXT
|SD_BUS_CREDS_DESCRIPTION
)))
435 if (c
->mask
& SD_BUS_CREDS_CGROUP
)
436 fprintf(f
, "%sCGroup=%s%s%s", prefix
, color
, c
->cgroup
, suffix
);
437 (void) sd_bus_creds_get_unit(c
, &u
);
439 fprintf(f
, "%sUnit=%s%s%s", prefix
, color
, u
, suffix
);
440 (void) sd_bus_creds_get_user_unit(c
, &uu
);
442 fprintf(f
, "%sUserUnit=%s%s%s", prefix
, color
, uu
, suffix
);
443 (void) sd_bus_creds_get_slice(c
, &sl
);
445 fprintf(f
, "%sSlice=%s%s%s", prefix
, color
, sl
, suffix
);
446 (void) sd_bus_creds_get_session(c
, &s
);
448 fprintf(f
, "%sSession=%s%s%s", prefix
, color
, s
, suffix
);
450 if (terse
&& ((c
->mask
& SD_BUS_CREDS_CGROUP
) || u
|| uu
|| sl
|| s
))
453 if (sd_bus_creds_get_audit_login_uid(c
, &audit_loginuid
) >= 0) {
454 audit_loginuid_is_set
= true;
455 fprintf(f
, "%sAuditLoginUID=%s"UID_FMT
"%s", prefix
, color
, audit_loginuid
, suffix
);
457 if (sd_bus_creds_get_audit_session_id(c
, &audit_sessionid
) >= 0) {
458 audit_sessionid_is_set
= true;
459 fprintf(f
, "%sAuditSessionID=%s%"PRIu32
"%s", prefix
, color
, audit_sessionid
, suffix
);
462 if (terse
&& (audit_loginuid_is_set
|| audit_sessionid_is_set
))
465 if (c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
)
466 fprintf(f
, "%sUniqueName=%s%s%s", prefix
, color
, c
->unique_name
, suffix
);
468 if (sd_bus_creds_get_well_known_names(c
, &well_known
) >= 0) {
471 fprintf(f
, "%sWellKnownNames=%s", prefix
, color
);
472 STRV_FOREACH(i
, well_known
) {
479 fprintf(f
, "%s", suffix
);
482 if (terse
&& (c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
|| well_known
))
485 dump_capabilities(c
, f
, "EffectiveCapabilities", terse
, sd_bus_creds_has_effective_cap
);
486 dump_capabilities(c
, f
, "PermittedCapabilities", terse
, sd_bus_creds_has_permitted_cap
);
487 dump_capabilities(c
, f
, "InheritableCapabilities", terse
, sd_bus_creds_has_inheritable_cap
);
488 dump_capabilities(c
, f
, "BoundingCapabilities", terse
, sd_bus_creds_has_bounding_cap
);
494 * For details about the file format, see:
496 * http://wiki.wireshark.org/Development/LibpcapFileFormat
499 typedef struct _packed_ pcap_hdr_s
{
500 uint32_t magic_number
; /* magic number */
501 uint16_t version_major
; /* major version number */
502 uint16_t version_minor
; /* minor version number */
503 int32_t thiszone
; /* GMT to local correction */
504 uint32_t sigfigs
; /* accuracy of timestamps */
505 uint32_t snaplen
; /* max length of captured packets, in octets */
506 uint32_t network
; /* data link type */
509 typedef struct _packed_ pcaprec_hdr_s
{
510 uint32_t ts_sec
; /* timestamp seconds */
511 uint32_t ts_usec
; /* timestamp microseconds */
512 uint32_t incl_len
; /* number of octets of packet saved in file */
513 uint32_t orig_len
; /* actual length of packet */
516 int bus_pcap_header(size_t snaplen
, FILE *f
) {
519 .magic_number
= 0xa1b2c3d4U
,
522 .thiszone
= 0, /* UTC */
524 .network
= 231, /* D-Bus */
531 assert((size_t) (uint32_t) snaplen
== snaplen
);
533 hdr
.snaplen
= (uint32_t) snaplen
;
535 fwrite(&hdr
, 1, sizeof(hdr
), f
);
541 int bus_message_pcap_frame(sd_bus_message
*m
, size_t snaplen
, FILE *f
) {
542 struct bus_body_part
*part
;
543 pcaprec_hdr_t hdr
= {};
553 assert((size_t) (uint32_t) snaplen
== snaplen
);
555 if (m
->realtime
!= 0)
556 timeval_store(&tv
, m
->realtime
);
558 assert_se(gettimeofday(&tv
, NULL
) >= 0);
560 hdr
.ts_sec
= tv
.tv_sec
;
561 hdr
.ts_usec
= tv
.tv_usec
;
562 hdr
.orig_len
= BUS_MESSAGE_SIZE(m
);
563 hdr
.incl_len
= MIN(hdr
.orig_len
, snaplen
);
565 /* write the pcap header */
566 fwrite(&hdr
, 1, sizeof(hdr
), f
);
568 /* write the dbus header */
569 w
= MIN(BUS_MESSAGE_BODY_BEGIN(m
), snaplen
);
570 fwrite(m
->header
, 1, w
, f
);
573 /* write the dbus body */
574 MESSAGE_FOREACH_PART(part
, i
, m
) {
578 w
= MIN(part
->size
, snaplen
);
579 fwrite(part
->data
, 1, w
, f
);