Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2016 Fabien Siron <fabien.siron (at) epita.fr>
      3  * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com>
      4  * Copyright (c) 2017 The strace developers.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     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.
     17  *
     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.
     28  */
     29 
     30 #include "defs.h"
     31 #include "netlink.h"
     32 #include "nlattr.h"
     33 #include "print_fields.h"
     34 
     35 #include <arpa/inet.h>
     36 #include <linux/inet_diag.h>
     37 #include <linux/netlink_diag.h>
     38 #include <linux/packet_diag.h>
     39 #ifdef AF_SMC
     40 # include <linux/smc_diag.h>
     41 #endif
     42 #include <linux/sock_diag.h>
     43 #include <linux/unix_diag.h>
     44 
     45 #include "xlat/inet_diag_attrs.h"
     46 #include "xlat/inet_diag_extended_flags.h"
     47 #include "xlat/inet_diag_req_attrs.h"
     48 
     49 #include "xlat/tcp_states.h"
     50 #include "xlat/tcp_state_flags.h"
     51 
     52 #include "xlat/netlink_diag_attrs.h"
     53 #include "xlat/netlink_diag_show.h"
     54 #include "xlat/netlink_socket_flags.h"
     55 #include "xlat/netlink_states.h"
     56 
     57 #include "xlat/packet_diag_attrs.h"
     58 #include "xlat/packet_diag_show.h"
     59 
     60 #ifdef AF_SMC
     61 # include "xlat/smc_diag_attrs.h"
     62 # include "xlat/smc_diag_extended_flags.h"
     63 # include "xlat/smc_states.h"
     64 #endif
     65 
     66 #include "xlat/unix_diag_attrs.h"
     67 #include "xlat/unix_diag_show.h"
     68 
     69 static void
     70 decode_family(struct tcb *const tcp, const uint8_t family,
     71 	      const kernel_ulong_t addr, const kernel_ulong_t len)
     72 {
     73 	tprints("{family=");
     74 	printxval(addrfams, family, "AF_???");
     75 	if (len > sizeof(family)) {
     76 		tprints(", ");
     77 		printstrn(tcp, addr + sizeof(family),
     78 			  len - sizeof(family));
     79 	}
     80 	tprints("}");
     81 }
     82 
     83 static void
     84 decode_unix_diag_req(struct tcb *const tcp,
     85 		     const struct nlmsghdr *const nlmsghdr,
     86 		     const uint8_t family,
     87 		     const kernel_ulong_t addr,
     88 		     const kernel_ulong_t len)
     89 {
     90 	struct unix_diag_req req = { .sdiag_family = family };
     91 	const size_t offset = sizeof(req.sdiag_family);
     92 
     93 	PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
     94 	tprints(", ");
     95 	if (len >= sizeof(req)) {
     96 		if (!umoven_or_printaddr(tcp, addr + offset,
     97 					 sizeof(req) - offset,
     98 					 (void *) &req + offset)) {
     99 			PRINT_FIELD_U("", req, sdiag_protocol);
    100 			PRINT_FIELD_FLAGS(", ", req, udiag_states,
    101 					  tcp_state_flags, "1<<TCP_???");
    102 			PRINT_FIELD_U(", ", req, udiag_ino);
    103 			PRINT_FIELD_FLAGS(", ", req, udiag_show,
    104 					  unix_diag_show, "UDIAG_SHOW_???");
    105 			PRINT_FIELD_COOKIE(", ", req, udiag_cookie);
    106 		}
    107 	} else
    108 		tprints("...");
    109 	tprints("}");
    110 }
    111 
    112 static bool
    113 print_meminfo(struct tcb *const tcp,
    114 	      void *const elem_buf,
    115 	      const size_t elem_size,
    116 	      void *const opaque_data)
    117 {
    118 	tprintf("%" PRIu32, *(uint32_t *) elem_buf);
    119 
    120 	return true;
    121 }
    122 
    123 static bool
    124 decode_meminfo(struct tcb *const tcp,
    125 	       const kernel_ulong_t addr,
    126 	       const kernel_ulong_t len,
    127 	       const void *const opaque_data)
    128 {
    129 	uint32_t mem;
    130 	size_t nmemb = len / sizeof(mem);
    131 
    132 	if (!nmemb)
    133 		return false;
    134 
    135 	if (nmemb > SK_MEMINFO_VARS)
    136 		nmemb = SK_MEMINFO_VARS;
    137 
    138 	print_array(tcp, addr, nmemb, &mem, sizeof(mem),
    139 		    umoven_or_printaddr, print_meminfo, 0);
    140 
    141 	return true;
    142 }
    143 
    144 static bool
    145 decode_unix_diag_vfs(struct tcb *const tcp,
    146 		     const kernel_ulong_t addr,
    147 		     const kernel_ulong_t len,
    148 		     const void *const opaque_data)
    149 {
    150 	struct unix_diag_vfs uv;
    151 
    152 	if (len < sizeof(uv))
    153 		return false;
    154 	if (umove_or_printaddr(tcp, addr, &uv))
    155 		return true;
    156 
    157 	tprints("{udiag_vfs_dev=");
    158 	print_dev_t(uv.udiag_vfs_dev);
    159 	PRINT_FIELD_U(", ", uv, udiag_vfs_ino);
    160 	tprints("}");
    161 
    162 	return true;
    163 }
    164 
    165 static bool
    166 print_inode(struct tcb *const tcp,
    167 	    void *const elem_buf,
    168 	    const size_t elem_size,
    169 	    void *const opaque_data)
    170 {
    171 	tprintf("%" PRIu32, *(uint32_t *) elem_buf);
    172 
    173 	return true;
    174 }
    175 
    176 static bool
    177 decode_unix_diag_inode(struct tcb *const tcp,
    178 		       const kernel_ulong_t addr,
    179 		       const kernel_ulong_t len,
    180 		       const void *const opaque_data)
    181 {
    182 	uint32_t inode;
    183 	const size_t nmemb = len / sizeof(inode);
    184 
    185 	if (!nmemb)
    186 		return false;
    187 
    188 	print_array(tcp, addr, nmemb, &inode, sizeof(inode),
    189 		    umoven_or_printaddr, print_inode, 0);
    190 
    191 	return true;
    192 }
    193 
    194 static bool
    195 decode_unix_diag_rqlen(struct tcb *const tcp,
    196 		       const kernel_ulong_t addr,
    197 		       const kernel_ulong_t len,
    198 		       const void *const opaque_data)
    199 {
    200 	struct unix_diag_rqlen rql;
    201 
    202 	if (len < sizeof(rql))
    203 		return false;
    204 	if (umove_or_printaddr(tcp, addr, &rql))
    205 		return true;
    206 
    207 	PRINT_FIELD_U("{", rql, udiag_rqueue);
    208 	PRINT_FIELD_U(", ", rql, udiag_wqueue);
    209 	tprints("}");
    210 
    211 	return true;
    212 }
    213 
    214 static const nla_decoder_t unix_diag_msg_nla_decoders[] = {
    215 	[UNIX_DIAG_NAME]	= decode_nla_str,
    216 	[UNIX_DIAG_VFS]		= decode_unix_diag_vfs,
    217 	[UNIX_DIAG_PEER]	= decode_nla_u32,
    218 	[UNIX_DIAG_ICONS]	= decode_unix_diag_inode,
    219 	[UNIX_DIAG_RQLEN]	= decode_unix_diag_rqlen,
    220 	[UNIX_DIAG_MEMINFO]	= decode_meminfo,
    221 	[UNIX_DIAG_SHUTDOWN]	= decode_nla_u8
    222 };
    223 
    224 static void
    225 decode_unix_diag_msg(struct tcb *const tcp,
    226 		     const struct nlmsghdr *const nlmsghdr,
    227 		     const uint8_t family,
    228 		     const kernel_ulong_t addr,
    229 		     const kernel_ulong_t len)
    230 {
    231 	struct unix_diag_msg msg = { .udiag_family = family };
    232 	size_t offset = sizeof(msg.udiag_family);
    233 	bool decode_nla = false;
    234 
    235 	PRINT_FIELD_XVAL("{", msg, udiag_family, addrfams, "AF_???");
    236 	tprints(", ");
    237 	if (len >= sizeof(msg)) {
    238 		if (!umoven_or_printaddr(tcp, addr + offset,
    239 					 sizeof(msg) - offset,
    240 					 (void *) &msg + offset)) {
    241 			PRINT_FIELD_XVAL("", msg, udiag_type,
    242 					 socktypes, "SOCK_???");
    243 			PRINT_FIELD_XVAL(", ", msg, udiag_state,
    244 					 tcp_states, "TCP_???");
    245 			PRINT_FIELD_U(", ", msg, udiag_ino);
    246 			PRINT_FIELD_COOKIE(", ", msg, udiag_cookie);
    247 			decode_nla = true;
    248 		}
    249 	} else
    250 		tprints("...");
    251 	tprints("}");
    252 
    253 	offset = NLMSG_ALIGN(sizeof(msg));
    254 	if (decode_nla && len > offset) {
    255 		tprints(", ");
    256 		decode_nlattr(tcp, addr + offset, len - offset,
    257 			      unix_diag_attrs, "UNIX_DIAG_???",
    258 			      unix_diag_msg_nla_decoders,
    259 			      ARRAY_SIZE(unix_diag_msg_nla_decoders), NULL);
    260 	}
    261 }
    262 
    263 static void
    264 decode_netlink_diag_req(struct tcb *const tcp,
    265 			const struct nlmsghdr *const nlmsghdr,
    266 			const uint8_t family,
    267 			const kernel_ulong_t addr,
    268 			const kernel_ulong_t len)
    269 {
    270 	struct netlink_diag_req req = { .sdiag_family = family };
    271 	const size_t offset = sizeof(req.sdiag_family);
    272 
    273 	PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
    274 	tprints(", ");
    275 	if (len >= sizeof(req)) {
    276 		if (!umoven_or_printaddr(tcp, addr + offset,
    277 					 sizeof(req) - offset,
    278 					 (void *) &req + offset)) {
    279 			if (NDIAG_PROTO_ALL == req.sdiag_protocol)
    280 				tprintf("%s=%s",
    281 					"sdiag_protocol", "NDIAG_PROTO_ALL");
    282 			else
    283 				PRINT_FIELD_XVAL("", req, sdiag_protocol,
    284 						 netlink_protocols,
    285 						 "NETLINK_???");
    286 			PRINT_FIELD_U(", ", req, ndiag_ino);
    287 			PRINT_FIELD_FLAGS(", ", req, ndiag_show,
    288 					  netlink_diag_show, "NDIAG_SHOW_???");
    289 			PRINT_FIELD_COOKIE(", ", req, ndiag_cookie);
    290 		}
    291 	} else
    292 		tprints("...");
    293 	tprints("}");
    294 }
    295 
    296 static bool
    297 print_group(struct tcb *const tcp,
    298 	    void *const elem_buf,
    299 	    const size_t elem_size,
    300 	    void *const opaque_data)
    301 {
    302 	if (elem_size < sizeof(kernel_ulong_t))
    303 		tprintf("%#0*x", (int) elem_size * 2 + 2,
    304 			*(unsigned int *) elem_buf);
    305 	else
    306 		tprintf("%#0*" PRI_klx, (int) elem_size * 2 + 2,
    307 			*(kernel_ulong_t *) elem_buf);
    308 
    309 	return true;
    310 }
    311 
    312 static bool
    313 decode_netlink_diag_groups(struct tcb *const tcp,
    314 			   const kernel_ulong_t addr,
    315 			   const kernel_ulong_t len,
    316 			   const void *const opaque_data)
    317 {
    318 	kernel_ulong_t buf;
    319 	const size_t nmemb = len / current_wordsize;
    320 
    321 	if (!nmemb)
    322 		return false;
    323 
    324 	print_array(tcp, addr, nmemb, &buf, current_wordsize,
    325 		    umoven_or_printaddr, print_group, 0);
    326 
    327 	return true;
    328 }
    329 
    330 static bool
    331 decode_netlink_diag_ring(struct tcb *const tcp,
    332 			 const kernel_ulong_t addr,
    333 			 const kernel_ulong_t len,
    334 			 const void *const opaque_data)
    335 {
    336 	struct netlink_diag_ring ndr;
    337 
    338 	if (len < sizeof(ndr))
    339 		return false;
    340 	if (umove_or_printaddr(tcp, addr, &ndr))
    341 		return true;
    342 
    343 	PRINT_FIELD_U("{", ndr, ndr_block_size);
    344 	PRINT_FIELD_U(", ", ndr, ndr_block_nr);
    345 	PRINT_FIELD_U(", ", ndr, ndr_frame_size);
    346 	PRINT_FIELD_U(", ", ndr, ndr_frame_nr);
    347 	tprints("}");
    348 
    349 	return true;
    350 }
    351 
    352 static bool
    353 decode_netlink_diag_flags(struct tcb *const tcp,
    354 			  const kernel_ulong_t addr,
    355 			  const kernel_ulong_t len,
    356 			  const void *const opaque_data)
    357 {
    358 	uint32_t flags;
    359 
    360 	if (len < sizeof(flags))
    361 		return false;
    362 	if (umove_or_printaddr(tcp, addr, &flags))
    363 		return true;
    364 
    365 	printflags(netlink_socket_flags, flags, "NDIAG_FLAG_???");
    366 
    367 	return true;
    368 }
    369 
    370 static const nla_decoder_t netlink_diag_msg_nla_decoders[] = {
    371 	[NETLINK_DIAG_MEMINFO]	= decode_meminfo,
    372 	[NETLINK_DIAG_GROUPS]	= decode_netlink_diag_groups,
    373 	[NETLINK_DIAG_RX_RING]	= decode_netlink_diag_ring,
    374 	[NETLINK_DIAG_TX_RING]	= decode_netlink_diag_ring,
    375 	[NETLINK_DIAG_FLAGS]	= decode_netlink_diag_flags
    376 };
    377 
    378 static void
    379 decode_netlink_diag_msg(struct tcb *const tcp,
    380 			const struct nlmsghdr *const nlmsghdr,
    381 			const uint8_t family,
    382 			const kernel_ulong_t addr,
    383 			const kernel_ulong_t len)
    384 {
    385 	struct netlink_diag_msg msg = { .ndiag_family = family };
    386 	size_t offset = sizeof(msg.ndiag_family);
    387 	bool decode_nla = false;
    388 
    389 	PRINT_FIELD_XVAL("{", msg, ndiag_family, addrfams, "AF_???");
    390 	tprints(", ");
    391 	if (len >= sizeof(msg)) {
    392 		if (!umoven_or_printaddr(tcp, addr + offset,
    393 					 sizeof(msg) - offset,
    394 					 (void *) &msg + offset)) {
    395 			PRINT_FIELD_XVAL("", msg, ndiag_type,
    396 					 socktypes, "SOCK_???");
    397 			PRINT_FIELD_XVAL(", ", msg, ndiag_protocol,
    398 					 netlink_protocols, "NETLINK_???");
    399 			PRINT_FIELD_XVAL(", ", msg, ndiag_state,
    400 					 netlink_states, "NETLINK_???");
    401 			PRINT_FIELD_U(", ", msg, ndiag_portid);
    402 			PRINT_FIELD_U(", ", msg, ndiag_dst_portid);
    403 			PRINT_FIELD_U(", ", msg, ndiag_dst_group);
    404 			PRINT_FIELD_U(", ", msg, ndiag_ino);
    405 			PRINT_FIELD_COOKIE(", ", msg, ndiag_cookie);
    406 			decode_nla = true;
    407 		}
    408 	} else
    409 		tprints("...");
    410 	tprints("}");
    411 
    412 	offset = NLA_ALIGN(sizeof(msg));
    413 	if (decode_nla && len > offset) {
    414 		tprints(", ");
    415 		decode_nlattr(tcp, addr + offset, len - offset,
    416 			      netlink_diag_attrs, "NETLINK_DIAG_???",
    417 			      netlink_diag_msg_nla_decoders,
    418 			      ARRAY_SIZE(netlink_diag_msg_nla_decoders), NULL);
    419 	}
    420 }
    421 
    422 static void
    423 decode_packet_diag_req(struct tcb *const tcp,
    424 		       const struct nlmsghdr *const nlmsghdr,
    425 		       const uint8_t family,
    426 		       const kernel_ulong_t addr,
    427 		       const kernel_ulong_t len)
    428 {
    429 	struct packet_diag_req req = { .sdiag_family = family };
    430 	const size_t offset = sizeof(req.sdiag_family);
    431 
    432 	PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
    433 	tprints(", ");
    434 	if (len >= sizeof(req)) {
    435 		if (!umoven_or_printaddr(tcp, addr + offset,
    436 					 sizeof(req) - offset,
    437 					 (void *) &req + offset)) {
    438 			PRINT_FIELD_XVAL("", req, sdiag_protocol,
    439 					 ethernet_protocols, "ETH_P_???");
    440 			PRINT_FIELD_U(", ", req, pdiag_ino);
    441 			PRINT_FIELD_FLAGS(", ", req, pdiag_show,
    442 					  packet_diag_show, "PACKET_SHOW_???");
    443 			PRINT_FIELD_COOKIE(", ", req, pdiag_cookie);
    444 		}
    445 	} else
    446 		tprints("...");
    447 	tprints("}");
    448 }
    449 
    450 static void
    451 decode_packet_diag_msg(struct tcb *const tcp,
    452 		       const struct nlmsghdr *const nlmsghdr,
    453 		       const uint8_t family,
    454 		       const kernel_ulong_t addr,
    455 		       const kernel_ulong_t len)
    456 {
    457 	struct packet_diag_msg msg = { .pdiag_family = family };
    458 	size_t offset = sizeof(msg.pdiag_family);
    459 	bool decode_nla = false;
    460 
    461 	PRINT_FIELD_XVAL("{", msg, pdiag_family, addrfams, "AF_???");
    462 	tprints(", ");
    463 	if (len >= sizeof(msg)) {
    464 		if (!umoven_or_printaddr(tcp, addr + offset,
    465 					 sizeof(msg) - offset,
    466 					 (void *) &msg + offset)) {
    467 			PRINT_FIELD_XVAL("", msg, pdiag_type,
    468 					 socktypes, "SOCK_???");
    469 			PRINT_FIELD_U(", ", msg, pdiag_num);
    470 			PRINT_FIELD_U(", ", msg, pdiag_ino);
    471 			PRINT_FIELD_COOKIE(", ", msg, pdiag_cookie);
    472 			decode_nla = true;
    473 		}
    474 	} else
    475 		tprints("...");
    476 	tprints("}");
    477 
    478 	offset = NLA_ALIGN(sizeof(msg));
    479 	if (decode_nla && len > offset) {
    480 		tprints(", ");
    481 		decode_nlattr(tcp, addr + offset, len - offset,
    482 			      packet_diag_attrs, "PACKET_DIAG_???",
    483 			      NULL, 0, NULL);
    484 	}
    485 }
    486 
    487 static void
    488 print_inet_diag_sockid(const struct inet_diag_sockid *id, const uint8_t family)
    489 {
    490 	tprintf("{idiag_sport=htons(%u), idiag_dport=htons(%u)",
    491 		ntohs(id->idiag_sport), ntohs(id->idiag_dport));
    492 
    493 	tprints(", ");
    494 	print_inet_addr(family, id->idiag_src,
    495 			sizeof(id->idiag_src), "idiag_src");
    496 	tprints(", ");
    497 	print_inet_addr(family, id->idiag_dst,
    498 			sizeof(id->idiag_dst), "idiag_dst");
    499 
    500 	tprints(", idiag_if=");
    501 	print_ifindex(id->idiag_if);
    502 
    503 	PRINT_FIELD_COOKIE(", ", *id, idiag_cookie);
    504 
    505 	tprints("}");
    506 }
    507 
    508 static void
    509 decode_inet_diag_req_compat(struct tcb *const tcp,
    510 			    const struct nlmsghdr *const nlmsghdr,
    511 			    const uint8_t family,
    512 			    const kernel_ulong_t addr,
    513 			    const kernel_ulong_t len)
    514 {
    515 	struct inet_diag_req req = { .idiag_family = family };
    516 	size_t offset = sizeof(req.idiag_family);
    517 	bool decode_nla = false;
    518 
    519 	PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???");
    520 	tprints(", ");
    521 	if (len >= sizeof(req)) {
    522 		if (!umoven_or_printaddr(tcp, addr + offset,
    523 					 sizeof(req) - offset,
    524 					 (void *) &req + offset)) {
    525 			PRINT_FIELD_U("", req, idiag_src_len);
    526 			PRINT_FIELD_U(", ", req, idiag_dst_len);
    527 			PRINT_FIELD_FLAGS(", ", req, idiag_ext,
    528 					  inet_diag_extended_flags,
    529 					  "1<<INET_DIAG_\?\?\?-1");
    530 			tprints(", id=");
    531 			print_inet_diag_sockid(&req.id, req.idiag_family);
    532 			PRINT_FIELD_FLAGS(", ", req, idiag_states,
    533 					  tcp_state_flags, "1<<TCP_???");
    534 			PRINT_FIELD_U(", ", req, idiag_dbs);
    535 			decode_nla = true;
    536 		}
    537 	} else
    538 		tprints("...");
    539 	tprints("}");
    540 
    541 	offset = NLA_ALIGN(sizeof(req));
    542 	if (decode_nla && len > offset) {
    543 		tprints(", ");
    544 		decode_nlattr(tcp, addr + offset, len - offset,
    545 			      inet_diag_req_attrs, "INET_DIAG_REQ_???",
    546 			      NULL, 0, NULL);
    547 	}
    548 }
    549 
    550 static void
    551 decode_inet_diag_req_v2(struct tcb *const tcp,
    552 			const struct nlmsghdr *const nlmsghdr,
    553 			const uint8_t family,
    554 			const kernel_ulong_t addr,
    555 			const kernel_ulong_t len)
    556 {
    557 	struct inet_diag_req_v2 req = { .sdiag_family = family };
    558 	size_t offset = sizeof(req.sdiag_family);
    559 	bool decode_nla = false;
    560 
    561 	PRINT_FIELD_XVAL("{", req, sdiag_family, addrfams, "AF_???");
    562 	tprints(", ");
    563 	if (len >= sizeof(req)) {
    564 		if (!umoven_or_printaddr(tcp, addr + offset,
    565 					 sizeof(req) - offset,
    566 					 (void *) &req + offset)) {
    567 			PRINT_FIELD_XVAL("", req, sdiag_protocol,
    568 					 inet_protocols, "IPPROTO_???");
    569 			PRINT_FIELD_FLAGS(", ", req, idiag_ext,
    570 					  inet_diag_extended_flags,
    571 					  "1<<INET_DIAG_\?\?\?-1");
    572 			PRINT_FIELD_FLAGS(", ", req, idiag_states,
    573 					  tcp_state_flags, "1<<TCP_???");
    574 			tprints(", id=");
    575 			print_inet_diag_sockid(&req.id, req.sdiag_family);
    576 			decode_nla = true;
    577 		}
    578 	} else
    579 		tprints("...");
    580 	tprints("}");
    581 
    582 	offset = NLA_ALIGN(sizeof(req));
    583 	if (decode_nla && len > offset) {
    584 		tprints(", ");
    585 		decode_nlattr(tcp, addr + offset, len - offset,
    586 			      inet_diag_req_attrs, "INET_DIAG_REQ_???",
    587 			      NULL, 0, NULL);
    588 	}
    589 }
    590 
    591 static void
    592 decode_inet_diag_req(struct tcb *const tcp,
    593 		     const struct nlmsghdr *const nlmsghdr,
    594 		     const uint8_t family,
    595 		     const kernel_ulong_t addr,
    596 		     const kernel_ulong_t len)
    597 {
    598 	if (nlmsghdr->nlmsg_type == TCPDIAG_GETSOCK
    599 	    || nlmsghdr->nlmsg_type == DCCPDIAG_GETSOCK)
    600 		return decode_inet_diag_req_compat(tcp, nlmsghdr,
    601 						   family, addr, len);
    602 	else
    603 		return decode_inet_diag_req_v2(tcp, nlmsghdr,
    604 					       family, addr, len);
    605 }
    606 
    607 static bool
    608 decode_inet_diag_meminfo(struct tcb *const tcp,
    609 			 const kernel_ulong_t addr,
    610 			 const kernel_ulong_t len,
    611 			 const void *const opaque_data)
    612 {
    613 	struct inet_diag_meminfo minfo;
    614 
    615 	if (len < sizeof(minfo))
    616 		return false;
    617 	if (umove_or_printaddr(tcp, addr, &minfo))
    618 		return true;
    619 
    620 	PRINT_FIELD_U("{", minfo, idiag_rmem);
    621 	PRINT_FIELD_U(", ", minfo, idiag_wmem);
    622 	PRINT_FIELD_U(", ", minfo, idiag_fmem);
    623 	PRINT_FIELD_U(", ", minfo, idiag_tmem);
    624 	tprints("}");
    625 
    626 	return true;
    627 }
    628 
    629 static bool
    630 decode_tcpvegas_info(struct tcb *const tcp,
    631 		     const kernel_ulong_t addr,
    632 		     const kernel_ulong_t len,
    633 		     const void *const opaque_data)
    634 {
    635 	struct tcpvegas_info vegas;
    636 
    637 	if (len < sizeof(vegas))
    638 		return false;
    639 	if (umove_or_printaddr(tcp, addr, &vegas))
    640 		return true;
    641 
    642 	PRINT_FIELD_U("{", vegas, tcpv_enabled);
    643 	PRINT_FIELD_U(", ", vegas, tcpv_rttcnt);
    644 	PRINT_FIELD_U(", ", vegas, tcpv_rtt);
    645 	PRINT_FIELD_U(", ", vegas, tcpv_minrtt);
    646 	tprints("}");
    647 
    648 	return true;
    649 }
    650 
    651 static bool
    652 decode_tcp_dctcp_info(struct tcb *const tcp,
    653 		      const kernel_ulong_t addr,
    654 		      const kernel_ulong_t len,
    655 		      const void *const opaque_data)
    656 {
    657 	struct tcp_dctcp_info dctcp;
    658 
    659 	if (len < sizeof(dctcp))
    660 		return false;
    661 	if (umove_or_printaddr(tcp, addr, &dctcp))
    662 		return true;
    663 
    664 	PRINT_FIELD_U("{", dctcp, dctcp_enabled);
    665 	PRINT_FIELD_U(", ", dctcp, dctcp_ce_state);
    666 	PRINT_FIELD_U(", ", dctcp, dctcp_alpha);
    667 	PRINT_FIELD_U(", ", dctcp, dctcp_ab_ecn);
    668 	PRINT_FIELD_U(", ", dctcp, dctcp_ab_tot);
    669 	tprints("}");
    670 
    671 	return true;
    672 }
    673 
    674 static bool
    675 decode_tcp_bbr_info(struct tcb *const tcp,
    676 		    const kernel_ulong_t addr,
    677 		    const kernel_ulong_t len,
    678 		    const void *const opaque_data)
    679 {
    680 	struct tcp_bbr_info bbr;
    681 
    682 	if (len < sizeof(bbr))
    683 		return false;
    684 	if (umove_or_printaddr(tcp, addr, &bbr))
    685 		return true;
    686 
    687 	PRINT_FIELD_X("{", bbr, bbr_bw_lo);
    688 	PRINT_FIELD_X(", ", bbr, bbr_bw_hi);
    689 	PRINT_FIELD_U(", ", bbr, bbr_min_rtt);
    690 	PRINT_FIELD_U(", ", bbr, bbr_pacing_gain);
    691 	PRINT_FIELD_U(", ", bbr, bbr_cwnd_gain);
    692 	tprints("}");
    693 
    694 	return true;
    695 }
    696 
    697 static const nla_decoder_t inet_diag_msg_nla_decoders[] = {
    698 	[INET_DIAG_MEMINFO]	= decode_inet_diag_meminfo,
    699 	[INET_DIAG_INFO]	= NULL,			/* unimplemented */
    700 	[INET_DIAG_VEGASINFO]	= decode_tcpvegas_info,
    701 	[INET_DIAG_CONG]	= decode_nla_str,
    702 	[INET_DIAG_TOS]		= decode_nla_u8,
    703 	[INET_DIAG_TCLASS]	= decode_nla_u8,
    704 	[INET_DIAG_SKMEMINFO]	= decode_meminfo,
    705 	[INET_DIAG_SHUTDOWN]	= decode_nla_u8,
    706 	[INET_DIAG_DCTCPINFO]	= decode_tcp_dctcp_info,
    707 	[INET_DIAG_PROTOCOL]	= decode_nla_u8,
    708 	[INET_DIAG_SKV6ONLY]	= decode_nla_u8,
    709 	[INET_DIAG_LOCALS]	= NULL,			/* unimplemented */
    710 	[INET_DIAG_PEERS]	= NULL,			/* unimplemented */
    711 	[INET_DIAG_PAD]		= NULL,
    712 	[INET_DIAG_MARK]	= decode_nla_u32,
    713 	[INET_DIAG_BBRINFO]	= decode_tcp_bbr_info
    714 };
    715 
    716 static void
    717 decode_inet_diag_msg(struct tcb *const tcp,
    718 		     const struct nlmsghdr *const nlmsghdr,
    719 		     const uint8_t family,
    720 		     const kernel_ulong_t addr,
    721 		     const kernel_ulong_t len)
    722 {
    723 	struct inet_diag_msg msg = { .idiag_family = family };
    724 	size_t offset = sizeof(msg.idiag_family);
    725 	bool decode_nla = false;
    726 
    727 	PRINT_FIELD_XVAL("{", msg, idiag_family, addrfams, "AF_???");
    728 	tprints(", ");
    729 	if (len >= sizeof(msg)) {
    730 		if (!umoven_or_printaddr(tcp, addr + offset,
    731 					 sizeof(msg) - offset,
    732 					 (void *) &msg + offset)) {
    733 			PRINT_FIELD_XVAL("", msg, idiag_state,
    734 					 tcp_states, "TCP_???");
    735 			PRINT_FIELD_U(", ", msg, idiag_timer);
    736 			PRINT_FIELD_U(", ", msg, idiag_retrans);
    737 			tprints(", id=");
    738 			print_inet_diag_sockid(&msg.id, msg.idiag_family);
    739 			PRINT_FIELD_U(", ", msg, idiag_expires);
    740 			PRINT_FIELD_U(", ", msg, idiag_rqueue);
    741 			PRINT_FIELD_U(", ", msg, idiag_wqueue);
    742 			PRINT_FIELD_U(", ", msg, idiag_uid);
    743 			PRINT_FIELD_U(", ", msg, idiag_inode);
    744 			decode_nla = true;
    745 		}
    746 	} else
    747 		tprints("...");
    748 	tprints("}");
    749 
    750 	offset = NLA_ALIGN(sizeof(msg));
    751 	if (decode_nla && len > offset) {
    752 		tprints(", ");
    753 		decode_nlattr(tcp, addr + offset, len - offset,
    754 			      inet_diag_attrs, "INET_DIAG_???",
    755 			      inet_diag_msg_nla_decoders,
    756 			      ARRAY_SIZE(inet_diag_msg_nla_decoders), NULL);
    757 	}
    758 }
    759 
    760 #ifdef AF_SMC
    761 static void
    762 decode_smc_diag_req(struct tcb *const tcp,
    763 		    const struct nlmsghdr *const nlmsghdr,
    764 		    const uint8_t family,
    765 		    const kernel_ulong_t addr,
    766 		    const kernel_ulong_t len)
    767 {
    768 	struct smc_diag_req req = { .diag_family = family };
    769 	const size_t offset = sizeof(req.diag_family);
    770 
    771 	PRINT_FIELD_XVAL("{", req, diag_family, addrfams, "AF_???");
    772 	tprints(", ");
    773 	if (len >= sizeof(req)) {
    774 		if (!umoven_or_printaddr(tcp, addr + offset,
    775 					 sizeof(req) - offset,
    776 					 (void *) &req + offset)) {
    777 			PRINT_FIELD_FLAGS("", req, diag_ext,
    778 					  smc_diag_extended_flags,
    779 					  "1<<SMC_DIAG_\?\?\?-1");
    780 			tprints(", id=");
    781 			/*
    782 			 * AF_SMC protocol family socket handler
    783 			 * keeping the AF_INET sock address.
    784 			 */
    785 			print_inet_diag_sockid(&req.id, AF_INET);
    786 		}
    787 	} else
    788 		tprints("...");
    789 	tprints("}");
    790 }
    791 
    792 static void
    793 decode_smc_diag_msg(struct tcb *const tcp,
    794 		    const struct nlmsghdr *const nlmsghdr,
    795 		    const uint8_t family,
    796 		    const kernel_ulong_t addr,
    797 		    const kernel_ulong_t len)
    798 {
    799 	struct smc_diag_msg msg = { .diag_family = family };
    800 	size_t offset = sizeof(msg.diag_family);
    801 	bool decode_nla = false;
    802 
    803 	PRINT_FIELD_XVAL("{", msg, diag_family, addrfams, "AF_???");
    804 	tprints(", ");
    805 	if (len >= sizeof(msg)) {
    806 		if (!umoven_or_printaddr(tcp, addr + offset,
    807 					 sizeof(msg) - offset,
    808 					 (void *) &msg + offset)) {
    809 			PRINT_FIELD_XVAL("", msg, diag_state,
    810 					 smc_states, "SMC_???");
    811 			PRINT_FIELD_U(", ", msg, diag_fallback);
    812 			PRINT_FIELD_U(", ", msg, diag_shutdown);
    813 			tprints(", id=");
    814 			/*
    815 			 * AF_SMC protocol family socket handler
    816 			 * keeping the AF_INET sock address.
    817 			 */
    818 			print_inet_diag_sockid(&msg.id, AF_INET);
    819 			PRINT_FIELD_U(", ", msg, diag_uid);
    820 			PRINT_FIELD_U(", ", msg, diag_inode);
    821 			decode_nla = true;
    822 		}
    823 	} else
    824 		tprints("...");
    825 	tprints("}");
    826 
    827 	offset = NLA_ALIGN(sizeof(msg));
    828 	if (decode_nla && len > offset) {
    829 		tprints(", ");
    830 		decode_nlattr(tcp, addr + offset, len - offset,
    831 			      smc_diag_attrs, "SMC_DIAG_???",
    832 			      NULL, 0, NULL);
    833 	}
    834 }
    835 #endif
    836 
    837 typedef void (*netlink_diag_decoder_t)(struct tcb *,
    838 				       const struct nlmsghdr *,
    839 				       uint8_t family,
    840 				       kernel_ulong_t addr,
    841 				       kernel_ulong_t len);
    842 
    843 static const struct {
    844 	const netlink_diag_decoder_t request, response;
    845 } diag_decoders[] = {
    846 	[AF_INET] = { decode_inet_diag_req, decode_inet_diag_msg },
    847 	[AF_INET6] = { decode_inet_diag_req, decode_inet_diag_msg },
    848 	[AF_NETLINK] = { decode_netlink_diag_req, decode_netlink_diag_msg },
    849 	[AF_PACKET] = { decode_packet_diag_req, decode_packet_diag_msg },
    850 #ifdef AF_SMC
    851 	[AF_SMC] = { decode_smc_diag_req, decode_smc_diag_msg },
    852 #endif
    853 	[AF_UNIX] = { decode_unix_diag_req, decode_unix_diag_msg }
    854 };
    855 
    856 bool
    857 decode_netlink_sock_diag(struct tcb *const tcp,
    858 			 const struct nlmsghdr *const nlmsghdr,
    859 			 const kernel_ulong_t addr,
    860 			 const kernel_ulong_t len)
    861 {
    862 	uint8_t family;
    863 
    864 	if (nlmsghdr->nlmsg_type == NLMSG_DONE)
    865 		return false;
    866 
    867 	if (!umove_or_printaddr(tcp, addr, &family)) {
    868 		if (family < ARRAY_SIZE(diag_decoders)
    869 		    && len > sizeof(family)) {
    870 			const netlink_diag_decoder_t decoder =
    871 				(nlmsghdr->nlmsg_flags & NLM_F_REQUEST)
    872 				? diag_decoders[family].request
    873 				: diag_decoders[family].response;
    874 
    875 			if (decoder) {
    876 				decoder(tcp, nlmsghdr, family, addr, len);
    877 				return true;
    878 			}
    879 		}
    880 
    881 		decode_family(tcp, family, addr, len);
    882 	}
    883 
    884 	return true;
    885 }
    886