1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <mdb/mdb_modapi.h> 29 #include <mdb/mdb_ks.h> 30 #include <mdb/mdb_ctf.h> 31 #include <sys/types.h> 32 #include <sys/tihdr.h> 33 #include <inet/led.h> 34 #include <inet/common.h> 35 #include <netinet/in.h> 36 #include <netinet/ip6.h> 37 #include <netinet/icmp6.h> 38 #include <inet/ip.h> 39 #include <inet/ip6.h> 40 #include <inet/ipclassifier.h> 41 #include <inet/tcp.h> 42 #include <sys/stream.h> 43 #include <sys/vfs.h> 44 #include <sys/stropts.h> 45 #include <sys/tpicommon.h> 46 #include <sys/socket.h> 47 #include <sys/socketvar.h> 48 #include <sys/cred_impl.h> 49 #include <inet/udp_impl.h> 50 #include <inet/arp_impl.h> 51 #include <inet/rawip_impl.h> 52 #include <inet/mi.h> 53 54 #define MIH2MIO(mihp) (&(mihp)->mh_o) 55 56 #define ADDR_V6_WIDTH 23 57 #define ADDR_V4_WIDTH 15 58 59 #define NETSTAT_ALL 0x01 60 #define NETSTAT_VERBOSE 0x02 61 #define NETSTAT_ROUTE 0x04 62 #define NETSTAT_V4 0x08 63 #define NETSTAT_V6 0x10 64 #define NETSTAT_UNIX 0x20 65 66 #define NETSTAT_FIRST 0x80000000u 67 68 /* 69 * Print an IPv4 address and port number in a compact and easy to read format 70 * The arguments are in network byte order 71 */ 72 static void 73 net_ipv4addrport_pr(const in6_addr_t *nipv6addr, in_port_t nport) 74 { 75 uint32_t naddr = V4_PART_OF_V6((*nipv6addr)); 76 77 mdb_nhconvert(&nport, &nport, sizeof (nport)); 78 mdb_printf("%*I.%-5hu", ADDR_V4_WIDTH, naddr, nport); 79 } 80 81 /* 82 * Print an IPv6 address and port number in a compact and easy to read format 83 * The arguments are in network byte order 84 */ 85 static void 86 net_ipv6addrport_pr(const in6_addr_t *naddr, in_port_t nport) 87 { 88 mdb_nhconvert(&nport, &nport, sizeof (nport)); 89 mdb_printf("%*N.%-5hu", ADDR_V6_WIDTH, naddr, nport); 90 } 91 92 static int 93 net_tcp_active(const tcp_t *tcp) 94 { 95 return (tcp->tcp_state >= TCPS_ESTABLISHED); 96 } 97 98 static int 99 net_tcp_ipv4(const tcp_t *tcp) 100 { 101 return ((tcp->tcp_ipversion == IPV4_VERSION) || 102 (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip_src_v6) && 103 (tcp->tcp_state <= TCPS_LISTEN))); 104 } 105 106 static int 107 net_tcp_ipv6(const tcp_t *tcp) 108 { 109 return (tcp->tcp_ipversion == IPV6_VERSION); 110 } 111 112 static int 113 net_udp_active(const udp_t *udp) 114 { 115 return ((udp->udp_state == TS_IDLE) || 116 (udp->udp_state == TS_DATA_XFER)); 117 } 118 119 static int 120 net_udp_ipv4(const udp_t *udp) 121 { 122 return ((udp->udp_ipversion == IPV4_VERSION) || 123 (IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src) && 124 (udp->udp_state <= TS_IDLE))); 125 } 126 127 static int 128 net_udp_ipv6(const udp_t *udp) 129 { 130 return (udp->udp_ipversion == IPV6_VERSION); 131 } 132 133 int 134 sonode_walk_init(mdb_walk_state_t *wsp) 135 { 136 if (wsp->walk_addr == NULL) { 137 GElf_Sym sym; 138 struct socklist *slp; 139 140 if (mdb_lookup_by_obj("sockfs", "socklist", &sym) == -1) { 141 mdb_warn("failed to lookup sockfs`socklist"); 142 return (WALK_ERR); 143 } 144 145 slp = (struct socklist *)(uintptr_t)sym.st_value; 146 147 if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), 148 (uintptr_t)&slp->sl_list) == -1) { 149 mdb_warn("failed to read address of initial sonode " 150 "at %p", &slp->sl_list); 151 return (WALK_ERR); 152 } 153 } 154 155 wsp->walk_data = mdb_alloc(sizeof (struct sonode), UM_SLEEP); 156 return (WALK_NEXT); 157 } 158 159 int 160 sonode_walk_step(mdb_walk_state_t *wsp) 161 { 162 int status; 163 struct sonode *sonodep; 164 165 if (wsp->walk_addr == NULL) 166 return (WALK_DONE); 167 168 if (mdb_vread(wsp->walk_data, sizeof (struct sonode), 169 wsp->walk_addr) == -1) { 170 mdb_warn("failed to read sonode at %p", wsp->walk_addr); 171 return (WALK_ERR); 172 } 173 174 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 175 wsp->walk_cbdata); 176 177 sonodep = wsp->walk_data; 178 179 wsp->walk_addr = (uintptr_t)sonodep->so_next; 180 return (status); 181 } 182 183 void 184 sonode_walk_fini(mdb_walk_state_t *wsp) 185 { 186 mdb_free(wsp->walk_data, sizeof (struct sonode)); 187 } 188 189 struct mi_walk_data { 190 uintptr_t mi_wd_miofirst; 191 MI_O mi_wd_miodata; 192 }; 193 194 int 195 mi_walk_init(mdb_walk_state_t *wsp) 196 { 197 struct mi_walk_data *wdp; 198 199 if (wsp->walk_addr == NULL) { 200 mdb_warn("mi doesn't support global walks\n"); 201 return (WALK_ERR); 202 } 203 204 wdp = mdb_alloc(sizeof (struct mi_walk_data), UM_SLEEP); 205 206 /* So that we do not immediately return WALK_DONE below */ 207 wdp->mi_wd_miofirst = NULL; 208 209 wsp->walk_data = wdp; 210 return (WALK_NEXT); 211 } 212 213 int 214 mi_walk_step(mdb_walk_state_t *wsp) 215 { 216 struct mi_walk_data *wdp = wsp->walk_data; 217 MI_OP miop = &wdp->mi_wd_miodata; 218 int status; 219 220 /* Always false in the first iteration */ 221 if ((wsp->walk_addr == (uintptr_t)NULL) || 222 (wsp->walk_addr == wdp->mi_wd_miofirst)) { 223 return (WALK_DONE); 224 } 225 226 if (mdb_vread(miop, sizeof (MI_O), wsp->walk_addr) == -1) { 227 mdb_warn("failed to read MI object at %p", wsp->walk_addr); 228 return (WALK_ERR); 229 } 230 231 status = wsp->walk_callback(wsp->walk_addr, miop, wsp->walk_cbdata); 232 233 /* Only true in the first iteration */ 234 if (wdp->mi_wd_miofirst == NULL) 235 wdp->mi_wd_miofirst = wsp->walk_addr; 236 237 wsp->walk_addr = (uintptr_t)miop->mi_o_next; 238 return (status); 239 } 240 241 void 242 mi_walk_fini(mdb_walk_state_t *wsp) 243 { 244 mdb_free(wsp->walk_data, sizeof (struct mi_walk_data)); 245 } 246 247 typedef struct mi_payload_walk_data_s { 248 uintptr_t mi_pwd_first; 249 void *mi_pwd_data; 250 } mi_payload_walk_data_t; 251 252 static void 253 delete_mi_payload_walk_data(mi_payload_walk_data_t *pwdp, size_t payload_size) 254 { 255 mdb_free(pwdp->mi_pwd_data, payload_size); 256 mdb_free(pwdp, sizeof (mi_payload_walk_data_t)); 257 } 258 259 typedef struct mi_payload_walk_arg_s { 260 const char *mi_pwa_obj; /* load object of mi_o_head_t * */ 261 const char *mi_pwa_sym; /* symbol name of mi_o_head_t * */ 262 const size_t mi_pwa_size; /* size of mi payload */ 263 const uint_t mi_pwa_flags; /* device and/or module */ 264 } mi_payload_walk_arg_t; 265 266 #define MI_PAYLOAD_DEVICE 0x1 267 #define MI_PAYLOAD_MODULE 0x2 268 269 int 270 mi_payload_walk_init(mdb_walk_state_t *wsp) 271 { 272 const mi_payload_walk_arg_t *arg = wsp->walk_arg; 273 mi_payload_walk_data_t *pwdp; 274 GElf_Sym sym; 275 mi_head_t *mihp; 276 277 /* Determine the address to start or end the walk with */ 278 if (mdb_lookup_by_obj(arg->mi_pwa_obj, arg->mi_pwa_sym, &sym) == -1) { 279 mdb_warn("failed to lookup %s`%s", 280 arg->mi_pwa_obj, arg->mi_pwa_sym); 281 return (WALK_ERR); 282 } 283 284 if (mdb_vread(&mihp, sizeof (mihp), (uintptr_t)sym.st_value) == -1) { 285 mdb_warn("failed to read address of global MI Head " 286 "mi_o_head_t at %p", (uintptr_t)sym.st_value); 287 return (WALK_ERR); 288 } 289 290 pwdp = mdb_alloc(sizeof (mi_payload_walk_data_t), UM_SLEEP); 291 pwdp->mi_pwd_data = mdb_alloc(arg->mi_pwa_size, UM_SLEEP); 292 wsp->walk_data = pwdp; 293 294 if (wsp->walk_addr == NULL) { 295 /* Do not immediately return WALK_DONE below */ 296 pwdp->mi_pwd_first = NULL; 297 /* We determined where to begin */ 298 wsp->walk_addr = (uintptr_t)MIH2MIO(mihp); 299 } else { 300 /* Do not cycle through all of the MI_O objects */ 301 pwdp->mi_pwd_first = (uintptr_t)MIH2MIO(mihp); 302 /* We were given where to begin */ 303 wsp->walk_addr = (uintptr_t)((MI_OP)wsp->walk_addr - 1); 304 } 305 306 if (mdb_layered_walk("genunix`mi", wsp) == -1) { 307 mdb_warn("failed to walk genunix`mi"); 308 delete_mi_payload_walk_data(pwdp, arg->mi_pwa_size); 309 return (WALK_ERR); 310 } 311 312 return (WALK_NEXT); 313 } 314 315 int 316 mi_payload_walk_step(mdb_walk_state_t *wsp) 317 { 318 const mi_payload_walk_arg_t *arg = wsp->walk_arg; 319 mi_payload_walk_data_t *pwdp = wsp->walk_data; 320 void *payload = pwdp->mi_pwd_data; 321 uintptr_t payload_kaddr = (uintptr_t)((MI_OP)wsp->walk_addr + 1); 322 const MI_O *mio = wsp->walk_layer; 323 324 /* If this is a local walk, prevent cycling */ 325 if (wsp->walk_addr == pwdp->mi_pwd_first) 326 return (WALK_DONE); 327 328 /* 329 * This was a global walk, prevent reading this payload as the 330 * initial MI_O is the head of the list and is not the header 331 * to a valid payload 332 */ 333 if (pwdp->mi_pwd_first == NULL) { 334 pwdp->mi_pwd_first = wsp->walk_addr; 335 return (WALK_NEXT); 336 } 337 338 if (mio->mi_o_isdev == B_FALSE) { 339 /* mio is a module */ 340 if (!(arg->mi_pwa_flags & MI_PAYLOAD_MODULE)) 341 return (WALK_NEXT); 342 } else { 343 /* mio is a device */ 344 if (!(arg->mi_pwa_flags & MI_PAYLOAD_DEVICE)) 345 return (WALK_NEXT); 346 } 347 348 if (mdb_vread(payload, arg->mi_pwa_size, payload_kaddr) == -1) { 349 mdb_warn("failed to read payload at %p", payload_kaddr); 350 return (WALK_ERR); 351 } 352 353 return (wsp->walk_callback(payload_kaddr, payload, wsp->walk_cbdata)); 354 } 355 356 void 357 mi_payload_walk_fini(mdb_walk_state_t *wsp) 358 { 359 const mi_payload_walk_arg_t *arg = wsp->walk_arg; 360 361 delete_mi_payload_walk_data(wsp->walk_data, arg->mi_pwa_size); 362 } 363 364 const mi_payload_walk_arg_t mi_ar_arg = { 365 "arp", "ar_g_head", sizeof (ar_t), 366 MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 367 }; 368 369 const mi_payload_walk_arg_t mi_icmp_arg = { 370 "icmp", "icmp_g_head", sizeof (icmp_t), 371 MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 372 }; 373 374 const mi_payload_walk_arg_t mi_ill_arg = 375 { "ip", "ip_g_head", sizeof (ill_t), MI_PAYLOAD_MODULE }; 376 377 int 378 sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 379 { 380 const char *optf = NULL; 381 const char *optt = NULL; 382 const char *optp = NULL; 383 int family, type, proto; 384 int filter = 0; 385 struct sonode so; 386 387 if (!(flags & DCMD_ADDRSPEC)) { 388 if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc, 389 argv) == -1) { 390 mdb_warn("failed to walk sonode"); 391 return (DCMD_ERR); 392 } 393 394 return (DCMD_OK); 395 } 396 397 if (mdb_getopts(argc, argv, 398 'f', MDB_OPT_STR, &optf, 399 't', MDB_OPT_STR, &optt, 400 'p', MDB_OPT_STR, &optp, 401 NULL) != argc) 402 return (DCMD_USAGE); 403 404 if (optf != NULL) { 405 if (strcmp("inet", optf) == 0) 406 family = AF_INET; 407 else if (strcmp("inet6", optf) == 0) 408 family = AF_INET6; 409 else if (strcmp("unix", optf) == 0) 410 family = AF_UNIX; 411 else 412 family = mdb_strtoull(optf); 413 filter = 1; 414 } 415 416 if (optt != NULL) { 417 if (strcmp("stream", optt) == 0) 418 type = SOCK_STREAM; 419 else if (strcmp("dgram", optt) == 0) 420 type = SOCK_DGRAM; 421 else if (strcmp("raw", optt) == 0) 422 type = SOCK_RAW; 423 else 424 type = mdb_strtoull(optt); 425 filter = 1; 426 } 427 428 if (optp != NULL) { 429 proto = mdb_strtoull(optp); 430 filter = 1; 431 } 432 433 if (DCMD_HDRSPEC(flags) && !filter) { 434 mdb_printf("%<u>%-?s Family Type Proto State Mode Flag " 435 "AccessVP%</u>\n", "Sonode:"); 436 } 437 438 if (mdb_vread(&so, sizeof (so), addr) == -1) { 439 mdb_warn("failed to read sonode at %p", addr); 440 return (DCMD_ERR); 441 } 442 443 if ((optf != NULL) && (so.so_family != family)) 444 return (DCMD_OK); 445 446 if ((optt != NULL) && (so.so_type != type)) 447 return (DCMD_OK); 448 449 if ((optp != NULL) && (so.so_protocol != proto)) 450 return (DCMD_OK); 451 452 if (filter) { 453 mdb_printf("%0?p\n", addr); 454 return (DCMD_OK); 455 } 456 457 mdb_printf("%0?p ", addr); 458 459 switch (so.so_family) { 460 case AF_UNIX: 461 mdb_printf("unix "); 462 break; 463 case AF_INET: 464 mdb_printf("inet "); 465 break; 466 case AF_INET6: 467 mdb_printf("inet6 "); 468 break; 469 default: 470 mdb_printf("%6hi", so.so_family); 471 } 472 473 switch (so.so_type) { 474 case SOCK_STREAM: 475 mdb_printf(" strm"); 476 break; 477 case SOCK_DGRAM: 478 mdb_printf(" dgrm"); 479 break; 480 case SOCK_RAW: 481 mdb_printf(" raw "); 482 break; 483 default: 484 mdb_printf(" %4hi", so.so_type); 485 } 486 487 mdb_printf(" %5hi %05x %04x %04hx %0?p\n", 488 so.so_protocol, so.so_state, so.so_mode, 489 so.so_flag, so.so_accessvp); 490 491 return (DCMD_OK); 492 } 493 494 #define MI_PAYLOAD 0x1 495 #define MI_DEVICE 0x2 496 #define MI_MODULE 0x4 497 498 int 499 mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 500 { 501 uint_t opts = 0; 502 MI_O mio; 503 504 if (!(flags & DCMD_ADDRSPEC)) 505 return (DCMD_USAGE); 506 507 if (mdb_getopts(argc, argv, 508 'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts, 509 'd', MDB_OPT_SETBITS, MI_DEVICE, &opts, 510 'm', MDB_OPT_SETBITS, MI_MODULE, &opts, 511 NULL) != argc) 512 return (DCMD_USAGE); 513 514 if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) { 515 mdb_warn("at most one filter, d for devices or m " 516 "for modules, may be specified\n"); 517 return (DCMD_USAGE); 518 } 519 520 if ((opts == 0) && (DCMD_HDRSPEC(flags))) { 521 mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n", 522 "MI_O", "Next", "Prev"); 523 } 524 525 if (mdb_vread(&mio, sizeof (mio), addr) == -1) { 526 mdb_warn("failed to read mi object MI_O at %p", addr); 527 return (DCMD_ERR); 528 } 529 530 if (opts != 0) { 531 if (mio.mi_o_isdev == B_FALSE) { 532 /* mio is a module */ 533 if (!(opts & MI_MODULE) && (opts & MI_DEVICE)) 534 return (DCMD_OK); 535 } else { 536 /* mio is a device */ 537 if (!(opts & MI_DEVICE) && (opts & MI_MODULE)) 538 return (DCMD_OK); 539 } 540 541 if (opts & MI_PAYLOAD) 542 mdb_printf("%p\n", addr + sizeof (MI_O)); 543 else 544 mdb_printf("%p\n", addr); 545 return (DCMD_OK); 546 } 547 548 mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev); 549 550 if (mio.mi_o_isdev == B_FALSE) 551 mdb_printf("FALSE"); 552 else 553 mdb_printf("TRUE "); 554 555 mdb_printf(" %0?p\n", mio.mi_o_dev); 556 557 return (DCMD_OK); 558 } 559 560 static void 561 netstat_tcp_verbose_pr(const tcp_t *tcp) 562 { 563 mdb_printf(" %5i %08x %08x %5i %08x %08x %5li %5i\n", 564 tcp->tcp_swnd, tcp->tcp_snxt, tcp->tcp_suna, tcp->tcp_rwnd, 565 tcp->tcp_rack, tcp->tcp_rnxt, tcp->tcp_rto, tcp->tcp_mss); 566 } 567 568 /*ARGSUSED*/ 569 static int 570 netstat_tcp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data, int af) 571 { 572 const uintptr_t opts = (uintptr_t)cb_data; 573 static size_t itc_size = 0; 574 uintptr_t tcp_kaddr; 575 conn_t *connp; 576 tcp_t *tcp; 577 578 if (itc_size == 0) { 579 mdb_ctf_id_t id; 580 581 if (mdb_ctf_lookup_by_name("itc_t", &id) != 0) { 582 mdb_warn("failed to lookup type 'itc_t'"); 583 return (WALK_ERR); 584 } 585 itc_size = mdb_ctf_type_size(id); 586 } 587 588 connp = (conn_t *)mdb_alloc(itc_size, UM_SLEEP | UM_GC); 589 590 if (mdb_vread(connp, itc_size, kaddr) == -1) { 591 mdb_warn("failed to read connection info at %p", kaddr); 592 return (WALK_ERR); 593 } 594 595 tcp_kaddr = (uintptr_t)connp->conn_tcp; 596 tcp = (tcp_t *)((uintptr_t)connp + (tcp_kaddr - kaddr)); 597 598 if ((uintptr_t)tcp < (uintptr_t)connp || 599 (uintptr_t)(tcp + 1) > (uintptr_t)connp + itc_size || 600 (uintptr_t)tcp->tcp_connp != kaddr) { 601 mdb_warn("conn_tcp %p is invalid", tcp_kaddr); 602 return (WALK_NEXT); 603 } 604 connp->conn_tcp = tcp; 605 tcp->tcp_connp = connp; 606 607 if (!((opts & NETSTAT_ALL) || net_tcp_active(tcp)) || 608 (af == AF_INET && !net_tcp_ipv4(tcp)) || 609 (af == AF_INET6 && !net_tcp_ipv6(tcp))) { 610 return (WALK_NEXT); 611 } 612 613 mdb_printf("%0?p %2i ", tcp_kaddr, tcp->tcp_state); 614 if (af == AF_INET) { 615 net_ipv4addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 616 mdb_printf(" "); 617 net_ipv4addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 618 } else if (af == AF_INET6) { 619 net_ipv6addrport_pr(&tcp->tcp_ip_src_v6, tcp->tcp_lport); 620 mdb_printf(" "); 621 net_ipv6addrport_pr(&tcp->tcp_remote_v6, tcp->tcp_fport); 622 } 623 mdb_printf(" %4i\n", connp->conn_zoneid); 624 625 if (opts & NETSTAT_VERBOSE) 626 netstat_tcp_verbose_pr(tcp); 627 628 return (WALK_NEXT); 629 } 630 631 static int 632 netstat_tcpv4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 633 { 634 return (netstat_tcp_cb(kaddr, walk_data, cb_data, AF_INET)); 635 } 636 637 static int 638 netstat_tcpv6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 639 { 640 return (netstat_tcp_cb(kaddr, walk_data, cb_data, AF_INET6)); 641 } 642 643 /*ARGSUSED*/ 644 static int 645 netstat_udp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data, int af) 646 { 647 const uintptr_t opts = (uintptr_t)cb_data; 648 udp_t udp; 649 conn_t connp; 650 651 if (mdb_vread(&udp, sizeof (udp_t), kaddr) == -1) { 652 mdb_warn("failed to read udp at %p", kaddr); 653 return (WALK_ERR); 654 } 655 656 if (mdb_vread(&connp, sizeof (conn_t), 657 (uintptr_t)udp.udp_connp) == -1) { 658 mdb_warn("failed to read udp_connp at %p", 659 (uintptr_t)udp.udp_connp); 660 return (WALK_ERR); 661 } 662 663 if (!((opts & NETSTAT_ALL) || net_udp_active(&udp)) || 664 (af == AF_INET && !net_udp_ipv4(&udp)) || 665 (af == AF_INET6 && !net_udp_ipv6(&udp))) { 666 return (WALK_NEXT); 667 } 668 669 mdb_printf("%0?p %2i ", kaddr, udp.udp_state); 670 if (af == AF_INET) { 671 net_ipv4addrport_pr(&udp.udp_v6src, udp.udp_port); 672 mdb_printf(" "); 673 net_ipv4addrport_pr(&udp.udp_v6dst, udp.udp_dstport); 674 } else if (af == AF_INET6) { 675 net_ipv6addrport_pr(&udp.udp_v6src, udp.udp_port); 676 mdb_printf(" "); 677 net_ipv6addrport_pr(&udp.udp_v6dst, udp.udp_dstport); 678 } 679 mdb_printf(" %4i\n", connp.conn_zoneid); 680 681 return (WALK_NEXT); 682 } 683 684 static int 685 netstat_udpv4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 686 { 687 return (netstat_udp_cb(kaddr, walk_data, cb_data, AF_INET)); 688 } 689 690 static int 691 netstat_udpv6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 692 { 693 return (netstat_udp_cb(kaddr, walk_data, cb_data, AF_INET6)); 694 } 695 696 /* 697 * print the address of a unix domain socket 698 * 699 * so is the address of a AF_UNIX struct sonode in mdb's address space 700 * soa is the address of the struct soaddr to print 701 * 702 * returns 0 on success, -1 otherwise 703 */ 704 static int 705 netstat_unix_name_pr(const struct sonode *so, const struct soaddr *soa) 706 { 707 const char none[] = " (none)"; 708 709 if ((so->so_state & SS_ISBOUND) && (soa->soa_len != 0)) { 710 if (so->so_state & SS_FADDR_NOXLATE) { 711 mdb_printf("%-14s ", " (socketpair)"); 712 } else { 713 if (soa->soa_len > sizeof (sa_family_t)) { 714 char addr[MAXPATHLEN + 1]; 715 716 if (mdb_readstr(addr, sizeof (addr), 717 (uintptr_t)&soa->soa_sa->sa_data) == -1) { 718 mdb_warn("failed to read unix address " 719 "at %p", &soa->soa_sa->sa_data); 720 return (-1); 721 } 722 723 mdb_printf("%-14s ", addr); 724 } else { 725 mdb_printf("%-14s ", none); 726 } 727 } 728 } else { 729 mdb_printf("%-14s ", none); 730 } 731 732 return (0); 733 } 734 735 /* based on sockfs_snapshot */ 736 /*ARGSUSED*/ 737 static int 738 netstat_unix_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 739 { 740 const struct sonode *so = walk_data; 741 742 if (so->so_accessvp == NULL) 743 return (WALK_NEXT); 744 745 if (so->so_family != AF_UNIX) { 746 mdb_warn("sonode of family %hi at %p\n", so->so_family, kaddr); 747 return (WALK_ERR); 748 } 749 750 mdb_printf("%-?p ", kaddr); 751 752 switch (so->so_serv_type) { 753 case T_CLTS: 754 mdb_printf("%-10s ", "dgram"); 755 break; 756 case T_COTS: 757 mdb_printf("%-10s ", "stream"); 758 break; 759 case T_COTS_ORD: 760 mdb_printf("%-10s ", "stream-ord"); 761 break; 762 default: 763 mdb_printf("%-10i ", so->so_serv_type); 764 } 765 766 if ((so->so_state & SS_ISBOUND) && 767 (so->so_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 768 mdb_printf("%0?p ", so->so_ux_laddr.soua_vp); 769 } else { 770 mdb_printf("%0?p ", NULL); 771 } 772 773 if ((so->so_state & SS_ISCONNECTED) && 774 (so->so_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 775 mdb_printf("%0?p ", so->so_ux_faddr.soua_vp); 776 } else { 777 mdb_printf("%0?p ", NULL); 778 } 779 780 if (netstat_unix_name_pr(so, &so->so_laddr) == -1) 781 return (WALK_ERR); 782 783 if (netstat_unix_name_pr(so, &so->so_faddr) == -1) 784 return (WALK_ERR); 785 786 mdb_printf("%4i\n", so->so_zoneid); 787 788 return (WALK_NEXT); 789 } 790 791 static void 792 netstat_tcp_verbose_header_pr(void) 793 { 794 mdb_printf(" %<u>%-5s %-8s %-8s %-5s %-8s %-8s %5s %5s%</u>\n", 795 "Swind", "Snext", "Suna", "Rwind", "Rack", "Rnext", "Rto", "Mss"); 796 } 797 798 static void 799 get_ifname(const ire_t *ire, char *intf) 800 { 801 ill_t ill; 802 803 *intf = '\0'; 804 if (ire->ire_type == IRE_CACHE) { 805 queue_t stq; 806 807 if (mdb_vread(&stq, sizeof (stq), (uintptr_t)ire->ire_stq) == 808 -1) 809 return; 810 if (mdb_vread(&ill, sizeof (ill), (uintptr_t)stq.q_ptr) == -1) 811 return; 812 (void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length), 813 (uintptr_t)ill.ill_name); 814 } else if (ire->ire_ipif != NULL) { 815 ipif_t ipif; 816 char *cp; 817 818 if (mdb_vread(&ipif, sizeof (ipif), 819 (uintptr_t)ire->ire_ipif) == -1) 820 return; 821 if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ipif.ipif_ill) == 822 -1) 823 return; 824 (void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length), 825 (uintptr_t)ill.ill_name); 826 if (ipif.ipif_id != 0) { 827 cp = intf + strlen(intf); 828 (void) mdb_snprintf(cp, LIFNAMSIZ + 1 - (cp - intf), 829 ":%u", ipif.ipif_id); 830 } 831 } 832 } 833 834 static void 835 get_v4flags(const ire_t *ire, char *flags) 836 { 837 (void) strcpy(flags, "U"); 838 if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX || 839 ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT) 840 (void) strcat(flags, "G"); 841 if (ire->ire_mask == IP_HOST_MASK) 842 (void) strcat(flags, "H"); 843 if (ire->ire_type == IRE_HOST_REDIRECT) 844 (void) strcat(flags, "D"); 845 if (ire->ire_type == IRE_CACHE) 846 (void) strcat(flags, "A"); 847 if (ire->ire_type == IRE_BROADCAST) 848 (void) strcat(flags, "B"); 849 if (ire->ire_type == IRE_LOCAL) 850 (void) strcat(flags, "L"); 851 if (ire->ire_flags & RTF_MULTIRT) 852 (void) strcat(flags, "M"); 853 if (ire->ire_flags & RTF_SETSRC) 854 (void) strcat(flags, "S"); 855 } 856 857 static int 858 ip_mask_to_plen(ipaddr_t mask) 859 { 860 int i; 861 862 if (mask == 0) 863 return (0); 864 for (i = 32; i > 0; i--, mask >>= 1) 865 if (mask & 1) 866 break; 867 return (i); 868 } 869 870 static int 871 netstat_irev4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 872 { 873 const ire_t *ire = walk_data; 874 uint_t *opts = cb_data; 875 ipaddr_t gate; 876 char flags[10], intf[LIFNAMSIZ + 1]; 877 878 if (ire->ire_ipversion != IPV4_VERSION || ire->ire_in_src_addr != 0 || 879 ire->ire_in_ill != NULL) 880 return (WALK_NEXT); 881 882 if (!(*opts & NETSTAT_ALL) && (ire->ire_type == IRE_CACHE || 883 ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL)) 884 return (WALK_NEXT); 885 886 if (*opts & NETSTAT_FIRST) { 887 *opts &= ~NETSTAT_FIRST; 888 mdb_printf("%<u>%s Table: IPv4%</u>\n", 889 (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 890 if (*opts & NETSTAT_VERBOSE) { 891 mdb_printf("%<u>%-?s %-*s %-*s %-*s Device Mxfrg Rtt " 892 " Ref Flg Out In/Fwd%</u>\n", 893 "Address", ADDR_V4_WIDTH, "Destination", 894 ADDR_V4_WIDTH, "Mask", ADDR_V4_WIDTH, "Gateway"); 895 } else { 896 mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use " 897 "Interface%</u>\n", 898 "Address", ADDR_V4_WIDTH, "Destination", 899 ADDR_V4_WIDTH, "Gateway"); 900 } 901 } 902 903 gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ? 904 ire->ire_src_addr : ire->ire_gateway_addr; 905 906 get_v4flags(ire, flags); 907 908 get_ifname(ire, intf); 909 910 if (*opts & NETSTAT_VERBOSE) { 911 mdb_printf("%?p %-*I %-*I %-*I %-6s %5u%c %4u %3u %-3s %5u " 912 "%u\n", kaddr, ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, 913 ire->ire_mask, ADDR_V4_WIDTH, gate, intf, 914 ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 915 ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags, 916 ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 917 } else { 918 mdb_printf("%?p %-*I %-*I %-5s %4u %5u %s\n", kaddr, 919 ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, gate, flags, 920 ire->ire_refcnt, 921 ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 922 } 923 924 return (WALK_NEXT); 925 } 926 927 static int 928 netstat_irev4src_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 929 { 930 const ire_t *ire = walk_data; 931 uint_t *opts = cb_data; 932 ipaddr_t gate; 933 char flags[10], intf[LIFNAMSIZ + 1], srcif[LIFNAMSIZ + 1]; 934 char dest[ADDR_V4_WIDTH + 3 + 1]; 935 ill_t ill; 936 937 if (ire->ire_ipversion != IPV4_VERSION || 938 (ire->ire_in_src_addr == 0 && ire->ire_in_ill == NULL)) 939 return (WALK_NEXT); 940 941 if (!(*opts & NETSTAT_ALL) && (ire->ire_type == IRE_CACHE || 942 ire->ire_type == IRE_BROADCAST || ire->ire_type == IRE_LOCAL)) 943 return (WALK_NEXT); 944 945 if (*opts & NETSTAT_FIRST) { 946 *opts &= ~NETSTAT_FIRST; 947 mdb_printf("\n%<u>%s Table: IPv4 Source-Specific%</u>\n", 948 (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 949 if (*opts & NETSTAT_VERBOSE) { 950 mdb_printf("%<u>%-?s %-*s In If %-*s %-*s " 951 "Out If Mxfrg Rtt Ref Flg Out In/Fwd" 952 "%</u>\n", 953 "Address", ADDR_V4_WIDTH+3, "Destination", 954 ADDR_V4_WIDTH, "Source", ADDR_V4_WIDTH, "Gateway"); 955 } else { 956 mdb_printf("%<u>%-?s %-*s In If %-*s %-*s Flags " 957 "Ref Use Out If%</u>\n", 958 "Address", ADDR_V4_WIDTH+3, "Destination", 959 ADDR_V4_WIDTH, "Source", ADDR_V4_WIDTH, "Gateway"); 960 } 961 } 962 963 gate = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK|IRE_BROADCAST)) ? 964 ire->ire_src_addr : ire->ire_gateway_addr; 965 966 get_v4flags(ire, flags); 967 968 get_ifname(ire, intf); 969 970 srcif[0] = '\0'; 971 if (mdb_vread(&ill, sizeof (ill), (uintptr_t)ire->ire_in_ill) != -1) 972 (void) mdb_readstr(srcif, MIN(LIFNAMSIZ, ill.ill_name_length), 973 (uintptr_t)ill.ill_name); 974 975 if (ire->ire_in_src_addr != 0 && ire->ire_addr == 0 && 976 ire->ire_mask == 0) 977 strcpy(dest, " --"); 978 else 979 mdb_snprintf(dest, sizeof (dest), "%I/%d", ire->ire_addr, 980 ip_mask_to_plen(ire->ire_mask)); 981 982 if (*opts & NETSTAT_VERBOSE) { 983 mdb_printf("%?p %-*s %-11s %-*I %-*I %-11s %5u%c %4u %3u %-3s " 984 "%5u %u\n", kaddr, ADDR_V4_WIDTH+3, dest, srcif, 985 ADDR_V4_WIDTH, ire->ire_in_src_addr, ADDR_V4_WIDTH, gate, 986 intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 987 ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, flags, 988 ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 989 } else { 990 mdb_printf("%?p %-*s %-8s %-*I %-*I %-5s %4u %5u %s\n", kaddr, 991 ADDR_V4_WIDTH+3, dest, srcif, ADDR_V4_WIDTH, 992 ire->ire_in_src_addr, ADDR_V4_WIDTH, gate, flags, 993 ire->ire_refcnt, 994 ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 995 } 996 997 return (WALK_NEXT); 998 } 999 1000 int 1001 ip_mask_to_plen_v6(const in6_addr_t *v6mask) 1002 { 1003 int plen; 1004 int i; 1005 uint32_t val; 1006 1007 for (i = 3; i >= 0; i--) 1008 if (v6mask->s6_addr32[i] != 0) 1009 break; 1010 if (i < 0) 1011 return (0); 1012 plen = 32 + 32 * i; 1013 val = v6mask->s6_addr32[i]; 1014 while (!(val & 1)) { 1015 val >>= 1; 1016 plen--; 1017 } 1018 1019 return (plen); 1020 } 1021 1022 static int 1023 netstat_irev6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 1024 { 1025 const ire_t *ire = walk_data; 1026 uint_t *opts = cb_data; 1027 const in6_addr_t *gatep; 1028 char deststr[ADDR_V6_WIDTH + 5]; 1029 char flags[10], intf[LIFNAMSIZ + 1]; 1030 int masklen; 1031 1032 if (ire->ire_ipversion != IPV6_VERSION) 1033 return (WALK_NEXT); 1034 1035 if (!(*opts & NETSTAT_ALL) && ire->ire_type == IRE_CACHE) 1036 return (WALK_NEXT); 1037 1038 if (*opts & NETSTAT_FIRST) { 1039 *opts &= ~NETSTAT_FIRST; 1040 mdb_printf("\n%<u>%s Table: IPv6%</u>\n", 1041 (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 1042 if (*opts & NETSTAT_VERBOSE) { 1043 mdb_printf("%<u>%-?s %-*s %-*s If PMTU Rtt Ref " 1044 "Flags Out In/Fwd%</u>\n", 1045 "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 1046 ADDR_V6_WIDTH, "Gateway"); 1047 } else { 1048 mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use If" 1049 "%</u>\n", 1050 "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 1051 ADDR_V6_WIDTH, "Gateway"); 1052 } 1053 } 1054 1055 gatep = (ire->ire_type & (IRE_INTERFACE|IRE_LOOPBACK)) ? 1056 &ire->ire_src_addr_v6 : &ire->ire_gateway_addr_v6; 1057 1058 masklen = ip_mask_to_plen_v6(&ire->ire_mask_v6); 1059 (void) mdb_snprintf(deststr, sizeof (deststr), "%N/%d", 1060 &ire->ire_addr_v6, masklen); 1061 1062 (void) strcpy(flags, "U"); 1063 if (ire->ire_type == IRE_DEFAULT || ire->ire_type == IRE_PREFIX || 1064 ire->ire_type == IRE_HOST || ire->ire_type == IRE_HOST_REDIRECT) 1065 (void) strcat(flags, "G"); 1066 if (masklen == IPV6_ABITS) 1067 (void) strcat(flags, "H"); 1068 if (ire->ire_type == IRE_HOST_REDIRECT) 1069 (void) strcat(flags, "D"); 1070 if (ire->ire_type == IRE_CACHE) 1071 (void) strcat(flags, "A"); 1072 if (ire->ire_type == IRE_LOCAL) 1073 (void) strcat(flags, "L"); 1074 if (ire->ire_flags & RTF_MULTIRT) 1075 (void) strcat(flags, "M"); 1076 if (ire->ire_flags & RTF_SETSRC) 1077 (void) strcat(flags, "S"); 1078 1079 get_ifname(ire, intf); 1080 1081 if (*opts & NETSTAT_VERBOSE) { 1082 mdb_printf("%?p %-*s %-*N %-5s %5u%c %5u %3u %-5s %6u %u\n", 1083 kaddr, ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, 1084 intf, ire->ire_max_frag, ire->ire_frag_flag ? '*' : ' ', 1085 ire->ire_uinfo.iulp_rtt, ire->ire_refcnt, 1086 flags, ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 1087 } else { 1088 mdb_printf("%?p %-*s %-*N %-5s %3u %6u %s\n", kaddr, 1089 ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, flags, 1090 ire->ire_refcnt, 1091 ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 1092 } 1093 1094 return (WALK_NEXT); 1095 } 1096 1097 /*ARGSUSED*/ 1098 int 1099 netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1100 { 1101 uint_t opts = 0; 1102 const char *optf = NULL; 1103 const char *optP = NULL; 1104 1105 if (mdb_getopts(argc, argv, 1106 'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts, 1107 'f', MDB_OPT_STR, &optf, 1108 'P', MDB_OPT_STR, &optP, 1109 'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts, 1110 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts, 1111 NULL) != argc) 1112 return (DCMD_USAGE); 1113 1114 if (optP != NULL) { 1115 if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0)) 1116 return (DCMD_USAGE); 1117 if (opts & NETSTAT_ROUTE) 1118 return (DCMD_USAGE); 1119 } 1120 1121 if (optf == NULL) 1122 opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX; 1123 else if (strcmp("inet", optf) == 0) 1124 opts |= NETSTAT_V4; 1125 else if (strcmp("inet6", optf) == 0) 1126 opts |= NETSTAT_V6; 1127 else if (strcmp("unix", optf) == 0) 1128 opts |= NETSTAT_UNIX; 1129 else 1130 return (DCMD_USAGE); 1131 1132 if (opts & NETSTAT_ROUTE) { 1133 if (!(opts & (NETSTAT_V4|NETSTAT_V6))) 1134 return (DCMD_USAGE); 1135 if (opts & NETSTAT_V4) { 1136 opts |= NETSTAT_FIRST; 1137 if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) { 1138 mdb_warn("failed to walk ip`ire"); 1139 return (DCMD_ERR); 1140 } 1141 opts |= NETSTAT_FIRST; 1142 if (mdb_walk("ip`ire", netstat_irev4src_cb, 1143 &opts) == -1) { 1144 mdb_warn("failed to walk ip`ire"); 1145 return (DCMD_ERR); 1146 } 1147 } 1148 if (opts & NETSTAT_V6) { 1149 opts |= NETSTAT_FIRST; 1150 if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) { 1151 mdb_warn("failed to walk ip`ire"); 1152 return (DCMD_ERR); 1153 } 1154 } 1155 return (DCMD_OK); 1156 } 1157 1158 if ((optP == NULL) || (strcmp("tcp", optP) == 0)) { 1159 if ((optf == NULL) || (strcmp("inet", optf) == 0)) { 1160 /* Print TCPv4 connection */ 1161 mdb_printf( 1162 "%<u>%-?s St %*s %*s %s%</u>\n", 1163 "TCPv4", ADDR_V4_WIDTH, "Local Address", 1164 ADDR_V4_WIDTH, "Remote Address", "Zone"); 1165 1166 if (opts & NETSTAT_VERBOSE) 1167 netstat_tcp_verbose_header_pr(); 1168 1169 if (mdb_walk("ipcl_tcpconn_cache", netstat_tcpv4_cb, 1170 (void *)(uintptr_t)opts) == -1) { 1171 mdb_warn("failed to walk ipcl_tcpconn_cache"); 1172 return (DCMD_ERR); 1173 } 1174 } 1175 1176 if ((optf == NULL) || (strcmp("inet6", optf) == 0)) { 1177 /* Print TCPv6 connection */ 1178 mdb_printf( 1179 "%<u>%-?s St %*s %*s %s\n%</u>", 1180 "TCPv6", ADDR_V6_WIDTH, "Local Address", 1181 ADDR_V6_WIDTH, "Remote Address", "Zone"); 1182 1183 if (opts & NETSTAT_VERBOSE) 1184 netstat_tcp_verbose_header_pr(); 1185 1186 if (mdb_walk("ipcl_tcpconn_cache", netstat_tcpv6_cb, 1187 (void *)(uintptr_t)opts) == -1) { 1188 mdb_warn("failed to walk ipcl_tcpconn_cache"); 1189 return (DCMD_ERR); 1190 } 1191 } 1192 } 1193 1194 if ((optP == NULL) || (strcmp("udp", optP) == 0)) { 1195 if ((optf == NULL) || (strcmp("inet", optf) == 0)) { 1196 /* Print UDPv4 connection */ 1197 mdb_printf( 1198 "%<u>%-?s St %*s %*s %s\n%</u>", 1199 "UDPv4", ADDR_V4_WIDTH, "Local Address", 1200 ADDR_V4_WIDTH, "Remote Address", "Zone"); 1201 1202 if (mdb_walk("udp_cache", netstat_udpv4_cb, 1203 (void *)(uintptr_t)opts) == -1) { 1204 mdb_warn("failed to walk genunix`udp"); 1205 return (DCMD_ERR); 1206 } 1207 1208 } 1209 1210 if ((optf == NULL) || (strcmp("inet6", optf) == 0)) { 1211 /* Print UDPv6 connection */ 1212 mdb_printf( 1213 "%<u>%-?s St %*s %*s %s\n%</u>", 1214 "UDPv6", ADDR_V6_WIDTH, "Local Address", 1215 ADDR_V6_WIDTH, "Remote Address", "Zone"); 1216 1217 if (mdb_walk("udp_cache", netstat_udpv6_cb, 1218 (void *)(uintptr_t)opts) == -1) { 1219 mdb_warn("failed to walk genunix`udp"); 1220 return (DCMD_ERR); 1221 } 1222 } 1223 } 1224 1225 if (((optf == NULL) || (strcmp("unix", optf) == 0)) && (optP == NULL)) { 1226 /* Print Unix Domain Sockets */ 1227 mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n", 1228 "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr", 1229 "Remote Addr", "Zone"); 1230 1231 if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) { 1232 mdb_warn("failed to walk genunix`sonode"); 1233 return (DCMD_ERR); 1234 } 1235 } 1236 1237 return (DCMD_OK); 1238 } 1239