]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-dump.c
shared: add terminal-util.[ch]
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-dump.c
CommitLineData
3db0e46b
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
3db0e46b
LP
22#include "util.h"
23#include "capability.h"
24#include "strv.h"
1f70b087 25#include "macro.h"
2822da4f 26#include "cap-list.h"
6482f626 27#include "formats-util.h"
288a74cc 28#include "terminal-util.h"
3db0e46b
LP
29
30#include "bus-message.h"
31#include "bus-internal.h"
32#include "bus-type.h"
33#include "bus-dump.h"
34
d55192ad 35static char *indent(unsigned level, unsigned flags) {
f8cfb5f5 36 char *p;
d55192ad 37 unsigned n, i = 0;
f8cfb5f5 38
d55192ad
LP
39 n = 0;
40
41 if (flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY && level > 0)
42 level -= 1;
43
44 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER)
45 n += 2;
46
47 p = new(char, n + level*8 + 1);
f8cfb5f5
LP
48 if (!p)
49 return NULL;
50
d55192ad
LP
51 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
52 p[i++] = ' ';
53 p[i++] = ' ';
54 }
55
56 memset(p + i, ' ', level*8);
57 p[i + level*8] = 0;
f8cfb5f5
LP
58
59 return p;
60}
61
d55192ad 62int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
3db0e46b
LP
63 unsigned level = 1;
64 int r;
3db0e46b
LP
65
66 assert(m);
67
68 if (!f)
69 f = stdout;
70
d55192ad 71 if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
3db0e46b 72 fprintf(f,
1fa2f38f 73 "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64,
f8cfb5f5
LP
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(),
3db0e46b 77 ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
f8cfb5f5 78 m->header->endian,
3db0e46b 79 m->header->flags,
ca7b42c8 80 m->header->version,
1fa2f38f 81 m->priority);
a009c158
LS
82
83 /* Display synthetic message serial number in a more readable
84 * format than (uint32_t) -1 */
693eb9a2
LP
85 if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL)
86 fprintf(f, " Cookie=-1");
a009c158 87 else
42c4ebcb 88 fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m));
3db0e46b 89
693eb9a2 90 if (m->reply_cookie != 0)
42c4ebcb 91 fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie);
3db0e46b
LP
92
93 fputs("\n", f);
94
95 if (m->sender)
96 fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
97 if (m->destination)
98 fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
99 if (m->path)
100 fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
101 if (m->interface)
102 fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
103 if (m->member)
104 fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
105
106 if (m->sender || m->destination || m->path || m->interface || m->member)
107 fputs("\n", f);
108
109 if (sd_bus_error_is_set(&m->error))
110 fprintf(f,
111 " ErrorName=%s%s%s"
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());
115
3db0e46b 116 if (m->monotonic != 0)
de0671ee 117 fprintf(f, " Monotonic="USEC_FMT, m->monotonic);
3db0e46b 118 if (m->realtime != 0)
de0671ee 119 fprintf(f, " Realtime="USEC_FMT, m->realtime);
6a0e376c 120 if (m->seqnum != 0)
de0671ee 121 fprintf(f, " SequenceNumber=%"PRIu64, m->seqnum);
3db0e46b 122
6a0e376c 123 if (m->monotonic != 0 || m->realtime != 0 || m->seqnum != 0)
3db0e46b
LP
124 fputs("\n", f);
125
d0b2babf 126 bus_creds_dump(&m->creds, f, true);
3db0e46b
LP
127 }
128
d55192ad 129 r = sd_bus_message_rewind(m, !(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY));
23bbb0de
MS
130 if (r < 0)
131 return log_error_errno(r, "Failed to rewind: %m");
3db0e46b 132
ee04388a
LP
133 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
134 _cleanup_free_ char *prefix = NULL;
135
136 prefix = indent(0, flags);
137 if (!prefix)
138 return log_oom();
139
140 fprintf(f, "%sMESSAGE \"%s\" {\n", prefix, strempty(m->root_container.signature));
141 }
3db0e46b 142
f168c273 143 for (;;) {
3db0e46b
LP
144 _cleanup_free_ char *prefix = NULL;
145 const char *contents = NULL;
146 char type;
147 union {
148 uint8_t u8;
149 uint16_t u16;
150 int16_t s16;
151 uint32_t u32;
152 int32_t s32;
153 uint64_t u64;
154 int64_t s64;
155 double d64;
156 const char *string;
157 int i;
158 } basic;
159
160 r = sd_bus_message_peek_type(m, &type, &contents);
23bbb0de
MS
161 if (r < 0)
162 return log_error_errno(r, "Failed to peek type: %m");
3db0e46b
LP
163
164 if (r == 0) {
165 if (level <= 1)
166 break;
167
168 r = sd_bus_message_exit_container(m);
23bbb0de
MS
169 if (r < 0)
170 return log_error_errno(r, "Failed to exit container: %m");
3db0e46b
LP
171
172 level--;
173
d55192ad 174 prefix = indent(level, flags);
3db0e46b
LP
175 if (!prefix)
176 return log_oom();
177
178 fprintf(f, "%s};\n", prefix);
179 continue;
180 }
181
d55192ad 182 prefix = indent(level, flags);
3db0e46b
LP
183 if (!prefix)
184 return log_oom();
185
186 if (bus_type_is_container(type) > 0) {
187 r = sd_bus_message_enter_container(m, type, contents);
23bbb0de
MS
188 if (r < 0)
189 return log_error_errno(r, "Failed to enter container: %m");
3db0e46b
LP
190
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);
199
200 level ++;
201
202 continue;
203 }
204
205 r = sd_bus_message_read_basic(m, type, &basic);
23bbb0de
MS
206 if (r < 0)
207 return log_error_errno(r, "Failed to get basic: %m");
3db0e46b
LP
208
209 assert(r > 0);
210
211 switch (type) {
212
213 case SD_BUS_TYPE_BYTE:
214 fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
215 break;
216
217 case SD_BUS_TYPE_BOOLEAN:
5232c42e 218 fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_highlight_off());
3db0e46b
LP
219 break;
220
221 case SD_BUS_TYPE_INT16:
222 fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
223 break;
224
225 case SD_BUS_TYPE_UINT16:
226 fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
227 break;
228
229 case SD_BUS_TYPE_INT32:
230 fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
231 break;
232
233 case SD_BUS_TYPE_UINT32:
234 fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
235 break;
236
237 case SD_BUS_TYPE_INT64:
de0671ee 238 fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_highlight_off());
3db0e46b
LP
239 break;
240
241 case SD_BUS_TYPE_UINT64:
de0671ee 242 fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_highlight_off());
3db0e46b
LP
243 break;
244
245 case SD_BUS_TYPE_DOUBLE:
246 fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
247 break;
248
249 case SD_BUS_TYPE_STRING:
250 fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
251 break;
252
253 case SD_BUS_TYPE_OBJECT_PATH:
254 fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
255 break;
256
257 case SD_BUS_TYPE_SIGNATURE:
258 fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
259 break;
260
261 case SD_BUS_TYPE_UNIX_FD:
262 fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
263 break;
264
265 default:
266 assert_not_reached("Unknown basic type.");
267 }
268 }
269
ee04388a
LP
270 if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
271 _cleanup_free_ char *prefix = NULL;
272
273 prefix = indent(0, flags);
274 if (!prefix)
275 return log_oom();
276
277 fprintf(f, "%s};\n\n", prefix);
278 }
d55192ad 279
3db0e46b
LP
280 return 0;
281}
5b12334d
LP
282
283static void dump_capabilities(
284 sd_bus_creds *c,
285 FILE *f,
286 const char *name,
d0b2babf 287 bool terse,
5b12334d
LP
288 int (*has)(sd_bus_creds *c, int capability)) {
289
290 unsigned long i, last_cap;
291 unsigned n = 0;
292 int r;
293
294 assert(c);
295 assert(f);
296 assert(name);
297 assert(has);
298
299 i = 0;
300 r = has(c, i);
301 if (r < 0)
302 return;
303
d0b2babf 304 fprintf(f, "%s%s=%s", terse ? " " : "", name, terse ? "" : ansi_highlight());
5b12334d
LP
305 last_cap = cap_last_cap();
306
307 for (;;) {
308 if (r > 0) {
5ce70e5b 309
5b12334d
LP
310 if (n > 0)
311 fputc(' ', f);
312 if (n % 4 == 3)
d0b2babf 313 fprintf(f, terse ? "\n " : "\n ");
5b12334d 314
2822da4f 315 fprintf(f, "%s", strna(capability_to_name(i)));
5b12334d
LP
316 n++;
317 }
318
319 i++;
320
321 if (i > last_cap)
322 break;
323
324 r = has(c, i);
325 }
326
327 fputs("\n", f);
d0b2babf
LP
328
329 if (!terse)
330 fputs(ansi_highlight_off(), f);
5b12334d
LP
331}
332
d0b2babf 333int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
5b12334d
LP
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;
49b832c5 338 char **cmdline = NULL, **well_known = NULL;
d0b2babf 339 const char *prefix, *color, *suffix;
5b12334d
LP
340 int r;
341
342 assert(c);
343
344 if (!f)
345 f = stdout;
346
d0b2babf
LP
347 if (terse) {
348 prefix = " ";
349 suffix = "";
350 color = "";
351 } else {
352 const char *off;
353
354 prefix = "";
355 color = ansi_highlight();
356
357 off = ansi_highlight_off();
63c372cb 358 suffix = strjoina(off, "\n");
d0b2babf
LP
359 }
360
5b12334d 361 if (c->mask & SD_BUS_CREDS_PID)
d0b2babf 362 fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix);
5b12334d 363 if (c->mask & SD_BUS_CREDS_TID)
d0b2babf 364 fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
705a415f 365
32802361 366 if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID))))
705a415f
LP
367 fputs("\n", f);
368
5b12334d 369 if (c->mask & SD_BUS_CREDS_UID)
d0b2babf 370 fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix);
705a415f
LP
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);
5b12334d
LP
377 r = sd_bus_creds_get_owner_uid(c, &owner);
378 if (r >= 0)
d0b2babf 379 fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix);
5b12334d 380 if (c->mask & SD_BUS_CREDS_GID)
d0b2babf 381 fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix);
705a415f
LP
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);
388
02581590
LP
389 if (c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
390 unsigned i;
391
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);
396 }
397
705a415f 398 if (terse && ((c->mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
02581590
LP
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))
5b12334d
LP
401 fputs("\n", f);
402
5b12334d 403 if (c->mask & SD_BUS_CREDS_COMM)
d0b2babf 404 fprintf(f, "%sComm=%s%s%s", prefix, color, c->comm, suffix);
5b12334d 405 if (c->mask & SD_BUS_CREDS_TID_COMM)
d0b2babf 406 fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix);
5cf4f2d1
LP
407 if (c->mask & SD_BUS_CREDS_EXE)
408 fprintf(f, "%sExe=%s%s%s", prefix, color, c->exe, suffix);
14008e4e 409
d0b2babf 410 if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)))
14008e4e
LP
411 fputs("\n", f);
412
5b12334d
LP
413 if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
414 char **i;
415
d0b2babf 416 fprintf(f, "%sCommandLine=%s", prefix, color);
5b12334d
LP
417 STRV_FOREACH(i, cmdline) {
418 if (i != cmdline)
419 fputc(' ', f);
420
421 fputs(*i, f);
422 }
423
d0b2babf 424 fprintf(f, "%s", suffix);
5b12334d
LP
425 }
426
5cf4f2d1
LP
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);
431
432 if (terse && (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION)))
433 fputs("\n", f);
434
5b12334d 435 if (c->mask & SD_BUS_CREDS_CGROUP)
d0b2babf 436 fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix);
c7fbd996 437 (void) sd_bus_creds_get_unit(c, &u);
5b12334d 438 if (u)
d0b2babf 439 fprintf(f, "%sUnit=%s%s%s", prefix, color, u, suffix);
c7fbd996 440 (void) sd_bus_creds_get_user_unit(c, &uu);
5b12334d 441 if (uu)
d0b2babf 442 fprintf(f, "%sUserUnit=%s%s%s", prefix, color, uu, suffix);
c7fbd996 443 (void) sd_bus_creds_get_slice(c, &sl);
5b12334d 444 if (sl)
d0b2babf 445 fprintf(f, "%sSlice=%s%s%s", prefix, color, sl, suffix);
c7fbd996 446 (void) sd_bus_creds_get_session(c, &s);
5b12334d 447 if (s)
d0b2babf 448 fprintf(f, "%sSession=%s%s%s", prefix, color, s, suffix);
5b12334d 449
d0b2babf 450 if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s))
5b12334d
LP
451 fputs("\n", f);
452
453 if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
454 audit_loginuid_is_set = true;
d0b2babf 455 fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix);
5b12334d
LP
456 }
457 if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
458 audit_sessionid_is_set = true;
d0b2babf 459 fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix);
5b12334d
LP
460 }
461
d0b2babf 462 if (terse && (audit_loginuid_is_set || audit_sessionid_is_set))
5b12334d
LP
463 fputs("\n", f);
464
49b832c5 465 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
d0b2babf 466 fprintf(f, "%sUniqueName=%s%s%s", prefix, color, c->unique_name, suffix);
49b832c5
LP
467
468 if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
469 char **i;
470
d0b2babf 471 fprintf(f, "%sWellKnownNames=%s", prefix, color);
49b832c5
LP
472 STRV_FOREACH(i, well_known) {
473 if (i != well_known)
474 fputc(' ', f);
475
476 fputs(*i, f);
477 }
478
d0b2babf 479 fprintf(f, "%s", suffix);
49b832c5
LP
480 }
481
d0b2babf 482 if (terse && (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known))
3310dfd5
LP
483 fputc('\n', f);
484
d0b2babf
LP
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);
5b12334d
LP
489
490 return 0;
491}
1f70b087
LP
492
493/*
494 * For details about the file format, see:
495 *
496 * http://wiki.wireshark.org/Development/LibpcapFileFormat
497 */
498
499typedef 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 */
507} pcap_hdr_t ;
508
509typedef 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 */
514} pcaprec_hdr_t;
515
516int bus_pcap_header(size_t snaplen, FILE *f) {
517
518 pcap_hdr_t hdr = {
519 .magic_number = 0xa1b2c3d4U,
520 .version_major = 2,
521 .version_minor = 4,
522 .thiszone = 0, /* UTC */
523 .sigfigs = 0,
524 .network = 231, /* D-Bus */
525 };
526
527 if (!f)
528 f = stdout;
529
530 assert(snaplen > 0);
531 assert((size_t) (uint32_t) snaplen == snaplen);
532
533 hdr.snaplen = (uint32_t) snaplen;
534
535 fwrite(&hdr, 1, sizeof(hdr), f);
536 fflush(f);
537
538 return 0;
539}
540
541int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
542 struct bus_body_part *part;
543 pcaprec_hdr_t hdr = {};
544 struct timeval tv;
545 unsigned i;
546 size_t w;
547
548 if (!f)
549 f = stdout;
550
551 assert(m);
552 assert(snaplen > 0);
553 assert((size_t) (uint32_t) snaplen == snaplen);
554
555 if (m->realtime != 0)
556 timeval_store(&tv, m->realtime);
557 else
558 assert_se(gettimeofday(&tv, NULL) >= 0);
559
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);
564
565 /* write the pcap header */
566 fwrite(&hdr, 1, sizeof(hdr), f);
567
568 /* write the dbus header */
569 w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen);
570 fwrite(m->header, 1, w, f);
571 snaplen -= w;
572
573 /* write the dbus body */
574 MESSAGE_FOREACH_PART(part, i, m) {
575 if (snaplen <= 0)
576 break;
577
578 w = MIN(part->size, snaplen);
579 fwrite(part->data, 1, w, f);
580 snaplen -= w;
581 }
582
583 fflush(f);
584
585 return 0;
586}