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.
33 #include "print_fields.h"
35 #include <arpa/inet.h>
36 #include <linux/filter.h>
38 #include <linux/inet_diag.h>
39 #include <linux/netlink_diag.h>
40 #include <linux/packet_diag.h>
42 # include <linux/smc_diag.h>
44 #include <linux/sock_diag.h>
45 #include <linux/unix_diag.h>
47 #include "xlat/inet_diag_attrs.h"
48 #include "xlat/inet_diag_extended_flags.h"
49 #include "xlat/inet_diag_req_attrs.h"
51 #include "xlat/tcp_states.h"
52 #include "xlat/tcp_state_flags.h"
54 #include "xlat/netlink_diag_attrs.h"
55 #include "xlat/netlink_diag_show.h"
56 #include "xlat/netlink_socket_flags.h"
57 #include "xlat/netlink_states.h"
59 #include "xlat/packet_diag_attrs.h"
60 #include "xlat/packet_diag_info_flags.h"
61 #include "xlat/packet_diag_show.h"
64 # include "xlat/smc_diag_attrs.h"
65 # include "xlat/smc_diag_extended_flags.h"
66 # include "xlat/smc_states.h"
69 #include "xlat/unix_diag_attrs.h"
70 #include "xlat/unix_diag_show.h"
73 decode_family(struct tcb *const tcp, const uint8_t family,
74 const kernel_ulong_t addr, const kernel_ulong_t len)
77 printxval(addrfams, family, "AF_???");
78 if (len > sizeof(family)) {
80 printstr_ex(tcp, addr + sizeof(family),
81 len - sizeof(family), QUOTE_FORCE_HEX);
87 decode_unix_diag_req(struct tcb *const tcp,
88 const struct nlmsghdr *const nlmsghdr,
90 const kernel_ulong_t addr,
91 const kernel_ulong_t len)
93 struct unix_diag_req req = { .sdiag_family = family };
94 const size_t offset = sizeof(req.sdiag_family);
96 PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
98 if (len >= sizeof(req)) {
99 if (!umoven_or_printaddr(tcp, addr + offset,
100 sizeof(req) - offset,
101 (void *) &req + offset)) {
102 PRINT_FIELD_U("", req, sdiag_protocol);
103 PRINT_FIELD_FLAGS(", ", req, udiag_states,
104 tcp_state_flags, "1<<TCP_???");
105 PRINT_FIELD_U(", ", req, udiag_ino);
106 PRINT_FIELD_FLAGS(", ", req, udiag_show,
107 unix_diag_show, "UDIAG_SHOW_???");
108 PRINT_FIELD_COOKIE(", ", req, udiag_cookie);
116 print_meminfo(struct tcb *const tcp,
117 void *const elem_buf,
118 const size_t elem_size,
119 void *const opaque_data)
121 tprintf("%" PRIu32, *(uint32_t *) elem_buf);
127 decode_meminfo(struct tcb *const tcp,
128 const kernel_ulong_t addr,
129 const kernel_ulong_t len,
130 const void *const opaque_data)
133 size_t nmemb = len / sizeof(mem);
138 if (nmemb > SK_MEMINFO_VARS)
139 nmemb = SK_MEMINFO_VARS;
141 print_array(tcp, addr, nmemb, &mem, sizeof(mem),
142 umoven_or_printaddr, print_meminfo, 0);
148 decode_unix_diag_vfs(struct tcb *const tcp,
149 const kernel_ulong_t addr,
150 const kernel_ulong_t len,
151 const void *const opaque_data)
153 struct unix_diag_vfs uv;
155 if (len < sizeof(uv))
157 if (umove_or_printaddr(tcp, addr, &uv))
160 tprints("{udiag_vfs_dev=");
161 print_dev_t(uv.udiag_vfs_dev);
162 PRINT_FIELD_U(", ", uv, udiag_vfs_ino);
169 print_inode(struct tcb *const tcp,
170 void *const elem_buf,
171 const size_t elem_size,
172 void *const opaque_data)
174 tprintf("%" PRIu32, *(uint32_t *) elem_buf);
180 decode_unix_diag_inode(struct tcb *const tcp,
181 const kernel_ulong_t addr,
182 const kernel_ulong_t len,
183 const void *const opaque_data)
186 const size_t nmemb = len / sizeof(inode);
191 print_array(tcp, addr, nmemb, &inode, sizeof(inode),
192 umoven_or_printaddr, print_inode, 0);
198 decode_unix_diag_rqlen(struct tcb *const tcp,
199 const kernel_ulong_t addr,
200 const kernel_ulong_t len,
201 const void *const opaque_data)
203 struct unix_diag_rqlen rql;
205 if (len < sizeof(rql))
207 if (umove_or_printaddr(tcp, addr, &rql))
210 PRINT_FIELD_U("{", rql, udiag_rqueue);
211 PRINT_FIELD_U(", ", rql, udiag_wqueue);
217 static const nla_decoder_t unix_diag_msg_nla_decoders[] = {
218 [UNIX_DIAG_NAME] = decode_nla_str,
219 [UNIX_DIAG_VFS] = decode_unix_diag_vfs,
220 [UNIX_DIAG_PEER] = decode_nla_u32,
221 [UNIX_DIAG_ICONS] = decode_unix_diag_inode,
222 [UNIX_DIAG_RQLEN] = decode_unix_diag_rqlen,
223 [UNIX_DIAG_MEMINFO] = decode_meminfo,
224 [UNIX_DIAG_SHUTDOWN] = decode_nla_u8
228 decode_unix_diag_msg(struct tcb *const tcp,
229 const struct nlmsghdr *const nlmsghdr,
230 const uint8_t family,
231 const kernel_ulong_t addr,
232 const kernel_ulong_t len)
234 struct unix_diag_msg msg = { .udiag_family = family };
235 size_t offset = sizeof(msg.udiag_family);
236 bool decode_nla = false;
238 PRINT_FIELD_XVAL("{", msg, udiag_family, addrfams, "AF_???");
240 if (len >= sizeof(msg)) {
241 if (!umoven_or_printaddr(tcp, addr + offset,
242 sizeof(msg) - offset,
243 (void *) &msg + offset)) {
244 PRINT_FIELD_XVAL("", msg, udiag_type,
245 socktypes, "SOCK_???");
246 PRINT_FIELD_XVAL(", ", msg, udiag_state,
247 tcp_states, "TCP_???");
248 PRINT_FIELD_U(", ", msg, udiag_ino);
249 PRINT_FIELD_COOKIE(", ", msg, udiag_cookie);
256 offset = NLMSG_ALIGN(sizeof(msg));
257 if (decode_nla && len > offset) {
259 decode_nlattr(tcp, addr + offset, len - offset,
260 unix_diag_attrs, "UNIX_DIAG_???",
261 unix_diag_msg_nla_decoders,
262 ARRAY_SIZE(unix_diag_msg_nla_decoders), NULL);
267 decode_netlink_diag_req(struct tcb *const tcp,
268 const struct nlmsghdr *const nlmsghdr,
269 const uint8_t family,
270 const kernel_ulong_t addr,
271 const kernel_ulong_t len)
273 struct netlink_diag_req req = { .sdiag_family = family };
274 const size_t offset = sizeof(req.sdiag_family);
276 PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
278 if (len >= sizeof(req)) {
279 if (!umoven_or_printaddr(tcp, addr + offset,
280 sizeof(req) - offset,
281 (void *) &req + offset)) {
282 if (NDIAG_PROTO_ALL == req.sdiag_protocol)
284 "sdiag_protocol", "NDIAG_PROTO_ALL");
286 PRINT_FIELD_XVAL("", req, sdiag_protocol,
289 PRINT_FIELD_U(", ", req, ndiag_ino);
290 PRINT_FIELD_FLAGS(", ", req, ndiag_show,
291 netlink_diag_show, "NDIAG_SHOW_???");
292 PRINT_FIELD_COOKIE(", ", req, ndiag_cookie);
300 print_group(struct tcb *const tcp,
301 void *const elem_buf,
302 const size_t elem_size,
303 void *const opaque_data)
305 if (elem_size < sizeof(kernel_ulong_t))
306 tprintf("%#0*x", (int) elem_size * 2 + 2,
307 *(unsigned int *) elem_buf);
309 tprintf("%#0*" PRI_klx, (int) elem_size * 2 + 2,
310 *(kernel_ulong_t *) elem_buf);
316 decode_netlink_diag_groups(struct tcb *const tcp,
317 const kernel_ulong_t addr,
318 const kernel_ulong_t len,
319 const void *const opaque_data)
322 const size_t nmemb = len / current_wordsize;
327 print_array(tcp, addr, nmemb, &buf, current_wordsize,
328 umoven_or_printaddr, print_group, 0);
334 decode_netlink_diag_ring(struct tcb *const tcp,
335 const kernel_ulong_t addr,
336 const kernel_ulong_t len,
337 const void *const opaque_data)
339 struct netlink_diag_ring ndr;
341 if (len < sizeof(ndr))
343 if (umove_or_printaddr(tcp, addr, &ndr))
346 PRINT_FIELD_U("{", ndr, ndr_block_size);
347 PRINT_FIELD_U(", ", ndr, ndr_block_nr);
348 PRINT_FIELD_U(", ", ndr, ndr_frame_size);
349 PRINT_FIELD_U(", ", ndr, ndr_frame_nr);
356 decode_netlink_diag_flags(struct tcb *const tcp,
357 const kernel_ulong_t addr,
358 const kernel_ulong_t len,
359 const void *const opaque_data)
363 if (len < sizeof(flags))
365 if (umove_or_printaddr(tcp, addr, &flags))
368 printflags(netlink_socket_flags, flags, "NDIAG_FLAG_???");
373 static const nla_decoder_t netlink_diag_msg_nla_decoders[] = {
374 [NETLINK_DIAG_MEMINFO] = decode_meminfo,
375 [NETLINK_DIAG_GROUPS] = decode_netlink_diag_groups,
376 [NETLINK_DIAG_RX_RING] = decode_netlink_diag_ring,
377 [NETLINK_DIAG_TX_RING] = decode_netlink_diag_ring,
378 [NETLINK_DIAG_FLAGS] = decode_netlink_diag_flags
382 decode_netlink_diag_msg(struct tcb *const tcp,
383 const struct nlmsghdr *const nlmsghdr,
384 const uint8_t family,
385 const kernel_ulong_t addr,
386 const kernel_ulong_t len)
388 struct netlink_diag_msg msg = { .ndiag_family = family };
389 size_t offset = sizeof(msg.ndiag_family);
390 bool decode_nla = false;
392 PRINT_FIELD_XVAL("{", msg, ndiag_family, addrfams, "AF_???");
394 if (len >= sizeof(msg)) {
395 if (!umoven_or_printaddr(tcp, addr + offset,
396 sizeof(msg) - offset,
397 (void *) &msg + offset)) {
398 PRINT_FIELD_XVAL("", msg, ndiag_type,
399 socktypes, "SOCK_???");
400 PRINT_FIELD_XVAL(", ", msg, ndiag_protocol,
401 netlink_protocols, "NETLINK_???");
402 PRINT_FIELD_XVAL(", ", msg, ndiag_state,
403 netlink_states, "NETLINK_???");
404 PRINT_FIELD_U(", ", msg, ndiag_portid);
405 PRINT_FIELD_U(", ", msg, ndiag_dst_portid);
406 PRINT_FIELD_U(", ", msg, ndiag_dst_group);
407 PRINT_FIELD_U(", ", msg, ndiag_ino);
408 PRINT_FIELD_COOKIE(", ", msg, ndiag_cookie);
415 offset = NLA_ALIGN(sizeof(msg));
416 if (decode_nla && len > offset) {
418 decode_nlattr(tcp, addr + offset, len - offset,
419 netlink_diag_attrs, "NETLINK_DIAG_???",
420 netlink_diag_msg_nla_decoders,
421 ARRAY_SIZE(netlink_diag_msg_nla_decoders), NULL);
426 decode_packet_diag_req(struct tcb *const tcp,
427 const struct nlmsghdr *const nlmsghdr,
428 const uint8_t family,
429 const kernel_ulong_t addr,
430 const kernel_ulong_t len)
432 struct packet_diag_req req = { .sdiag_family = family };
433 const size_t offset = sizeof(req.sdiag_family);
435 PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
437 if (len >= sizeof(req)) {
438 if (!umoven_or_printaddr(tcp, addr + offset,
439 sizeof(req) - offset,
440 (void *) &req + offset)) {
441 PRINT_FIELD_XVAL("", req, sdiag_protocol,
442 ethernet_protocols, "ETH_P_???");
443 PRINT_FIELD_U(", ", req, pdiag_ino);
444 PRINT_FIELD_FLAGS(", ", req, pdiag_show,
445 packet_diag_show, "PACKET_SHOW_???");
446 PRINT_FIELD_COOKIE(", ", req, pdiag_cookie);
454 decode_packet_diag_info(struct tcb *const tcp,
455 const kernel_ulong_t addr,
456 const kernel_ulong_t len,
457 const void *const opaque_data)
459 struct packet_diag_info pinfo;
461 if (len < sizeof(pinfo))
463 if (umove_or_printaddr(tcp, addr, &pinfo))
466 PRINT_FIELD_U("{", pinfo, pdi_index);
467 PRINT_FIELD_U(", ", pinfo, pdi_version);
468 PRINT_FIELD_U(", ", pinfo, pdi_reserve);
469 PRINT_FIELD_U(", ", pinfo, pdi_copy_thresh);
470 PRINT_FIELD_U(", ", pinfo, pdi_tstamp);
471 PRINT_FIELD_FLAGS(", ", pinfo, pdi_flags,
472 packet_diag_info_flags, "PDI_???");
479 print_packet_diag_mclist(struct tcb *const tcp, void *const elem_buf,
480 const size_t elem_size, void *const opaque_data)
482 struct packet_diag_mclist *dml = elem_buf;
483 uint16_t alen = dml->pdmc_alen > sizeof(dml->pdmc_addr) ?
484 sizeof(dml->pdmc_addr) : dml->pdmc_alen;
486 PRINT_FIELD_IFINDEX("{", *dml, pdmc_index);
487 PRINT_FIELD_U(", ", *dml, pdmc_count);
488 PRINT_FIELD_U(", ", *dml, pdmc_type);
489 PRINT_FIELD_U(", ", *dml, pdmc_alen);
490 PRINT_FIELD_QUOTED_STRING(", ", *dml, pdmc_addr, alen, QUOTE_FORCE_HEX);
497 decode_packet_diag_mclist(struct tcb *const tcp,
498 const kernel_ulong_t addr,
499 const kernel_ulong_t len,
500 const void *const opaque_data)
502 struct packet_diag_mclist dml;
503 const size_t nmemb = len / sizeof(dml);
508 print_array(tcp, addr, nmemb, &dml, sizeof(dml),
509 umoven_or_printaddr, print_packet_diag_mclist, 0);
515 decode_packet_diag_ring(struct tcb *const tcp,
516 const kernel_ulong_t addr,
517 const kernel_ulong_t len,
518 const void *const opaque_data)
520 struct packet_diag_ring pdr;
522 if (len < sizeof(pdr))
524 if (umove_or_printaddr(tcp, addr, &pdr))
527 PRINT_FIELD_U("{", pdr, pdr_block_size);
528 PRINT_FIELD_U(", ", pdr, pdr_block_nr);
529 PRINT_FIELD_U(", ", pdr, pdr_frame_size);
530 PRINT_FIELD_U(", ", pdr, pdr_frame_nr);
531 PRINT_FIELD_U(", ", pdr, pdr_retire_tmo);
532 PRINT_FIELD_U(", ", pdr, pdr_sizeof_priv);
533 PRINT_FIELD_U(", ", pdr, pdr_features);
540 decode_packet_diag_filter(struct tcb *const tcp,
541 const kernel_ulong_t addr,
542 const kernel_ulong_t len,
543 const void *const opaque_data)
545 const kernel_ulong_t nmemb = len / sizeof(struct sock_filter);
546 if (!nmemb || (unsigned short) nmemb != nmemb)
549 print_sock_fprog(tcp, addr, nmemb);
554 static const nla_decoder_t packet_diag_msg_nla_decoders[] = {
555 [PACKET_DIAG_INFO] = decode_packet_diag_info,
556 [PACKET_DIAG_MCLIST] = decode_packet_diag_mclist,
557 [PACKET_DIAG_RX_RING] = decode_packet_diag_ring,
558 [PACKET_DIAG_TX_RING] = decode_packet_diag_ring,
559 [PACKET_DIAG_FANOUT] = decode_nla_u32,
560 [PACKET_DIAG_UID] = decode_nla_u32,
561 [PACKET_DIAG_MEMINFO] = decode_meminfo,
562 [PACKET_DIAG_FILTER] = decode_packet_diag_filter
566 decode_packet_diag_msg(struct tcb *const tcp,
567 const struct nlmsghdr *const nlmsghdr,
568 const uint8_t family,
569 const kernel_ulong_t addr,
570 const kernel_ulong_t len)
572 struct packet_diag_msg msg = { .pdiag_family = family };
573 size_t offset = sizeof(msg.pdiag_family);
574 bool decode_nla = false;
576 PRINT_FIELD_XVAL("{", msg, pdiag_family, addrfams, "AF_???");
578 if (len >= sizeof(msg)) {
579 if (!umoven_or_printaddr(tcp, addr + offset,
580 sizeof(msg) - offset,
581 (void *) &msg + offset)) {
582 PRINT_FIELD_XVAL("", msg, pdiag_type,
583 socktypes, "SOCK_???");
584 PRINT_FIELD_U(", ", msg, pdiag_num);
585 PRINT_FIELD_U(", ", msg, pdiag_ino);
586 PRINT_FIELD_COOKIE(", ", msg, pdiag_cookie);
593 offset = NLA_ALIGN(sizeof(msg));
594 if (decode_nla && len > offset) {
596 decode_nlattr(tcp, addr + offset, len - offset,
597 packet_diag_attrs, "PACKET_DIAG_???",
598 packet_diag_msg_nla_decoders,
599 ARRAY_SIZE(packet_diag_msg_nla_decoders), NULL);
604 print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
606 PRINT_FIELD_NET_PORT("{", *id, idiag_sport);
607 PRINT_FIELD_NET_PORT(", ", *id, idiag_dport);
608 PRINT_FIELD_INET_ADDR(", ", *id, idiag_src, family);
609 PRINT_FIELD_INET_ADDR(", ", *id, idiag_dst, family);
610 PRINT_FIELD_IFINDEX(", ", *id, idiag_if);
611 PRINT_FIELD_COOKIE(", ", *id, idiag_cookie);
616 decode_inet_diag_req_compat(struct tcb *const tcp,
617 const struct nlmsghdr *const nlmsghdr,
618 const uint8_t family,
619 const kernel_ulong_t addr,
620 const kernel_ulong_t len)
622 struct inet_diag_req req = { .idiag_family = family };
623 size_t offset = sizeof(req.idiag_family);
624 bool decode_nla = false;
626 PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???");
628 if (len >= sizeof(req)) {
629 if (!umoven_or_printaddr(tcp, addr + offset,
630 sizeof(req) - offset,
631 (void *) &req + offset)) {
632 PRINT_FIELD_U("", req, idiag_src_len);
633 PRINT_FIELD_U(", ", req, idiag_dst_len);
634 PRINT_FIELD_FLAGS(", ", req, idiag_ext,
635 inet_diag_extended_flags,
636 "1<<INET_DIAG_\?\?\?-1");
638 print_inet_diag_sockid(&req.id, req.idiag_family);
639 PRINT_FIELD_FLAGS(", ", req, idiag_states,
640 tcp_state_flags, "1<<TCP_???");
641 PRINT_FIELD_U(", ", req, idiag_dbs);
648 offset = NLA_ALIGN(sizeof(req));
649 if (decode_nla && len > offset) {
651 decode_nlattr(tcp, addr + offset, len - offset,
652 inet_diag_req_attrs, "INET_DIAG_REQ_???",
658 decode_inet_diag_req_v2(struct tcb *const tcp,
659 const struct nlmsghdr *const nlmsghdr,
660 const uint8_t family,
661 const kernel_ulong_t addr,
662 const kernel_ulong_t len)
664 struct inet_diag_req_v2 req = { .sdiag_family = family };
665 size_t offset = sizeof(req.sdiag_family);
666 bool decode_nla = false;
668 PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
670 if (len >= sizeof(req)) {
671 if (!umoven_or_printaddr(tcp, addr + offset,
672 sizeof(req) - offset,
673 (void *) &req + offset)) {
674 PRINT_FIELD_XVAL("", req, sdiag_protocol,
675 inet_protocols, "IPPROTO_???");
676 PRINT_FIELD_FLAGS(", ", req, idiag_ext,
677 inet_diag_extended_flags,
678 "1<<INET_DIAG_\?\?\?-1");
679 PRINT_FIELD_FLAGS(", ", req, idiag_states,
680 tcp_state_flags, "1<<TCP_???");
682 print_inet_diag_sockid(&req.id, req.sdiag_family);
689 offset = NLA_ALIGN(sizeof(req));
690 if (decode_nla && len > offset) {
692 decode_nlattr(tcp, addr + offset, len - offset,
693 inet_diag_req_attrs, "INET_DIAG_REQ_???",
699 decode_inet_diag_req(struct tcb *const tcp,
700 const struct nlmsghdr *const nlmsghdr,
701 const uint8_t family,
702 const kernel_ulong_t addr,
703 const kernel_ulong_t len)
705 if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
706 || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
707 return decode_inet_diag_req_compat(tcp, nlmsghdr,
710 return decode_inet_diag_req_v2(tcp, nlmsghdr,
715 decode_inet_diag_meminfo(struct tcb *const tcp,
716 const kernel_ulong_t addr,
717 const kernel_ulong_t len,
718 const void *const opaque_data)
720 struct inet_diag_meminfo minfo;
722 if (len < sizeof(minfo))
724 if (umove_or_printaddr(tcp, addr, &minfo))
727 PRINT_FIELD_U("{", minfo, idiag_rmem);
728 PRINT_FIELD_U(", ", minfo, idiag_wmem);
729 PRINT_FIELD_U(", ", minfo, idiag_fmem);
730 PRINT_FIELD_U(", ", minfo, idiag_tmem);
737 decode_tcpvegas_info(struct tcb *const tcp,
738 const kernel_ulong_t addr,
739 const kernel_ulong_t len,
740 const void *const opaque_data)
742 struct tcpvegas_info vegas;
744 if (len < sizeof(vegas))
746 if (umove_or_printaddr(tcp, addr, &vegas))
749 PRINT_FIELD_U("{", vegas, tcpv_enabled);
750 PRINT_FIELD_U(", ", vegas, tcpv_rttcnt);
751 PRINT_FIELD_U(", ", vegas, tcpv_rtt);
752 PRINT_FIELD_U(", ", vegas, tcpv_minrtt);
759 decode_tcp_dctcp_info(struct tcb *const tcp,
760 const kernel_ulong_t addr,
761 const kernel_ulong_t len,
762 const void *const opaque_data)
764 struct tcp_dctcp_info dctcp;
766 if (len < sizeof(dctcp))
768 if (umove_or_printaddr(tcp, addr, &dctcp))
771 PRINT_FIELD_U("{", dctcp, dctcp_enabled);
772 PRINT_FIELD_U(", ", dctcp, dctcp_ce_state);
773 PRINT_FIELD_U(", ", dctcp, dctcp_alpha);
774 PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn);
775 PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot);
782 decode_tcp_bbr_info(struct tcb *const tcp,
783 const kernel_ulong_t addr,
784 const kernel_ulong_t len,
785 const void *const opaque_data)
787 struct tcp_bbr_info bbr;
789 if (len < sizeof(bbr))
791 if (umove_or_printaddr(tcp, addr, &bbr))
794 PRINT_FIELD_X("{", bbr, bbr_bw_lo);
795 PRINT_FIELD_X(", ", bbr, bbr_bw_hi);
796 PRINT_FIELD_U(", ", bbr, bbr_min_rtt);
797 PRINT_FIELD_U(", ", bbr, bbr_pacing_gain);
798 PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain);
804 static const nla_decoder_t inet_diag_msg_nla_decoders[] = {
805 [INET_DIAG_MEMINFO] = decode_inet_diag_meminfo,
806 [INET_DIAG_INFO] = NULL, /* unimplemented */
807 [INET_DIAG_VEGASINFO] = decode_tcpvegas_info,
808 [INET_DIAG_CONG] = decode_nla_str,
809 [INET_DIAG_TOS] = decode_nla_u8,
810 [INET_DIAG_TCLASS] = decode_nla_u8,
811 [INET_DIAG_SKMEMINFO] = decode_meminfo,
812 [INET_DIAG_SHUTDOWN] = decode_nla_u8,
813 [INET_DIAG_DCTCPINFO] = decode_tcp_dctcp_info,
814 [INET_DIAG_PROTOCOL] = decode_nla_u8,
815 [INET_DIAG_SKV6ONLY] = decode_nla_u8,
816 [INET_DIAG_LOCALS] = NULL, /* unimplemented */
817 [INET_DIAG_PEERS] = NULL, /* unimplemented */
818 [INET_DIAG_PAD] = NULL,
819 [INET_DIAG_MARK] = decode_nla_u32,
820 [INET_DIAG_BBRINFO] = decode_tcp_bbr_info
824 decode_inet_diag_msg(struct tcb *const tcp,
825 const struct nlmsghdr *const nlmsghdr,
826 const uint8_t family,
827 const kernel_ulong_t addr,
828 const kernel_ulong_t len)
830 struct inet_diag_msg msg = { .idiag_family = family };
831 size_t offset = sizeof(msg.idiag_family);
832 bool decode_nla = false;
834 PRINT_FIELD_XVAL("{", msg, idiag_family, addrfams, "AF_???");
836 if (len >= sizeof(msg)) {
837 if (!umoven_or_printaddr(tcp, addr + offset,
838 sizeof(msg) - offset,
839 (void *) &msg + offset)) {
840 PRINT_FIELD_XVAL("", msg, idiag_state,
841 tcp_states, "TCP_???");
842 PRINT_FIELD_U(", ", msg, idiag_timer);
843 PRINT_FIELD_U(", ", msg, idiag_retrans);
845 print_inet_diag_sockid(&msg.id, msg.idiag_family);
846 PRINT_FIELD_U(", ", msg, idiag_expires);
847 PRINT_FIELD_U(", ", msg, idiag_rqueue);
848 PRINT_FIELD_U(", ", msg, idiag_wqueue);
849 PRINT_FIELD_U(", ", msg, idiag_uid);
850 PRINT_FIELD_U(", ", msg, idiag_inode);
857 offset = NLA_ALIGN(sizeof(msg));
858 if (decode_nla && len > offset) {
860 decode_nlattr(tcp, addr + offset, len - offset,
861 inet_diag_attrs, "INET_DIAG_???",
862 inet_diag_msg_nla_decoders,
863 ARRAY_SIZE(inet_diag_msg_nla_decoders), NULL);
869 decode_smc_diag_req(struct tcb *const tcp,
870 const struct nlmsghdr *const nlmsghdr,
871 const uint8_t family,
872 const kernel_ulong_t addr,
873 const kernel_ulong_t len)
875 struct smc_diag_req req = { .diag_family = family };
876 const size_t offset = sizeof(req.diag_family);
878 PRINT_FIELD_XVAL("{", req, diag_family, addrfams, "AF_???");
880 if (len >= sizeof(req)) {
881 if (!umoven_or_printaddr(tcp, addr + offset,
882 sizeof(req) - offset,
883 (void *) &req + offset)) {
884 PRINT_FIELD_FLAGS("", req, diag_ext,
885 smc_diag_extended_flags,
886 "1<<SMC_DIAG_\?\?\?-1");
889 * AF_SMC protocol family socket handler
890 * keeping the AF_INET sock address.
892 print_inet_diag_sockid(&req.id, AF_INET);
900 decode_smc_diag_msg(struct tcb *const tcp,
901 const struct nlmsghdr *const nlmsghdr,
902 const uint8_t family,
903 const kernel_ulong_t addr,
904 const kernel_ulong_t len)
906 struct smc_diag_msg msg = { .diag_family = family };
907 size_t offset = sizeof(msg.diag_family);
908 bool decode_nla = false;
910 PRINT_FIELD_XVAL("{", msg, diag_family, addrfams, "AF_???");
912 if (len >= sizeof(msg)) {
913 if (!umoven_or_printaddr(tcp, addr + offset,
914 sizeof(msg) - offset,
915 (void *) &msg + offset)) {
916 PRINT_FIELD_XVAL("", msg, diag_state,
917 smc_states, "SMC_???");
918 PRINT_FIELD_U(", ", msg, diag_fallback);
919 PRINT_FIELD_U(", ", msg, diag_shutdown);
922 * AF_SMC protocol family socket handler
923 * keeping the AF_INET sock address.
925 print_inet_diag_sockid(&msg.id, AF_INET);
926 PRINT_FIELD_U(", ", msg, diag_uid);
927 PRINT_FIELD_U(", ", msg, diag_inode);
934 offset = NLA_ALIGN(sizeof(msg));
935 if (decode_nla && len > offset) {
937 decode_nlattr(tcp, addr + offset, len - offset,
938 smc_diag_attrs, "SMC_DIAG_???",
944 typedef void (*netlink_diag_decoder_t)(struct tcb *,
945 const struct nlmsghdr *,
950 static const struct {
951 const netlink_diag_decoder_t request, response;
952 } diag_decoders[] = {
953 [AF_INET] = { decode_inet_diag_req, decode_inet_diag_msg },
954 [AF_INET6] = { decode_inet_diag_req, decode_inet_diag_msg },
955 [AF_NETLINK] = { decode_netlink_diag_req, decode_netlink_diag_msg },
956 [AF_PACKET] = { decode_packet_diag_req, decode_packet_diag_msg },
958 [AF_SMC] = { decode_smc_diag_req, decode_smc_diag_msg },
960 [AF_UNIX] = { decode_unix_diag_req, decode_unix_diag_msg }
964 decode_netlink_sock_diag(struct tcb *const tcp,
965 const struct nlmsghdr *const nlmsghdr,
966 const kernel_ulong_t addr,
967 const kernel_ulong_t len)
971 if (nlmsghdr->nlmsg_type == NLMSG_DONE)
974 if (!umove_or_printaddr(tcp, addr, &family)) {
975 if (family < ARRAY_SIZE(diag_decoders)
976 && len > sizeof(family)) {
977 const netlink_diag_decoder_t decoder =
978 (nlmsghdr->nlmsg_flags & NLM_F_REQUEST)
979 ? diag_decoders[family].request
980 : diag_decoders[family].response;
983 decoder(tcp, nlmsghdr, family, addr, len);
988 decode_family(tcp, family, addr, len);