]> granicus.if.org Git - strace/blob - netlink_netlink_diag.c
tests: add support of multi-line diagnostics to check_h
[strace] / netlink_netlink_diag.c
1 /*
2  * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4  * Copyright (c) 2017-2018 The strace developers.
5  * All rights reserved.
6  *
7  * SPDX-License-Identifier: LGPL-2.1-or-later
8  */
9
10 #include "defs.h"
11 #include "netlink.h"
12 #include "netlink_sock_diag.h"
13 #include "nlattr.h"
14 #include "print_fields.h"
15
16 #include <linux/sock_diag.h>
17 #include <linux/netlink_diag.h>
18
19 #include "xlat/netlink_diag_attrs.h"
20 #include "xlat/netlink_diag_show.h"
21 #include "xlat/netlink_socket_flags.h"
22 #include "xlat/netlink_states.h"
23
24 DECL_NETLINK_DIAG_DECODER(decode_netlink_diag_req)
25 {
26         struct netlink_diag_req req = { .sdiag_family = family };
27         const size_t offset = sizeof(req.sdiag_family);
28
29         PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
30         tprints(", ");
31         if (len >= sizeof(req)) {
32                 if (!umoven_or_printaddr(tcp, addr + offset,
33                                          sizeof(req) - offset,
34                                          (char *) &req + offset)) {
35                         if (NDIAG_PROTO_ALL == req.sdiag_protocol)
36                                 tprintf("%s=%s",
37                                         "sdiag_protocol", "NDIAG_PROTO_ALL");
38                         else
39                                 PRINT_FIELD_XVAL("", req, sdiag_protocol,
40                                                  netlink_protocols,
41                                                  "NETLINK_???");
42                         PRINT_FIELD_U(", ", req, ndiag_ino);
43                         PRINT_FIELD_FLAGS(", ", req, ndiag_show,
44                                           netlink_diag_show, "NDIAG_SHOW_???");
45                         PRINT_FIELD_COOKIE(", ", req, ndiag_cookie);
46                 }
47         } else
48                 tprints("...");
49         tprints("}");
50 }
51
52 static bool
53 print_group(struct tcb *const tcp,
54             void *const elem_buf,
55             const size_t elem_size,
56             void *const opaque_data)
57 {
58         if (elem_size < sizeof(kernel_ulong_t))
59                 tprintf("%#0*x", (int) elem_size * 2 + 2,
60                         *(unsigned int *) elem_buf);
61         else
62                 tprintf("%#0*" PRI_klx, (int) elem_size * 2 + 2,
63                         *(kernel_ulong_t *) elem_buf);
64
65         return true;
66 }
67
68 static bool
69 decode_netlink_diag_groups(struct tcb *const tcp,
70                            const kernel_ulong_t addr,
71                            const unsigned int len,
72                            const void *const opaque_data)
73 {
74         kernel_ulong_t buf;
75         const size_t nmemb = len / current_wordsize;
76
77         if (!nmemb)
78                 return false;
79
80         print_array(tcp, addr, nmemb, &buf, current_wordsize,
81                     tfetch_mem, print_group, 0);
82
83         return true;
84 }
85
86 static bool
87 decode_netlink_diag_ring(struct tcb *const tcp,
88                          const kernel_ulong_t addr,
89                          const unsigned int len,
90                          const void *const opaque_data)
91 {
92         struct netlink_diag_ring ndr;
93
94         if (len < sizeof(ndr))
95                 return false;
96         if (umove_or_printaddr(tcp, addr, &ndr))
97                 return true;
98
99         PRINT_FIELD_U("{", ndr, ndr_block_size);
100         PRINT_FIELD_U(", ", ndr, ndr_block_nr);
101         PRINT_FIELD_U(", ", ndr, ndr_frame_size);
102         PRINT_FIELD_U(", ", ndr, ndr_frame_nr);
103         tprints("}");
104
105         return true;
106 }
107
108 static bool
109 decode_netlink_diag_flags(struct tcb *const tcp,
110                           const kernel_ulong_t addr,
111                           const unsigned int len,
112                           const void *const opaque_data)
113 {
114         uint32_t flags;
115
116         if (len < sizeof(flags))
117                 return false;
118         if (umove_or_printaddr(tcp, addr, &flags))
119                 return true;
120
121         printflags(netlink_socket_flags, flags, "NDIAG_FLAG_???");
122
123         return true;
124 }
125
126 static const nla_decoder_t netlink_diag_msg_nla_decoders[] = {
127         [NETLINK_DIAG_MEMINFO]  = decode_nla_meminfo,
128         [NETLINK_DIAG_GROUPS]   = decode_netlink_diag_groups,
129         [NETLINK_DIAG_RX_RING]  = decode_netlink_diag_ring,
130         [NETLINK_DIAG_TX_RING]  = decode_netlink_diag_ring,
131         [NETLINK_DIAG_FLAGS]    = decode_netlink_diag_flags
132 };
133
134 DECL_NETLINK_DIAG_DECODER(decode_netlink_diag_msg)
135 {
136         struct netlink_diag_msg msg = { .ndiag_family = family };
137         size_t offset = sizeof(msg.ndiag_family);
138         bool decode_nla = false;
139
140         PRINT_FIELD_XVAL("{", msg, ndiag_family, addrfams, "AF_???");
141         tprints(", ");
142         if (len >= sizeof(msg)) {
143                 if (!umoven_or_printaddr(tcp, addr + offset,
144                                          sizeof(msg) - offset,
145                                          (char *) &msg + offset)) {
146                         PRINT_FIELD_XVAL("", msg, ndiag_type,
147                                          socktypes, "SOCK_???");
148                         PRINT_FIELD_XVAL(", ", msg, ndiag_protocol,
149                                          netlink_protocols, "NETLINK_???");
150                         PRINT_FIELD_XVAL(", ", msg, ndiag_state,
151                                          netlink_states, "NETLINK_???");
152                         PRINT_FIELD_U(", ", msg, ndiag_portid);
153                         PRINT_FIELD_U(", ", msg, ndiag_dst_portid);
154                         PRINT_FIELD_U(", ", msg, ndiag_dst_group);
155                         PRINT_FIELD_U(", ", msg, ndiag_ino);
156                         PRINT_FIELD_COOKIE(", ", msg, ndiag_cookie);
157                         decode_nla = true;
158                 }
159         } else
160                 tprints("...");
161         tprints("}");
162
163         offset = NLMSG_ALIGN(sizeof(msg));
164         if (decode_nla && len > offset) {
165                 tprints(", ");
166                 decode_nlattr(tcp, addr + offset, len - offset,
167                               netlink_diag_attrs, "NETLINK_DIAG_???",
168                               netlink_diag_msg_nla_decoders,
169                               ARRAY_SIZE(netlink_diag_msg_nla_decoders), NULL);
170         }
171 }