]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-dump.c
libsystemd: split up into subdirs
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-dump.c
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
22 #include "util.h"
23 #include "capability.h"
24 #include "strv.h"
25 #include "audit.h"
26
27 #include "bus-message.h"
28 #include "bus-internal.h"
29 #include "bus-type.h"
30 #include "bus-dump.h"
31
32 static char *indent(unsigned level) {
33 char *p;
34
35 p = new(char, 2 + level + 1);
36 if (!p)
37 return NULL;
38
39 p[0] = p[1] = ' ';
40 memset(p + 2, '\t', level);
41 p[2 + level] = 0;
42
43 return p;
44 }
45
46 int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
47 unsigned level = 1;
48 int r;
49
50 assert(m);
51
52 if (!f)
53 f = stdout;
54
55 if (with_header) {
56 fprintf(f,
57 "%s%s%sType=%s%s%s Endian=%c Flags=%u Version=%u",
58 m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
59 m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
60 m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", draw_special_char(DRAW_TRIANGULAR_BULLET), ansi_highlight_off(),
61 ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_highlight_off(),
62 m->header->endian,
63 m->header->flags,
64 m->header->version);
65
66 /* Display synthetic message serial number in a more readable
67 * format than (uint32_t) -1 */
68 if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL)
69 fprintf(f, " Cookie=-1");
70 else
71 fprintf(f, " Cookie=%lu", (unsigned long) BUS_MESSAGE_COOKIE(m));
72
73 if (m->reply_cookie != 0)
74 fprintf(f, " ReplyCookie=%lu", (unsigned long) m->reply_cookie);
75
76 fputs("\n", f);
77
78 if (m->sender)
79 fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_highlight_off());
80 if (m->destination)
81 fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_highlight_off());
82 if (m->path)
83 fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_highlight_off());
84 if (m->interface)
85 fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_highlight_off());
86 if (m->member)
87 fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_highlight_off());
88
89 if (m->sender || m->destination || m->path || m->interface || m->member)
90 fputs("\n", f);
91
92 if (sd_bus_error_is_set(&m->error))
93 fprintf(f,
94 " ErrorName=%s%s%s"
95 " ErrorMessage=%s\"%s\"%s\n",
96 ansi_highlight_red(), strna(m->error.name), ansi_highlight_off(),
97 ansi_highlight_red(), strna(m->error.message), ansi_highlight_off());
98
99 if (m->monotonic != 0)
100 fprintf(f, " Monotonic=%llu", (unsigned long long) m->monotonic);
101 if (m->realtime != 0)
102 fprintf(f, " Realtime=%llu", (unsigned long long) m->realtime);
103
104 if (m->monotonic != 0 || m->realtime != 0)
105 fputs("\n", f);
106
107 bus_creds_dump(&m->creds, f);
108 }
109
110 r = sd_bus_message_rewind(m, true);
111 if (r < 0) {
112 log_error("Failed to rewind: %s", strerror(-r));
113 return r;
114 }
115
116 fprintf(f, " MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
117
118 for (;;) {
119 _cleanup_free_ char *prefix = NULL;
120 const char *contents = NULL;
121 char type;
122 union {
123 uint8_t u8;
124 uint16_t u16;
125 int16_t s16;
126 uint32_t u32;
127 int32_t s32;
128 uint64_t u64;
129 int64_t s64;
130 double d64;
131 const char *string;
132 int i;
133 } basic;
134
135 r = sd_bus_message_peek_type(m, &type, &contents);
136 if (r < 0) {
137 log_error("Failed to peek type: %s", strerror(-r));
138 return r;
139 }
140
141 if (r == 0) {
142 if (level <= 1)
143 break;
144
145 r = sd_bus_message_exit_container(m);
146 if (r < 0) {
147 log_error("Failed to exit container: %s", strerror(-r));
148 return r;
149 }
150
151 level--;
152
153 prefix = indent(level);
154 if (!prefix)
155 return log_oom();
156
157 fprintf(f, "%s};\n", prefix);
158 continue;
159 }
160
161 prefix = indent(level);
162 if (!prefix)
163 return log_oom();
164
165 if (bus_type_is_container(type) > 0) {
166 r = sd_bus_message_enter_container(m, type, contents);
167 if (r < 0) {
168 log_error("Failed to enter container: %s", strerror(-r));
169 return r;
170 }
171
172 if (type == SD_BUS_TYPE_ARRAY)
173 fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
174 else if (type == SD_BUS_TYPE_VARIANT)
175 fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
176 else if (type == SD_BUS_TYPE_STRUCT)
177 fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
178 else if (type == SD_BUS_TYPE_DICT_ENTRY)
179 fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
180
181 level ++;
182
183 continue;
184 }
185
186 r = sd_bus_message_read_basic(m, type, &basic);
187 if (r < 0) {
188 log_error("Failed to get basic: %s", strerror(-r));
189 return r;
190 }
191
192 assert(r > 0);
193
194 switch (type) {
195
196 case SD_BUS_TYPE_BYTE:
197 fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_highlight_off());
198 break;
199
200 case SD_BUS_TYPE_BOOLEAN:
201 fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_highlight_off());
202 break;
203
204 case SD_BUS_TYPE_INT16:
205 fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_highlight_off());
206 break;
207
208 case SD_BUS_TYPE_UINT16:
209 fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_highlight_off());
210 break;
211
212 case SD_BUS_TYPE_INT32:
213 fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_highlight_off());
214 break;
215
216 case SD_BUS_TYPE_UINT32:
217 fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_highlight_off());
218 break;
219
220 case SD_BUS_TYPE_INT64:
221 fprintf(f, "%sINT64 %s%lli%s;\n", prefix, ansi_highlight(), (long long) basic.s64, ansi_highlight_off());
222 break;
223
224 case SD_BUS_TYPE_UINT64:
225 fprintf(f, "%sUINT64 %s%llu%s;\n", prefix, ansi_highlight(), (unsigned long long) basic.u64, ansi_highlight_off());
226 break;
227
228 case SD_BUS_TYPE_DOUBLE:
229 fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_highlight_off());
230 break;
231
232 case SD_BUS_TYPE_STRING:
233 fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
234 break;
235
236 case SD_BUS_TYPE_OBJECT_PATH:
237 fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
238 break;
239
240 case SD_BUS_TYPE_SIGNATURE:
241 fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_highlight_off());
242 break;
243
244 case SD_BUS_TYPE_UNIX_FD:
245 fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_highlight_off());
246 break;
247
248 default:
249 assert_not_reached("Unknown basic type.");
250 }
251 }
252
253 fprintf(f, " };\n\n");
254 return 0;
255 }
256
257 static void dump_capabilities(
258 sd_bus_creds *c,
259 FILE *f,
260 const char *name,
261 int (*has)(sd_bus_creds *c, int capability)) {
262
263 unsigned long i, last_cap;
264 unsigned n = 0;
265 int r;
266
267 assert(c);
268 assert(f);
269 assert(name);
270 assert(has);
271
272 i = 0;
273 r = has(c, i);
274 if (r < 0)
275 return;
276
277 fprintf(f, " %s=", name);
278 last_cap = cap_last_cap();
279
280 for (;;) {
281 if (r > 0) {
282 _cleanup_cap_free_charp_ char *t;
283
284 if (n > 0)
285 fputc(' ', f);
286 if (n % 4 == 3)
287 fputs("\n ", f);
288
289 t = cap_to_name(i);
290 fprintf(f, "%s", t);
291 n++;
292 }
293
294 i++;
295
296 if (i > last_cap)
297 break;
298
299 r = has(c, i);
300 }
301
302 fputs("\n", f);
303 }
304
305 int bus_creds_dump(sd_bus_creds *c, FILE *f) {
306 bool audit_sessionid_is_set = false, audit_loginuid_is_set = false;
307 const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL;
308 uid_t owner, audit_loginuid;
309 uint32_t audit_sessionid;
310 char **cmdline = NULL, **well_known = NULL;
311 int r;
312
313 assert(c);
314
315 if (!f)
316 f = stdout;
317
318 if (c->mask & SD_BUS_CREDS_PID)
319 fprintf(f, " PID=%lu", (unsigned long) c->pid);
320 if (c->mask & SD_BUS_CREDS_PID_STARTTIME)
321 fprintf(f, " PIDStartTime=%llu", (unsigned long long) c->pid_starttime);
322 if (c->mask & SD_BUS_CREDS_TID)
323 fprintf(f, " TID=%lu", (unsigned long) c->tid);
324 if (c->mask & SD_BUS_CREDS_UID)
325 fprintf(f, " UID=%lu", (unsigned long) c->uid);
326 r = sd_bus_creds_get_owner_uid(c, &owner);
327 if (r >= 0)
328 fprintf(f, " OwnerUID=%lu", (unsigned long) owner);
329 if (c->mask & SD_BUS_CREDS_GID)
330 fprintf(f, " GID=%lu", (unsigned long) c->gid);
331
332 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)
333 fputs("\n", f);
334
335 if (c->mask & SD_BUS_CREDS_EXE)
336 fprintf(f, " Exe=%s", c->exe);
337 if (c->mask & SD_BUS_CREDS_COMM)
338 fprintf(f, " Comm=%s", c->comm);
339 if (c->mask & SD_BUS_CREDS_TID_COMM)
340 fprintf(f, " TIDComm=%s", c->tid_comm);
341 if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
342 fprintf(f, " Label=%s", c->label);
343
344 if (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_SELINUX_CONTEXT))
345 fputs("\n", f);
346
347 if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) {
348 char **i;
349
350 fputs(" CommandLine={", f);
351 STRV_FOREACH(i, cmdline) {
352 if (i != cmdline)
353 fputc(' ', f);
354
355 fputs(*i, f);
356 }
357
358 fputs("}\n", f);
359 }
360
361 if (c->mask & SD_BUS_CREDS_CGROUP)
362 fprintf(f, " CGroup=%s", c->cgroup);
363 sd_bus_creds_get_unit(c, &u);
364 if (u)
365 fprintf(f, " Unit=%s", u);
366 sd_bus_creds_get_user_unit(c, &uu);
367 if (uu)
368 fprintf(f, " UserUnit=%s", uu);
369 sd_bus_creds_get_slice(c, &sl);
370 if (sl)
371 fprintf(f, " Slice=%s", sl);
372 sd_bus_creds_get_session(c, &s);
373 if (s)
374 fprintf(f, " Session=%s", s);
375
376 if ((c->mask & SD_BUS_CREDS_CGROUP) || u || uu || sl || s)
377 fputs("\n", f);
378
379 if (sd_bus_creds_get_audit_login_uid(c, &audit_loginuid) >= 0) {
380 audit_loginuid_is_set = true;
381 fprintf(f, " AuditLoginUID=%lu", (unsigned long) audit_loginuid);
382 }
383 if (sd_bus_creds_get_audit_session_id(c, &audit_sessionid) >= 0) {
384 audit_sessionid_is_set = true;
385 fprintf(f, " AuditSessionID=%lu", (unsigned long) audit_sessionid);
386 }
387
388 if (audit_loginuid_is_set || audit_sessionid_is_set)
389 fputs("\n", f);
390
391 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
392 fprintf(f, " UniqueName=%s", c->unique_name);
393
394 if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
395 char **i;
396
397 fputs(" WellKnownNames={", f);
398 STRV_FOREACH(i, well_known) {
399 if (i != well_known)
400 fputc(' ', f);
401
402 fputs(*i, f);
403 }
404
405 fputc('}', f);
406 }
407
408 if (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known)
409 fputc('\n', f);
410
411 dump_capabilities(c, f, "EffectiveCapabilities", sd_bus_creds_has_effective_cap);
412 dump_capabilities(c, f, "PermittedCapabilities", sd_bus_creds_has_permitted_cap);
413 dump_capabilities(c, f, "InheritableCapabilities", sd_bus_creds_has_inheritable_cap);
414 dump_capabilities(c, f, "BoundingCapabilities", sd_bus_creds_has_bounding_cap);
415
416 return 0;
417 }