1 /*
2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3 * Copyright (c) 2017-2021 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8
9 #include "defs.h"
10 #include <sys/socket.h>
11
12 #ifndef AF_SMC
13 # define XLAT_MACROS_ONLY
14 # include "xlat/addrfams.h"
15 # undef XLAT_MACROS_ONLY
16 #endif
17
18 #include "netlink.h"
19 #include "netlink_sock_diag.h"
20 #include "nlattr.h"
21
22 #include <arpa/inet.h>
23 #include <linux/smc_diag.h>
24
25 #include "xlat/smc_decl_codes.h"
26 #include "xlat/smc_diag_attrs.h"
27 #include "xlat/smc_diag_extended_flags.h"
28 #include "xlat/smc_diag_mode.h"
29 #include "xlat/smc_link_group_roles.h"
30 #include "xlat/smc_states.h"
31 #include "xlat/sock_shutdown_flags.h"
32
33 DECL_NETLINK_DIAG_DECODER(decode_smc_diag_req)
34 {
35 struct smc_diag_req req = { .diag_family = family };
36 const size_t offset = sizeof(req.diag_family);
37
38 tprint_struct_begin();
39 PRINT_FIELD_XVAL(req, diag_family, addrfams, "AF_???");
40 tprint_struct_next();
41
42 if (len >= sizeof(req)) {
43 if (!umoven_or_printaddr(tcp, addr + offset,
44 sizeof(req) - offset,
45 (void *) &req + offset)) {
46 PRINT_FIELD_FLAGS(req, diag_ext,
47 smc_diag_extended_flags,
48 "1<<SMC_DIAG_\?\?\?-1");
49 /*
50 * AF_SMC protocol family socket handler
51 * keeping the AF_INET sock address.
52 */
53 tprint_struct_next();
54 PRINT_FIELD_INET_DIAG_SOCKID(req, id, AF_INET);
55 }
56 } else
57 tprint_more_data_follows();
58 tprint_struct_end();
59 }
60
61 static void
62 print_smc_diag_cursor(const struct smc_diag_cursor *const cursor)
63 {
64 tprint_struct_begin();
65 PRINT_FIELD_U(*cursor, reserved);
66 tprint_struct_next();
67 PRINT_FIELD_U(*cursor, wrap);
68 tprint_struct_next();
69 PRINT_FIELD_U(*cursor, count);
70 tprint_struct_end();
71 }
72
73 static bool
74 decode_smc_diag_conninfo(struct tcb *const tcp,
75 const kernel_ulong_t addr,
76 const unsigned int len,
77 const void *const opaque_data)
78 {
79 struct smc_diag_conninfo cinfo;
80
81 if (len < sizeof(cinfo))
82 return false;
83 if (umove_or_printaddr(tcp, addr, &cinfo))
84 return true;
85
86 tprint_struct_begin();
87 PRINT_FIELD_U(cinfo, token);
88 tprint_struct_next();
89 PRINT_FIELD_U(cinfo, sndbuf_size);
90 tprint_struct_next();
91 PRINT_FIELD_U(cinfo, rmbe_size);
92 tprint_struct_next();
93 PRINT_FIELD_U(cinfo, peer_rmbe_size);
94 tprint_struct_next();
95 PRINT_FIELD_OBJ_PTR(cinfo, rx_prod, print_smc_diag_cursor);
96 tprint_struct_next();
97 PRINT_FIELD_OBJ_PTR(cinfo, rx_cons, print_smc_diag_cursor);
98 tprint_struct_next();
99 PRINT_FIELD_OBJ_PTR(cinfo, tx_prod, print_smc_diag_cursor);
100 tprint_struct_next();
101 PRINT_FIELD_OBJ_PTR(cinfo, tx_cons, print_smc_diag_cursor);
102 tprint_struct_next();
103 PRINT_FIELD_0X(cinfo, rx_prod_flags);
104 tprint_struct_next();
105 PRINT_FIELD_0X(cinfo, rx_conn_state_flags);
106 tprint_struct_next();
107 PRINT_FIELD_0X(cinfo, tx_prod_flags);
108 tprint_struct_next();
109 PRINT_FIELD_0X(cinfo, tx_conn_state_flags);
110 tprint_struct_next();
111 PRINT_FIELD_OBJ_PTR(cinfo, tx_prep, print_smc_diag_cursor);
112 tprint_struct_next();
113 PRINT_FIELD_OBJ_PTR(cinfo, tx_sent, print_smc_diag_cursor);
114 tprint_struct_next();
115 PRINT_FIELD_OBJ_PTR(cinfo, tx_fin, print_smc_diag_cursor);
116 tprint_struct_end();
117
118 return true;
119 }
120
121 static bool
122 print_smc_diag_linkinfo_array_member(struct tcb *tcp, void *elem_buf,
123 size_t elem_size, void *data)
124 {
125 const struct smc_diag_linkinfo *const p = elem_buf;
126 tprint_struct_begin();
127 PRINT_FIELD_U(*p, link_id);
128 tprint_struct_next();
129 PRINT_FIELD_CSTRING(*p, ibname);
130 tprint_struct_next();
131 PRINT_FIELD_U(*p, ibport);
132 tprint_struct_next();
133 PRINT_FIELD_CSTRING(*p, gid);
134 tprint_struct_next();
135 PRINT_FIELD_CSTRING(*p, peer_gid);
136 tprint_struct_end();
137 return true;
138 }
139
140 static bool
141 decode_smc_diag_lgrinfo(struct tcb *const tcp,
142 const kernel_ulong_t addr,
143 const unsigned int len,
144 const void *const opaque_data)
145 {
146 struct smc_diag_lgrinfo linfo;
147
148 if (len < sizeof(linfo))
149 return false;
150 if (umove_or_printaddr(tcp, addr, &linfo))
151 return true;
152
153 tprint_struct_begin();
154 PRINT_FIELD_ARRAY(linfo, lnk, tcp,
155 print_smc_diag_linkinfo_array_member);
156 tprint_struct_next();
157 PRINT_FIELD_XVAL(linfo, role, smc_link_group_roles, "SMC_???");
158 tprint_struct_end();
159
160 return true;
161 }
162
163 static bool
164 decode_smc_diag_shutdown(struct tcb *const tcp,
165 const kernel_ulong_t addr,
166 const unsigned int len,
167 const void *const opaque_data)
168 {
169 const struct decode_nla_xlat_opts opts = {
170 sock_shutdown_flags, "???_SHUTDOWN",
171 .size = 1,
172 };
173
174 return decode_nla_flags(tcp, addr, len, &opts);
175 }
176
177 static bool
178 decode_smc_diag_dmbinfo(struct tcb *const tcp,
179 const kernel_ulong_t addr,
180 const unsigned int len,
181 const void *const opaque_data)
182 {
183 struct smcd_diag_dmbinfo dinfo;
184
185 if (len < sizeof(dinfo))
186 return false;
187 if (umove_or_printaddr(tcp, addr, &dinfo))
188 return true;
189
190 tprint_struct_begin();
191 PRINT_FIELD_U(dinfo, linkid);
192 tprint_struct_next();
193 PRINT_FIELD_X(dinfo, peer_gid);
194 tprint_struct_next();
195 PRINT_FIELD_X(dinfo, my_gid);
196 tprint_struct_next();
197 PRINT_FIELD_X(dinfo, token);
198 tprint_struct_next();
199 PRINT_FIELD_X(dinfo, peer_token);
200 tprint_struct_end();
201
202 return true;
203 }
204 static bool
205 decode_smc_diag_fallback(struct tcb *const tcp,
206 const kernel_ulong_t addr,
207 const unsigned int len,
208 const void *const opaque_data)
209 {
210 struct smc_diag_fallback fb;
211
212 if (len < sizeof(fb))
213 return false;
214 if (umove_or_printaddr(tcp, addr, &fb))
215 return true;
216
217 /*
218 * We print them verbose since they are defined in a non-UAPI header,
219 * net/smc/smc_clc.h
220 */
221 tprint_struct_begin();
222 PRINT_FIELD_XVAL_VERBOSE(fb, reason, smc_decl_codes,
223 "SMC_CLC_DECL_???");
224 tprint_struct_next();
225 PRINT_FIELD_XVAL_VERBOSE(fb, peer_diagnosis, smc_decl_codes,
226 "SMC_CLC_DECL_???");
227 tprint_struct_end();
228
229 return true;
230 }
231
232 static const nla_decoder_t smc_diag_msg_nla_decoders[] = {
233 [SMC_DIAG_CONNINFO] = decode_smc_diag_conninfo,
234 [SMC_DIAG_LGRINFO] = decode_smc_diag_lgrinfo,
235 [SMC_DIAG_SHUTDOWN] = decode_smc_diag_shutdown,
236 [SMC_DIAG_DMBINFO] = decode_smc_diag_dmbinfo,
237 [SMC_DIAG_FALLBACK] = decode_smc_diag_fallback,
238 };
239
240 DECL_NETLINK_DIAG_DECODER(decode_smc_diag_msg)
241 {
242 struct smc_diag_msg msg = { .diag_family = family };
243 size_t offset = sizeof(msg.diag_family);
244 bool decode_nla = false;
245
246 tprint_struct_begin();
247 PRINT_FIELD_XVAL(msg, diag_family, addrfams, "AF_???");
248 tprint_struct_next();
249
250 if (len >= sizeof(msg)) {
251 if (!umoven_or_printaddr(tcp, addr + offset,
252 sizeof(msg) - offset,
253 (void *) &msg + offset)) {
254 PRINT_FIELD_XVAL(msg, diag_state,
255 smc_states, "SMC_???");
256 tprint_struct_next();
257 PRINT_FIELD_XVAL(msg, diag_fallback,
258 smc_diag_mode, "SMC_DIAG_MODE_???");
259 tprint_struct_next();
260 PRINT_FIELD_U(msg, diag_shutdown);
261 /*
262 * AF_SMC protocol family socket handler
263 * keeping the AF_INET sock address.
264 */
265 tprint_struct_next();
266 PRINT_FIELD_INET_DIAG_SOCKID(msg, id, AF_INET);
267 tprint_struct_next();
268 PRINT_FIELD_U(msg, diag_uid);
269 tprint_struct_next();
270 PRINT_FIELD_U(msg, diag_inode);
271 decode_nla = true;
272 }
273 } else
274 tprint_more_data_follows();
275 tprint_struct_end();
276
277 offset = NLMSG_ALIGN(sizeof(msg));
278 if (decode_nla && len > offset) {
279 tprint_array_next();
280 decode_nlattr(tcp, addr + offset, len - offset,
281 smc_diag_attrs, "SMC_DIAG_???",
282 smc_diag_msg_nla_decoders,
283 ARRAY_SIZE(smc_diag_msg_nla_decoders), NULL);
284 }
285 }