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