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.
7 * SPDX-License-Identifier: LGPL-2.1-or-later
12 #include "netlink_sock_diag.h"
14 #include "print_fields.h"
16 #include <arpa/inet.h>
18 #include <linux/sock_diag.h>
19 #include <linux/inet_diag.h>
21 #include "xlat/inet_diag_attrs.h"
22 #include "xlat/inet_diag_bytecodes.h"
23 #include "xlat/inet_diag_extended_flags.h"
24 #include "xlat/inet_diag_req_attrs.h"
26 #include "xlat/tcp_states.h"
27 #include "xlat/tcp_state_flags.h"
30 print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
32 PRINT_FIELD_NET_PORT("{", *id, idiag_sport);
33 PRINT_FIELD_NET_PORT(", ", *id, idiag_dport);
34 PRINT_FIELD_INET_ADDR(", ", *id, idiag_src, family);
35 PRINT_FIELD_INET_ADDR(", ", *id, idiag_dst, family);
36 PRINT_FIELD_IFINDEX(", ", *id, idiag_if);
37 PRINT_FIELD_COOKIE(", ", *id, idiag_cookie);
42 decode_inet_diag_hostcond(struct tcb *const tcp,
43 const kernel_ulong_t addr,
44 const unsigned int len)
46 struct inet_diag_hostcond cond;
48 if (len < sizeof(cond)) {
49 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
52 if (umove_or_printaddr(tcp, addr, &cond))
55 PRINT_FIELD_XVAL("{", cond, family, addrfams, "AF_???");
56 PRINT_FIELD_U(", ", cond, prefix_len);
57 PRINT_FIELD_U(", ", cond, port);
59 if (len > sizeof(cond)) {
61 decode_inet_addr(tcp, addr + sizeof(cond),
62 len - sizeof(cond), cond.family, "addr");
68 print_inet_diag_bc_op(const struct inet_diag_bc_op *const op)
70 PRINT_FIELD_XVAL("{", *op, code, inet_diag_bytecodes,
72 PRINT_FIELD_U(", ", *op, yes);
73 PRINT_FIELD_U(", ", *op, no);
78 decode_inet_diag_markcond(struct tcb *const tcp,
79 const kernel_ulong_t addr,
80 const unsigned int len)
82 struct inet_diag_markcond markcond;
84 if (len < sizeof(markcond))
85 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
86 else if (!umove_or_printaddr(tcp, addr, &markcond)) {
87 PRINT_FIELD_U("{", markcond, mark);
88 PRINT_FIELD_U(", ", markcond, mask);
94 decode_bytecode_data(struct tcb *const tcp,
95 const kernel_ulong_t addr,
96 const unsigned int len,
97 const unsigned char code)
100 case INET_DIAG_BC_S_COND:
101 case INET_DIAG_BC_D_COND:
102 decode_inet_diag_hostcond(tcp, addr, len);
104 case INET_DIAG_BC_DEV_COND: {
107 if (len < sizeof(ifindex))
108 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
109 else if (!umove_or_printaddr(tcp, addr, &ifindex))
110 print_ifindex(ifindex);
113 case INET_DIAG_BC_S_GE:
114 case INET_DIAG_BC_S_LE:
115 case INET_DIAG_BC_D_GE:
116 case INET_DIAG_BC_D_LE: {
117 struct inet_diag_bc_op op;
119 if (len < sizeof(op))
120 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
121 else if (!umove_or_printaddr(tcp, addr, &op))
122 print_inet_diag_bc_op(&op);
125 case INET_DIAG_BC_MARK_COND:
126 decode_inet_diag_markcond(tcp, addr, len);
128 case INET_DIAG_BC_AUTO:
129 case INET_DIAG_BC_JMP:
130 case INET_DIAG_BC_NOP:
132 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
138 decode_inet_diag_bc_op(struct tcb *const tcp,
139 const kernel_ulong_t addr,
140 const unsigned int len,
141 const void *const opaque_data)
143 struct inet_diag_bc_op op;
145 if (len < sizeof(op))
147 if (umove_or_printaddr(tcp, addr, &op))
150 if (len > sizeof(op))
153 print_inet_diag_bc_op(&op);
155 if (len > sizeof(op)) {
157 decode_bytecode_data(tcp, addr + sizeof(op),
158 len - sizeof(op), op.code);
165 static const nla_decoder_t inet_diag_req_nla_decoders[] = {
166 [INET_DIAG_REQ_BYTECODE] = decode_inet_diag_bc_op
170 decode_inet_diag_req_compat(struct tcb *const tcp,
171 const struct nlmsghdr *const nlmsghdr,
172 const uint8_t family,
173 const kernel_ulong_t addr,
174 const unsigned int len)
176 struct inet_diag_req req = { .idiag_family = family };
177 size_t offset = sizeof(req.idiag_family);
178 bool decode_nla = false;
180 PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???");
182 if (len >= sizeof(req)) {
183 if (!umoven_or_printaddr(tcp, addr + offset,
184 sizeof(req) - offset,
185 (char *) &req + offset)) {
186 PRINT_FIELD_U("", req, idiag_src_len);
187 PRINT_FIELD_U(", ", req, idiag_dst_len);
188 PRINT_FIELD_FLAGS(", ", req, idiag_ext,
189 inet_diag_extended_flags,
190 "1<<INET_DIAG_\?\?\?-1");
191 PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
193 PRINT_FIELD_FLAGS(", ", req, idiag_states,
194 tcp_state_flags, "1<<TCP_???");
195 PRINT_FIELD_U(", ", req, idiag_dbs);
202 offset = NLMSG_ALIGN(sizeof(req));
203 if (decode_nla && len > offset) {
205 decode_nlattr(tcp, addr + offset, len - offset,
206 inet_diag_req_attrs, "INET_DIAG_REQ_???",
207 inet_diag_req_nla_decoders,
208 ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
213 decode_inet_diag_req_v2(struct tcb *const tcp,
214 const struct nlmsghdr *const nlmsghdr,
215 const uint8_t family,
216 const kernel_ulong_t addr,
217 const unsigned int len)
219 struct inet_diag_req_v2 req = { .sdiag_family = family };
220 size_t offset = sizeof(req.sdiag_family);
221 bool decode_nla = false;
223 PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
225 if (len >= sizeof(req)) {
226 if (!umoven_or_printaddr(tcp, addr + offset,
227 sizeof(req) - offset,
228 (char *) &req + offset)) {
229 PRINT_FIELD_XVAL("", req, sdiag_protocol,
230 inet_protocols, "IPPROTO_???");
231 PRINT_FIELD_FLAGS(", ", req, idiag_ext,
232 inet_diag_extended_flags,
233 "1<<INET_DIAG_\?\?\?-1");
234 PRINT_FIELD_FLAGS(", ", req, idiag_states,
235 tcp_state_flags, "1<<TCP_???");
236 PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
244 offset = NLMSG_ALIGN(sizeof(req));
245 if (decode_nla && len > offset) {
247 decode_nlattr(tcp, addr + offset, len - offset,
248 inet_diag_req_attrs, "INET_DIAG_REQ_???",
249 inet_diag_req_nla_decoders,
250 ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
254 DECL_NETLINK_DIAG_DECODER(decode_inet_diag_req)
256 if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
257 || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
258 decode_inet_diag_req_compat(tcp, nlmsghdr, family, addr, len);
260 decode_inet_diag_req_v2(tcp, nlmsghdr, family, addr, len);
264 decode_inet_diag_meminfo(struct tcb *const tcp,
265 const kernel_ulong_t addr,
266 const unsigned int len,
267 const void *const opaque_data)
269 struct inet_diag_meminfo minfo;
271 if (len < sizeof(minfo))
273 if (umove_or_printaddr(tcp, addr, &minfo))
276 PRINT_FIELD_U("{", minfo, idiag_rmem);
277 PRINT_FIELD_U(", ", minfo, idiag_wmem);
278 PRINT_FIELD_U(", ", minfo, idiag_fmem);
279 PRINT_FIELD_U(", ", minfo, idiag_tmem);
286 decode_tcpvegas_info(struct tcb *const tcp,
287 const kernel_ulong_t addr,
288 const unsigned int len,
289 const void *const opaque_data)
291 struct tcpvegas_info vegas;
293 if (len < sizeof(vegas))
295 if (umove_or_printaddr(tcp, addr, &vegas))
298 PRINT_FIELD_U("{", vegas, tcpv_enabled);
299 PRINT_FIELD_U(", ", vegas, tcpv_rttcnt);
300 PRINT_FIELD_U(", ", vegas, tcpv_rtt);
301 PRINT_FIELD_U(", ", vegas, tcpv_minrtt);
308 decode_tcp_dctcp_info(struct tcb *const tcp,
309 const kernel_ulong_t addr,
310 const unsigned int len,
311 const void *const opaque_data)
313 struct tcp_dctcp_info dctcp;
315 if (len < sizeof(dctcp))
317 if (umove_or_printaddr(tcp, addr, &dctcp))
320 PRINT_FIELD_U("{", dctcp, dctcp_enabled);
321 PRINT_FIELD_U(", ", dctcp, dctcp_ce_state);
322 PRINT_FIELD_U(", ", dctcp, dctcp_alpha);
323 PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn);
324 PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot);
331 decode_tcp_bbr_info(struct tcb *const tcp,
332 const kernel_ulong_t addr,
333 const unsigned int len,
334 const void *const opaque_data)
336 struct tcp_bbr_info bbr;
338 if (len < sizeof(bbr))
340 if (umove_or_printaddr(tcp, addr, &bbr))
343 PRINT_FIELD_X("{", bbr, bbr_bw_lo);
344 PRINT_FIELD_X(", ", bbr, bbr_bw_hi);
345 PRINT_FIELD_U(", ", bbr, bbr_min_rtt);
346 PRINT_FIELD_U(", ", bbr, bbr_pacing_gain);
347 PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain);
353 static const nla_decoder_t inet_diag_msg_nla_decoders[] = {
354 [INET_DIAG_MEMINFO] = decode_inet_diag_meminfo,
355 [INET_DIAG_INFO] = NULL, /* unimplemented */
356 [INET_DIAG_VEGASINFO] = decode_tcpvegas_info,
357 [INET_DIAG_CONG] = decode_nla_str,
358 [INET_DIAG_TOS] = decode_nla_u8,
359 [INET_DIAG_TCLASS] = decode_nla_u8,
360 [INET_DIAG_SKMEMINFO] = decode_nla_meminfo,
361 [INET_DIAG_SHUTDOWN] = decode_nla_u8,
362 [INET_DIAG_DCTCPINFO] = decode_tcp_dctcp_info,
363 [INET_DIAG_PROTOCOL] = decode_nla_u8,
364 [INET_DIAG_SKV6ONLY] = decode_nla_u8,
365 [INET_DIAG_LOCALS] = NULL, /* unimplemented */
366 [INET_DIAG_PEERS] = NULL, /* unimplemented */
367 [INET_DIAG_PAD] = NULL,
368 [INET_DIAG_MARK] = decode_nla_u32,
369 [INET_DIAG_BBRINFO] = decode_tcp_bbr_info,
370 [INET_DIAG_CLASS_ID] = decode_nla_u32
373 DECL_NETLINK_DIAG_DECODER(decode_inet_diag_msg)
375 struct inet_diag_msg msg = { .idiag_family = family };
376 size_t offset = sizeof(msg.idiag_family);
377 bool decode_nla = false;
379 PRINT_FIELD_XVAL("{", msg, idiag_family, addrfams, "AF_???");
381 if (len >= sizeof(msg)) {
382 if (!umoven_or_printaddr(tcp, addr + offset,
383 sizeof(msg) - offset,
384 (char *) &msg + offset)) {
385 PRINT_FIELD_XVAL("", msg, idiag_state,
386 tcp_states, "TCP_???");
387 PRINT_FIELD_U(", ", msg, idiag_timer);
388 PRINT_FIELD_U(", ", msg, idiag_retrans);
389 PRINT_FIELD_INET_DIAG_SOCKID(", ", msg, id,
391 PRINT_FIELD_U(", ", msg, idiag_expires);
392 PRINT_FIELD_U(", ", msg, idiag_rqueue);
393 PRINT_FIELD_U(", ", msg, idiag_wqueue);
394 PRINT_FIELD_U(", ", msg, idiag_uid);
395 PRINT_FIELD_U(", ", msg, idiag_inode);
402 offset = NLMSG_ALIGN(sizeof(msg));
403 if (decode_nla && len > offset) {
405 decode_nlattr(tcp, addr + offset, len - offset,
406 inet_diag_attrs, "INET_DIAG_???",
407 inet_diag_msg_nla_decoders,
408 ARRAY_SIZE(inet_diag_msg_nla_decoders), NULL);