2 * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
3 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
4 * Copyright (c) 2017 The strace developers.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "netlink_sock_diag.h"
34 #include "print_fields.h"
36 #include <arpa/inet.h>
38 #include <linux/sock_diag.h>
39 #include <linux/inet_diag.h>
41 #include "xlat/inet_diag_attrs.h"
42 #include "xlat/inet_diag_bytecodes.h"
43 #include "xlat/inet_diag_extended_flags.h"
44 #include "xlat/inet_diag_req_attrs.h"
46 #include "xlat/tcp_states.h"
47 #include "xlat/tcp_state_flags.h"
50 print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
52 PRINT_FIELD_NET_PORT("{", *id, idiag_sport);
53 PRINT_FIELD_NET_PORT(", ", *id, idiag_dport);
54 PRINT_FIELD_INET_ADDR(", ", *id, idiag_src, family);
55 PRINT_FIELD_INET_ADDR(", ", *id, idiag_dst, family);
56 PRINT_FIELD_IFINDEX(", ", *id, idiag_if);
57 PRINT_FIELD_COOKIE(", ", *id, idiag_cookie);
62 decode_inet_addr(struct tcb *const tcp,
63 const kernel_ulong_t addr,
64 const unsigned int len,
75 size = sizeof(addrbuf.a4);
78 size = sizeof(addrbuf.a6);
82 if (!size || len < size) {
84 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
88 if (umoven(tcp, addr, size, &addrbuf) < 0) {
94 print_inet_addr(family, &addrbuf, size, "addr");
98 decode_inet_diag_hostcond(struct tcb *const tcp,
99 const kernel_ulong_t addr,
100 const unsigned int len)
102 struct inet_diag_hostcond cond;
104 if (len < sizeof(cond)) {
105 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
108 if (umove_or_printaddr(tcp, addr, &cond))
111 PRINT_FIELD_XVAL("{", cond, family, addrfams, "AF_???");
112 PRINT_FIELD_U(", ", cond, prefix_len);
113 PRINT_FIELD_U(", ", cond, port);
115 if (len > sizeof(cond)) {
117 decode_inet_addr(tcp, addr + sizeof(cond),
118 len - sizeof(cond), cond.family);
124 print_inet_diag_bc_op(const struct inet_diag_bc_op *const op)
126 PRINT_FIELD_XVAL("{", *op, code, inet_diag_bytecodes,
128 PRINT_FIELD_U(", ", *op, yes);
129 PRINT_FIELD_U(", ", *op, no);
134 decode_inet_diag_markcond(struct tcb *const tcp,
135 const kernel_ulong_t addr,
136 const unsigned int len)
138 struct inet_diag_markcond markcond;
140 if (len < sizeof(markcond))
141 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
142 else if (!umove_or_printaddr(tcp, addr, &markcond)) {
143 PRINT_FIELD_U("{", markcond, mark);
144 PRINT_FIELD_U(", ", markcond, mask);
150 decode_bytecode_data(struct tcb *const tcp,
151 const kernel_ulong_t addr,
152 const unsigned int len,
153 const unsigned char code)
156 case INET_DIAG_BC_S_COND:
157 case INET_DIAG_BC_D_COND:
158 decode_inet_diag_hostcond(tcp, addr, len);
160 case INET_DIAG_BC_DEV_COND: {
163 if (len < sizeof(ifindex))
164 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
165 else if (!umove_or_printaddr(tcp, addr, &ifindex))
166 print_ifindex(ifindex);
169 case INET_DIAG_BC_S_GE:
170 case INET_DIAG_BC_S_LE:
171 case INET_DIAG_BC_D_GE:
172 case INET_DIAG_BC_D_LE: {
173 struct inet_diag_bc_op op;
175 if (len < sizeof(op))
176 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
177 else if (!umove_or_printaddr(tcp, addr, &op))
178 print_inet_diag_bc_op(&op);
181 case INET_DIAG_BC_MARK_COND:
182 decode_inet_diag_markcond(tcp, addr, len);
184 case INET_DIAG_BC_AUTO:
185 case INET_DIAG_BC_JMP:
186 case INET_DIAG_BC_NOP:
188 printstr_ex(tcp, addr, len, QUOTE_FORCE_HEX);
194 decode_inet_diag_bc_op(struct tcb *const tcp,
195 const kernel_ulong_t addr,
196 const unsigned int len,
197 const void *const opaque_data)
199 struct inet_diag_bc_op op;
201 if (len < sizeof(op))
203 if (umove_or_printaddr(tcp, addr, &op))
206 if (len > sizeof(op))
209 print_inet_diag_bc_op(&op);
211 if (len > sizeof(op)) {
213 decode_bytecode_data(tcp, addr + sizeof(op),
214 len - sizeof(op), op.code);
221 static const nla_decoder_t inet_diag_req_nla_decoders[] = {
222 [INET_DIAG_REQ_BYTECODE] = decode_inet_diag_bc_op
226 decode_inet_diag_req_compat(struct tcb *const tcp,
227 const struct nlmsghdr *const nlmsghdr,
228 const uint8_t family,
229 const kernel_ulong_t addr,
230 const unsigned int len)
232 struct inet_diag_req req = { .idiag_family = family };
233 size_t offset = sizeof(req.idiag_family);
234 bool decode_nla = false;
236 PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???");
238 if (len >= sizeof(req)) {
239 if (!umoven_or_printaddr(tcp, addr + offset,
240 sizeof(req) - offset,
241 (void *) &req + offset)) {
242 PRINT_FIELD_U("", req, idiag_src_len);
243 PRINT_FIELD_U(", ", req, idiag_dst_len);
244 PRINT_FIELD_FLAGS(", ", req, idiag_ext,
245 inet_diag_extended_flags,
246 "1<<INET_DIAG_\?\?\?-1");
247 PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
249 PRINT_FIELD_FLAGS(", ", req, idiag_states,
250 tcp_state_flags, "1<<TCP_???");
251 PRINT_FIELD_U(", ", req, idiag_dbs);
258 offset = NLMSG_ALIGN(sizeof(req));
259 if (decode_nla && len > offset) {
261 decode_nlattr(tcp, addr + offset, len - offset,
262 inet_diag_req_attrs, "INET_DIAG_REQ_???",
263 inet_diag_req_nla_decoders,
264 ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
269 decode_inet_diag_req_v2(struct tcb *const tcp,
270 const struct nlmsghdr *const nlmsghdr,
271 const uint8_t family,
272 const kernel_ulong_t addr,
273 const unsigned int len)
275 struct inet_diag_req_v2 req = { .sdiag_family = family };
276 size_t offset = sizeof(req.sdiag_family);
277 bool decode_nla = false;
279 PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
281 if (len >= sizeof(req)) {
282 if (!umoven_or_printaddr(tcp, addr + offset,
283 sizeof(req) - offset,
284 (void *) &req + offset)) {
285 PRINT_FIELD_XVAL("", req, sdiag_protocol,
286 inet_protocols, "IPPROTO_???");
287 PRINT_FIELD_FLAGS(", ", req, idiag_ext,
288 inet_diag_extended_flags,
289 "1<<INET_DIAG_\?\?\?-1");
290 PRINT_FIELD_FLAGS(", ", req, idiag_states,
291 tcp_state_flags, "1<<TCP_???");
292 PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id,
300 offset = NLMSG_ALIGN(sizeof(req));
301 if (decode_nla && len > offset) {
303 decode_nlattr(tcp, addr + offset, len - offset,
304 inet_diag_req_attrs, "INET_DIAG_REQ_???",
305 inet_diag_req_nla_decoders,
306 ARRAY_SIZE(inet_diag_req_nla_decoders), NULL);
310 DECL_NETLINK_DIAG_DECODER(decode_inet_diag_req)
312 if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
313 || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
314 return decode_inet_diag_req_compat(tcp, nlmsghdr,
317 return decode_inet_diag_req_v2(tcp, nlmsghdr,
322 decode_inet_diag_meminfo(struct tcb *const tcp,
323 const kernel_ulong_t addr,
324 const unsigned int len,
325 const void *const opaque_data)
327 struct inet_diag_meminfo minfo;
329 if (len < sizeof(minfo))
331 if (umove_or_printaddr(tcp, addr, &minfo))
334 PRINT_FIELD_U("{", minfo, idiag_rmem);
335 PRINT_FIELD_U(", ", minfo, idiag_wmem);
336 PRINT_FIELD_U(", ", minfo, idiag_fmem);
337 PRINT_FIELD_U(", ", minfo, idiag_tmem);
344 decode_tcpvegas_info(struct tcb *const tcp,
345 const kernel_ulong_t addr,
346 const unsigned int len,
347 const void *const opaque_data)
349 struct tcpvegas_info vegas;
351 if (len < sizeof(vegas))
353 if (umove_or_printaddr(tcp, addr, &vegas))
356 PRINT_FIELD_U("{", vegas, tcpv_enabled);
357 PRINT_FIELD_U(", ", vegas, tcpv_rttcnt);
358 PRINT_FIELD_U(", ", vegas, tcpv_rtt);
359 PRINT_FIELD_U(", ", vegas, tcpv_minrtt);
366 decode_tcp_dctcp_info(struct tcb *const tcp,
367 const kernel_ulong_t addr,
368 const unsigned int len,
369 const void *const opaque_data)
371 struct tcp_dctcp_info dctcp;
373 if (len < sizeof(dctcp))
375 if (umove_or_printaddr(tcp, addr, &dctcp))
378 PRINT_FIELD_U("{", dctcp, dctcp_enabled);
379 PRINT_FIELD_U(", ", dctcp, dctcp_ce_state);
380 PRINT_FIELD_U(", ", dctcp, dctcp_alpha);
381 PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn);
382 PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot);
389 decode_tcp_bbr_info(struct tcb *const tcp,
390 const kernel_ulong_t addr,
391 const unsigned int len,
392 const void *const opaque_data)
394 struct tcp_bbr_info bbr;
396 if (len < sizeof(bbr))
398 if (umove_or_printaddr(tcp, addr, &bbr))
401 PRINT_FIELD_X("{", bbr, bbr_bw_lo);
402 PRINT_FIELD_X(", ", bbr, bbr_bw_hi);
403 PRINT_FIELD_U(", ", bbr, bbr_min_rtt);
404 PRINT_FIELD_U(", ", bbr, bbr_pacing_gain);
405 PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain);
411 static const nla_decoder_t inet_diag_msg_nla_decoders[] = {
412 [INET_DIAG_MEMINFO] = decode_inet_diag_meminfo,
413 [INET_DIAG_INFO] = NULL, /* unimplemented */
414 [INET_DIAG_VEGASINFO] = decode_tcpvegas_info,
415 [INET_DIAG_CONG] = decode_nla_str,
416 [INET_DIAG_TOS] = decode_nla_u8,
417 [INET_DIAG_TCLASS] = decode_nla_u8,
418 [INET_DIAG_SKMEMINFO] = decode_nla_meminfo,
419 [INET_DIAG_SHUTDOWN] = decode_nla_u8,
420 [INET_DIAG_DCTCPINFO] = decode_tcp_dctcp_info,
421 [INET_DIAG_PROTOCOL] = decode_nla_u8,
422 [INET_DIAG_SKV6ONLY] = decode_nla_u8,
423 [INET_DIAG_LOCALS] = NULL, /* unimplemented */
424 [INET_DIAG_PEERS] = NULL, /* unimplemented */
425 [INET_DIAG_PAD] = NULL,
426 [INET_DIAG_MARK] = decode_nla_u32,
427 [INET_DIAG_BBRINFO] = decode_tcp_bbr_info
430 DECL_NETLINK_DIAG_DECODER(decode_inet_diag_msg)
432 struct inet_diag_msg msg = { .idiag_family = family };
433 size_t offset = sizeof(msg.idiag_family);
434 bool decode_nla = false;
436 PRINT_FIELD_XVAL("{", msg, idiag_family, addrfams, "AF_???");
438 if (len >= sizeof(msg)) {
439 if (!umoven_or_printaddr(tcp, addr + offset,
440 sizeof(msg) - offset,
441 (void *) &msg + offset)) {
442 PRINT_FIELD_XVAL("", msg, idiag_state,
443 tcp_states, "TCP_???");
444 PRINT_FIELD_U(", ", msg, idiag_timer);
445 PRINT_FIELD_U(", ", msg, idiag_retrans);
446 PRINT_FIELD_INET_DIAG_SOCKID(", ", msg, id,
448 PRINT_FIELD_U(", ", msg, idiag_expires);
449 PRINT_FIELD_U(", ", msg, idiag_rqueue);
450 PRINT_FIELD_U(", ", msg, idiag_wqueue);
451 PRINT_FIELD_U(", ", msg, idiag_uid);
452 PRINT_FIELD_U(", ", msg, idiag_inode);
459 offset = NLMSG_ALIGN(sizeof(msg));
460 if (decode_nla && len > offset) {
462 decode_nlattr(tcp, addr + offset, len - offset,
463 inet_diag_attrs, "INET_DIAG_???",
464 inet_diag_msg_nla_decoders,
465 ARRAY_SIZE(inet_diag_msg_nla_decoders), NULL);