1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include "alloc-util.h"
23 #include "bus-internal.h"
24 #include "bus-message.h"
27 #include "capability-util.h"
29 #include "format-util.h"
30 #include "locale-util.h"
32 #include "string-util.h"
34 #include "terminal-util.h"
37 static char *indent(unsigned level
, unsigned flags
) {
43 if (flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
&& level
> 0)
46 if (flags
& BUS_MESSAGE_DUMP_WITH_HEADER
)
49 p
= new(char, n
+ level
*8 + 1);
53 if (flags
& BUS_MESSAGE_DUMP_WITH_HEADER
) {
58 memset(p
+ i
, ' ', level
*8);
64 int bus_message_dump(sd_bus_message
*m
, FILE *f
, unsigned flags
) {
73 if (flags
& BUS_MESSAGE_DUMP_WITH_HEADER
) {
75 "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64
,
76 m
->header
->type
== SD_BUS_MESSAGE_METHOD_ERROR
? ansi_highlight_red() :
77 m
->header
->type
== SD_BUS_MESSAGE_METHOD_RETURN
? ansi_highlight_green() :
78 m
->header
->type
!= SD_BUS_MESSAGE_SIGNAL
? ansi_highlight() : "", special_glyph(TRIANGULAR_BULLET
), ansi_normal(),
79 ansi_highlight(), bus_message_type_to_string(m
->header
->type
), ansi_normal(),
85 /* Display synthetic message serial number in a more readable
86 * format than (uint32_t) -1 */
87 if (BUS_MESSAGE_COOKIE(m
) == 0xFFFFFFFFULL
)
88 fprintf(f
, " Cookie=-1");
90 fprintf(f
, " Cookie=%" PRIu64
, BUS_MESSAGE_COOKIE(m
));
92 if (m
->reply_cookie
!= 0)
93 fprintf(f
, " ReplyCookie=%" PRIu64
, m
->reply_cookie
);
98 fprintf(f
, " Sender=%s%s%s", ansi_highlight(), m
->sender
, ansi_normal());
100 fprintf(f
, " Destination=%s%s%s", ansi_highlight(), m
->destination
, ansi_normal());
102 fprintf(f
, " Path=%s%s%s", ansi_highlight(), m
->path
, ansi_normal());
104 fprintf(f
, " Interface=%s%s%s", ansi_highlight(), m
->interface
, ansi_normal());
106 fprintf(f
, " Member=%s%s%s", ansi_highlight(), m
->member
, ansi_normal());
108 if (m
->sender
|| m
->destination
|| m
->path
|| m
->interface
|| m
->member
)
111 if (sd_bus_error_is_set(&m
->error
))
114 " ErrorMessage=%s\"%s\"%s\n",
115 ansi_highlight_red(), strna(m
->error
.name
), ansi_normal(),
116 ansi_highlight_red(), strna(m
->error
.message
), ansi_normal());
118 if (m
->monotonic
!= 0)
119 fprintf(f
, " Monotonic="USEC_FMT
, m
->monotonic
);
120 if (m
->realtime
!= 0)
121 fprintf(f
, " Realtime="USEC_FMT
, m
->realtime
);
123 fprintf(f
, " SequenceNumber=%"PRIu64
, m
->seqnum
);
125 if (m
->monotonic
!= 0 || m
->realtime
!= 0 || m
->seqnum
!= 0)
128 bus_creds_dump(&m
->creds
, f
, true);
131 r
= sd_bus_message_rewind(m
, !(flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
));
133 return log_error_errno(r
, "Failed to rewind: %m");
135 if (!(flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
)) {
136 _cleanup_free_
char *prefix
= NULL
;
138 prefix
= indent(0, flags
);
142 fprintf(f
, "%sMESSAGE \"%s\" {\n", prefix
, strempty(m
->root_container
.signature
));
146 _cleanup_free_
char *prefix
= NULL
;
147 const char *contents
= NULL
;
162 r
= sd_bus_message_peek_type(m
, &type
, &contents
);
164 return log_error_errno(r
, "Failed to peek type: %m");
170 r
= sd_bus_message_exit_container(m
);
172 return log_error_errno(r
, "Failed to exit container: %m");
176 prefix
= indent(level
, flags
);
180 fprintf(f
, "%s};\n", prefix
);
184 prefix
= indent(level
, flags
);
188 if (bus_type_is_container(type
) > 0) {
189 r
= sd_bus_message_enter_container(m
, type
, contents
);
191 return log_error_errno(r
, "Failed to enter container: %m");
193 if (type
== SD_BUS_TYPE_ARRAY
)
194 fprintf(f
, "%sARRAY \"%s\" {\n", prefix
, contents
);
195 else if (type
== SD_BUS_TYPE_VARIANT
)
196 fprintf(f
, "%sVARIANT \"%s\" {\n", prefix
, contents
);
197 else if (type
== SD_BUS_TYPE_STRUCT
)
198 fprintf(f
, "%sSTRUCT \"%s\" {\n", prefix
, contents
);
199 else if (type
== SD_BUS_TYPE_DICT_ENTRY
)
200 fprintf(f
, "%sDICT_ENTRY \"%s\" {\n", prefix
, contents
);
207 r
= sd_bus_message_read_basic(m
, type
, &basic
);
209 return log_error_errno(r
, "Failed to get basic: %m");
215 case SD_BUS_TYPE_BYTE
:
216 fprintf(f
, "%sBYTE %s%u%s;\n", prefix
, ansi_highlight(), basic
.u8
, ansi_normal());
219 case SD_BUS_TYPE_BOOLEAN
:
220 fprintf(f
, "%sBOOLEAN %s%s%s;\n", prefix
, ansi_highlight(), true_false(basic
.i
), ansi_normal());
223 case SD_BUS_TYPE_INT16
:
224 fprintf(f
, "%sINT16 %s%i%s;\n", prefix
, ansi_highlight(), basic
.s16
, ansi_normal());
227 case SD_BUS_TYPE_UINT16
:
228 fprintf(f
, "%sUINT16 %s%u%s;\n", prefix
, ansi_highlight(), basic
.u16
, ansi_normal());
231 case SD_BUS_TYPE_INT32
:
232 fprintf(f
, "%sINT32 %s%i%s;\n", prefix
, ansi_highlight(), basic
.s32
, ansi_normal());
235 case SD_BUS_TYPE_UINT32
:
236 fprintf(f
, "%sUINT32 %s%u%s;\n", prefix
, ansi_highlight(), basic
.u32
, ansi_normal());
239 case SD_BUS_TYPE_INT64
:
240 fprintf(f
, "%sINT64 %s%"PRIi64
"%s;\n", prefix
, ansi_highlight(), basic
.s64
, ansi_normal());
243 case SD_BUS_TYPE_UINT64
:
244 fprintf(f
, "%sUINT64 %s%"PRIu64
"%s;\n", prefix
, ansi_highlight(), basic
.u64
, ansi_normal());
247 case SD_BUS_TYPE_DOUBLE
:
248 fprintf(f
, "%sDOUBLE %s%g%s;\n", prefix
, ansi_highlight(), basic
.d64
, ansi_normal());
251 case SD_BUS_TYPE_STRING
:
252 fprintf(f
, "%sSTRING \"%s%s%s\";\n", prefix
, ansi_highlight(), basic
.string
, ansi_normal());
255 case SD_BUS_TYPE_OBJECT_PATH
:
256 fprintf(f
, "%sOBJECT_PATH \"%s%s%s\";\n", prefix
, ansi_highlight(), basic
.string
, ansi_normal());
259 case SD_BUS_TYPE_SIGNATURE
:
260 fprintf(f
, "%sSIGNATURE \"%s%s%s\";\n", prefix
, ansi_highlight(), basic
.string
, ansi_normal());
263 case SD_BUS_TYPE_UNIX_FD
:
264 fprintf(f
, "%sUNIX_FD %s%i%s;\n", prefix
, ansi_highlight(), basic
.i
, ansi_normal());
268 assert_not_reached("Unknown basic type.");
272 if (!(flags
& BUS_MESSAGE_DUMP_SUBTREE_ONLY
)) {
273 _cleanup_free_
char *prefix
= NULL
;
275 prefix
= indent(0, flags
);
279 fprintf(f
, "%s};\n\n", prefix
);
285 static void dump_capabilities(
290 int (*has
)(sd_bus_creds
*c
, int capability
)) {
292 unsigned long i
, last_cap
;
306 fprintf(f
, "%s%s=%s", terse
? " " : "", name
, terse
? "" : ansi_highlight());
307 last_cap
= cap_last_cap();
315 fprintf(f
, terse
? "\n " : "\n ");
317 fprintf(f
, "%s", strna(capability_to_name(i
)));
332 fputs(ansi_normal(), f
);
335 int bus_creds_dump(sd_bus_creds
*c
, FILE *f
, bool terse
) {
336 uid_t owner
, audit_loginuid
;
337 uint32_t audit_sessionid
;
338 char **cmdline
= NULL
, **well_known
= NULL
;
339 const char *prefix
, *color
, *suffix
, *s
;
355 color
= ansi_highlight();
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
);
365 if (c
->mask
& SD_BUS_CREDS_PPID
) {
367 fprintf(f
, "%sPPID=%sn/a%s", prefix
, color
, suffix
);
369 fprintf(f
, "%sPPID=%s"PID_FMT
"%s", prefix
, color
, c
->ppid
, suffix
);
371 if (c
->mask
& SD_BUS_CREDS_TTY
)
372 fprintf(f
, "%sTTY=%s%s%s", prefix
, color
, strna(c
->tty
), suffix
);
374 if (terse
&& ((c
->mask
& (SD_BUS_CREDS_PID
|SD_BUS_CREDS_TID
|SD_BUS_CREDS_PPID
|SD_BUS_CREDS_TTY
))))
377 if (c
->mask
& SD_BUS_CREDS_UID
)
378 fprintf(f
, "%sUID=%s"UID_FMT
"%s", prefix
, color
, c
->uid
, suffix
);
379 if (c
->mask
& SD_BUS_CREDS_EUID
)
380 fprintf(f
, "%sEUID=%s"UID_FMT
"%s", prefix
, color
, c
->euid
, suffix
);
381 if (c
->mask
& SD_BUS_CREDS_SUID
)
382 fprintf(f
, "%sSUID=%s"UID_FMT
"%s", prefix
, color
, c
->suid
, suffix
);
383 if (c
->mask
& SD_BUS_CREDS_FSUID
)
384 fprintf(f
, "%sFSUID=%s"UID_FMT
"%s", prefix
, color
, c
->fsuid
, suffix
);
385 r
= sd_bus_creds_get_owner_uid(c
, &owner
);
387 fprintf(f
, "%sOwnerUID=%s"UID_FMT
"%s", prefix
, color
, owner
, suffix
);
388 if (c
->mask
& SD_BUS_CREDS_GID
)
389 fprintf(f
, "%sGID=%s"GID_FMT
"%s", prefix
, color
, c
->gid
, suffix
);
390 if (c
->mask
& SD_BUS_CREDS_EGID
)
391 fprintf(f
, "%sEGID=%s"GID_FMT
"%s", prefix
, color
, c
->egid
, suffix
);
392 if (c
->mask
& SD_BUS_CREDS_SGID
)
393 fprintf(f
, "%sSGID=%s"GID_FMT
"%s", prefix
, color
, c
->sgid
, suffix
);
394 if (c
->mask
& SD_BUS_CREDS_FSGID
)
395 fprintf(f
, "%sFSGID=%s"GID_FMT
"%s", prefix
, color
, c
->fsgid
, suffix
);
397 if (c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
400 fprintf(f
, "%sSupplementaryGIDs=%s", prefix
, color
);
401 for (i
= 0; i
< c
->n_supplementary_gids
; i
++)
402 fprintf(f
, "%s" GID_FMT
, i
> 0 ? " " : "", c
->supplementary_gids
[i
]);
403 fprintf(f
, "%s", suffix
);
406 if (terse
&& ((c
->mask
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
|
407 SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
|
408 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
)) || r
>= 0))
411 if (c
->mask
& SD_BUS_CREDS_COMM
)
412 fprintf(f
, "%sComm=%s%s%s", prefix
, color
, c
->comm
, suffix
);
413 if (c
->mask
& SD_BUS_CREDS_TID_COMM
)
414 fprintf(f
, "%sTIDComm=%s%s%s", prefix
, color
, c
->tid_comm
, suffix
);
415 if (c
->mask
& SD_BUS_CREDS_EXE
)
416 fprintf(f
, "%sExe=%s%s%s", prefix
, color
, strna(c
->exe
), suffix
);
418 if (terse
&& (c
->mask
& (SD_BUS_CREDS_EXE
|SD_BUS_CREDS_COMM
|SD_BUS_CREDS_TID_COMM
)))
421 r
= sd_bus_creds_get_cmdline(c
, &cmdline
);
425 fprintf(f
, "%sCommandLine=%s", prefix
, color
);
426 STRV_FOREACH(i
, cmdline
) {
433 fprintf(f
, "%s", suffix
);
434 } else if (r
!= -ENODATA
)
435 fprintf(f
, "%sCommandLine=%sn/a%s", prefix
, color
, suffix
);
437 if (c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
)
438 fprintf(f
, "%sLabel=%s%s%s", prefix
, color
, c
->label
, suffix
);
439 if (c
->mask
& SD_BUS_CREDS_DESCRIPTION
)
440 fprintf(f
, "%sDescription=%s%s%s", prefix
, color
, c
->description
, suffix
);
442 if (terse
&& (c
->mask
& (SD_BUS_CREDS_SELINUX_CONTEXT
|SD_BUS_CREDS_DESCRIPTION
)))
445 if (c
->mask
& SD_BUS_CREDS_CGROUP
)
446 fprintf(f
, "%sCGroup=%s%s%s", prefix
, color
, c
->cgroup
, suffix
);
448 r
= sd_bus_creds_get_unit(c
, &s
);
450 fprintf(f
, "%sUnit=%s%s%s", prefix
, color
, strna(s
), suffix
);
452 v
= sd_bus_creds_get_slice(c
, &s
);
454 fprintf(f
, "%sSlice=%s%s%s", prefix
, color
, strna(s
), suffix
);
456 q
= sd_bus_creds_get_user_unit(c
, &s
);
458 fprintf(f
, "%sUserUnit=%s%s%s", prefix
, color
, strna(s
), suffix
);
460 w
= sd_bus_creds_get_user_slice(c
, &s
);
462 fprintf(f
, "%sUserSlice=%s%s%s", prefix
, color
, strna(s
), suffix
);
464 z
= sd_bus_creds_get_session(c
, &s
);
466 fprintf(f
, "%sSession=%s%s%s", prefix
, color
, strna(s
), suffix
);
468 if (terse
&& ((c
->mask
& SD_BUS_CREDS_CGROUP
) || r
!= -ENODATA
|| q
!= -ENODATA
|| v
!= -ENODATA
|| w
!= -ENODATA
|| z
!= -ENODATA
))
471 r
= sd_bus_creds_get_audit_login_uid(c
, &audit_loginuid
);
473 fprintf(f
, "%sAuditLoginUID=%s"UID_FMT
"%s", prefix
, color
, audit_loginuid
, suffix
);
474 else if (r
!= -ENODATA
)
475 fprintf(f
, "%sAuditLoginUID=%sn/a%s", prefix
, color
, suffix
);
476 q
= sd_bus_creds_get_audit_session_id(c
, &audit_sessionid
);
478 fprintf(f
, "%sAuditSessionID=%s%"PRIu32
"%s", prefix
, color
, audit_sessionid
, suffix
);
479 else if (q
!= -ENODATA
)
480 fprintf(f
, "%sAuditSessionID=%sn/a%s", prefix
, color
, suffix
);
482 if (terse
&& (r
!= -ENODATA
|| q
!= -ENODATA
))
485 if (c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
)
486 fprintf(f
, "%sUniqueName=%s%s%s", prefix
, color
, c
->unique_name
, suffix
);
488 if (sd_bus_creds_get_well_known_names(c
, &well_known
) >= 0) {
491 fprintf(f
, "%sWellKnownNames=%s", prefix
, color
);
492 STRV_FOREACH(i
, well_known
) {
499 fprintf(f
, "%s", suffix
);
502 if (terse
&& (c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
|| well_known
))
505 dump_capabilities(c
, f
, "EffectiveCapabilities", terse
, sd_bus_creds_has_effective_cap
);
506 dump_capabilities(c
, f
, "PermittedCapabilities", terse
, sd_bus_creds_has_permitted_cap
);
507 dump_capabilities(c
, f
, "InheritableCapabilities", terse
, sd_bus_creds_has_inheritable_cap
);
508 dump_capabilities(c
, f
, "BoundingCapabilities", terse
, sd_bus_creds_has_bounding_cap
);
514 * For details about the file format, see:
516 * http://wiki.wireshark.org/Development/LibpcapFileFormat
519 typedef struct _packed_ pcap_hdr_s
{
520 uint32_t magic_number
; /* magic number */
521 uint16_t version_major
; /* major version number */
522 uint16_t version_minor
; /* minor version number */
523 int32_t thiszone
; /* GMT to local correction */
524 uint32_t sigfigs
; /* accuracy of timestamps */
525 uint32_t snaplen
; /* max length of captured packets, in octets */
526 uint32_t network
; /* data link type */
529 typedef struct _packed_ pcaprec_hdr_s
{
530 uint32_t ts_sec
; /* timestamp seconds */
531 uint32_t ts_usec
; /* timestamp microseconds */
532 uint32_t incl_len
; /* number of octets of packet saved in file */
533 uint32_t orig_len
; /* actual length of packet */
536 int bus_pcap_header(size_t snaplen
, FILE *f
) {
539 .magic_number
= 0xa1b2c3d4U
,
542 .thiszone
= 0, /* UTC */
544 .network
= 231, /* D-Bus */
551 assert((size_t) (uint32_t) snaplen
== snaplen
);
553 hdr
.snaplen
= (uint32_t) snaplen
;
555 fwrite(&hdr
, 1, sizeof(hdr
), f
);
557 return fflush_and_check(f
);
560 int bus_message_pcap_frame(sd_bus_message
*m
, size_t snaplen
, FILE *f
) {
561 struct bus_body_part
*part
;
562 pcaprec_hdr_t hdr
= {};
572 assert((size_t) (uint32_t) snaplen
== snaplen
);
574 if (m
->realtime
!= 0)
575 timeval_store(&tv
, m
->realtime
);
577 assert_se(gettimeofday(&tv
, NULL
) >= 0);
579 hdr
.ts_sec
= tv
.tv_sec
;
580 hdr
.ts_usec
= tv
.tv_usec
;
581 hdr
.orig_len
= BUS_MESSAGE_SIZE(m
);
582 hdr
.incl_len
= MIN(hdr
.orig_len
, snaplen
);
584 /* write the pcap header */
585 fwrite(&hdr
, 1, sizeof(hdr
), f
);
587 /* write the dbus header */
588 w
= MIN(BUS_MESSAGE_BODY_BEGIN(m
), snaplen
);
589 fwrite(m
->header
, 1, w
, f
);
592 /* write the dbus body */
593 MESSAGE_FOREACH_PART(part
, i
, m
) {
597 w
= MIN(part
->size
, snaplen
);
598 fwrite(part
->data
, 1, w
, f
);
602 return fflush_and_check(f
);