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