1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1676 jpk * Common Development and Distribution License (the "License"). 6 1676 jpk * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 9089 Vasumathi * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #include <mdb/mdb_modapi.h> 27 0 stevel #include <mdb/mdb_ks.h> 28 0 stevel #include <mdb/mdb_ctf.h> 29 0 stevel #include <sys/types.h> 30 0 stevel #include <sys/tihdr.h> 31 0 stevel #include <inet/led.h> 32 0 stevel #include <inet/common.h> 33 0 stevel #include <netinet/in.h> 34 0 stevel #include <netinet/ip6.h> 35 0 stevel #include <netinet/icmp6.h> 36 0 stevel #include <inet/ip.h> 37 0 stevel #include <inet/ip6.h> 38 0 stevel #include <inet/ipclassifier.h> 39 0 stevel #include <inet/tcp.h> 40 0 stevel #include <sys/stream.h> 41 0 stevel #include <sys/vfs.h> 42 0 stevel #include <sys/stropts.h> 43 0 stevel #include <sys/tpicommon.h> 44 0 stevel #include <sys/socket.h> 45 0 stevel #include <sys/socketvar.h> 46 0 stevel #include <sys/cred_impl.h> 47 0 stevel #include <inet/udp_impl.h> 48 0 stevel #include <inet/rawip_impl.h> 49 0 stevel #include <inet/mi.h> 50 8348 Eric #include <fs/sockfs/socktpi_impl.h> 51 10491 Rishi #include <net/bridge_impl.h> 52 10491 Rishi #include <io/trill_impl.h> 53 10491 Rishi #include <sys/mac_impl.h> 54 0 stevel 55 0 stevel #define ADDR_V6_WIDTH 23 56 0 stevel #define ADDR_V4_WIDTH 15 57 0 stevel 58 1676 jpk #define NETSTAT_ALL 0x01 59 1676 jpk #define NETSTAT_VERBOSE 0x02 60 1676 jpk #define NETSTAT_ROUTE 0x04 61 1676 jpk #define NETSTAT_V4 0x08 62 1676 jpk #define NETSTAT_V6 0x10 63 1676 jpk #define NETSTAT_UNIX 0x20 64 1676 jpk 65 1676 jpk #define NETSTAT_FIRST 0x80000000u 66 3448 dh155122 67 9089 Vasumathi typedef struct netstat_cb_data_s { 68 9089 Vasumathi uint_t opts; 69 9089 Vasumathi conn_t conn; 70 9089 Vasumathi int af; 71 9089 Vasumathi } netstat_cb_data_t; 72 3448 dh155122 73 3448 dh155122 int 74 3448 dh155122 icmp_stacks_walk_init(mdb_walk_state_t *wsp) 75 3448 dh155122 { 76 3448 dh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 77 3448 dh155122 mdb_warn("can't walk 'netstack'"); 78 3448 dh155122 return (WALK_ERR); 79 3448 dh155122 } 80 3448 dh155122 return (WALK_NEXT); 81 3448 dh155122 } 82 3448 dh155122 83 3448 dh155122 int 84 3448 dh155122 icmp_stacks_walk_step(mdb_walk_state_t *wsp) 85 3448 dh155122 { 86 3448 dh155122 uintptr_t kaddr; 87 3448 dh155122 netstack_t nss; 88 3448 dh155122 89 3448 dh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 90 3448 dh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 91 3448 dh155122 return (WALK_ERR); 92 3448 dh155122 } 93 3448 dh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_ICMP]; 94 3448 dh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 95 3448 dh155122 } 96 3448 dh155122 97 3448 dh155122 int 98 3448 dh155122 tcp_stacks_walk_init(mdb_walk_state_t *wsp) 99 3448 dh155122 { 100 3448 dh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 101 3448 dh155122 mdb_warn("can't walk 'netstack'"); 102 3448 dh155122 return (WALK_ERR); 103 3448 dh155122 } 104 3448 dh155122 return (WALK_NEXT); 105 3448 dh155122 } 106 3448 dh155122 107 3448 dh155122 int 108 3448 dh155122 tcp_stacks_walk_step(mdb_walk_state_t *wsp) 109 3448 dh155122 { 110 3448 dh155122 uintptr_t kaddr; 111 3448 dh155122 netstack_t nss; 112 3448 dh155122 113 3448 dh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 114 3448 dh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 115 3448 dh155122 return (WALK_ERR); 116 3448 dh155122 } 117 3448 dh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_TCP]; 118 3448 dh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 119 3448 dh155122 } 120 3448 dh155122 121 3448 dh155122 int 122 3448 dh155122 udp_stacks_walk_init(mdb_walk_state_t *wsp) 123 3448 dh155122 { 124 3448 dh155122 if (mdb_layered_walk("netstack", wsp) == -1) { 125 3448 dh155122 mdb_warn("can't walk 'netstack'"); 126 3448 dh155122 return (WALK_ERR); 127 3448 dh155122 } 128 3448 dh155122 return (WALK_NEXT); 129 3448 dh155122 } 130 3448 dh155122 131 3448 dh155122 int 132 3448 dh155122 udp_stacks_walk_step(mdb_walk_state_t *wsp) 133 3448 dh155122 { 134 3448 dh155122 uintptr_t kaddr; 135 3448 dh155122 netstack_t nss; 136 3448 dh155122 137 3448 dh155122 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 138 3448 dh155122 mdb_warn("can't read netstack at %p", wsp->walk_addr); 139 3448 dh155122 return (WALK_ERR); 140 3448 dh155122 } 141 3448 dh155122 kaddr = (uintptr_t)nss.netstack_modules[NS_UDP]; 142 3448 dh155122 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 143 3448 dh155122 } 144 0 stevel 145 0 stevel /* 146 0 stevel * Print an IPv4 address and port number in a compact and easy to read format 147 0 stevel * The arguments are in network byte order 148 0 stevel */ 149 0 stevel static void 150 0 stevel net_ipv4addrport_pr(const in6_addr_t *nipv6addr, in_port_t nport) 151 0 stevel { 152 0 stevel uint32_t naddr = V4_PART_OF_V6((*nipv6addr)); 153 0 stevel 154 0 stevel mdb_nhconvert(&nport, &nport, sizeof (nport)); 155 0 stevel mdb_printf("%*I.%-5hu", ADDR_V4_WIDTH, naddr, nport); 156 0 stevel } 157 0 stevel 158 0 stevel /* 159 0 stevel * Print an IPv6 address and port number in a compact and easy to read format 160 0 stevel * The arguments are in network byte order 161 0 stevel */ 162 0 stevel static void 163 0 stevel net_ipv6addrport_pr(const in6_addr_t *naddr, in_port_t nport) 164 0 stevel { 165 0 stevel mdb_nhconvert(&nport, &nport, sizeof (nport)); 166 0 stevel mdb_printf("%*N.%-5hu", ADDR_V6_WIDTH, naddr, nport); 167 0 stevel } 168 0 stevel 169 0 stevel static int 170 0 stevel net_tcp_active(const tcp_t *tcp) 171 0 stevel { 172 0 stevel return (tcp->tcp_state >= TCPS_ESTABLISHED); 173 0 stevel } 174 0 stevel 175 0 stevel static int 176 0 stevel net_tcp_ipv4(const tcp_t *tcp) 177 0 stevel { 178 11042 Erik return ((tcp->tcp_connp->conn_ipversion == IPV4_VERSION) || 179 11042 Erik (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_connp->conn_laddr_v6) && 180 0 stevel (tcp->tcp_state <= TCPS_LISTEN))); 181 0 stevel } 182 0 stevel 183 0 stevel static int 184 0 stevel net_tcp_ipv6(const tcp_t *tcp) 185 0 stevel { 186 11042 Erik return (tcp->tcp_connp->conn_ipversion == IPV6_VERSION); 187 0 stevel } 188 0 stevel 189 0 stevel static int 190 0 stevel net_udp_active(const udp_t *udp) 191 0 stevel { 192 741 masputra return ((udp->udp_state == TS_IDLE) || 193 741 masputra (udp->udp_state == TS_DATA_XFER)); 194 0 stevel } 195 0 stevel 196 0 stevel static int 197 0 stevel net_udp_ipv4(const udp_t *udp) 198 0 stevel { 199 11042 Erik return ((udp->udp_connp->conn_ipversion == IPV4_VERSION) || 200 11042 Erik (IN6_IS_ADDR_UNSPECIFIED(&udp->udp_connp->conn_laddr_v6) && 201 0 stevel (udp->udp_state <= TS_IDLE))); 202 0 stevel } 203 0 stevel 204 0 stevel static int 205 0 stevel net_udp_ipv6(const udp_t *udp) 206 0 stevel { 207 11042 Erik return (udp->udp_connp->conn_ipversion == IPV6_VERSION); 208 0 stevel } 209 0 stevel 210 0 stevel int 211 0 stevel sonode_walk_init(mdb_walk_state_t *wsp) 212 0 stevel { 213 0 stevel if (wsp->walk_addr == NULL) { 214 0 stevel GElf_Sym sym; 215 0 stevel struct socklist *slp; 216 0 stevel 217 0 stevel if (mdb_lookup_by_obj("sockfs", "socklist", &sym) == -1) { 218 0 stevel mdb_warn("failed to lookup sockfs`socklist"); 219 0 stevel return (WALK_ERR); 220 0 stevel } 221 0 stevel 222 0 stevel slp = (struct socklist *)(uintptr_t)sym.st_value; 223 0 stevel 224 0 stevel if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), 225 0 stevel (uintptr_t)&slp->sl_list) == -1) { 226 0 stevel mdb_warn("failed to read address of initial sonode " 227 0 stevel "at %p", &slp->sl_list); 228 0 stevel return (WALK_ERR); 229 0 stevel } 230 0 stevel } 231 0 stevel 232 8348 Eric wsp->walk_data = mdb_alloc(sizeof (struct sotpi_sonode), UM_SLEEP); 233 0 stevel return (WALK_NEXT); 234 0 stevel } 235 0 stevel 236 0 stevel int 237 0 stevel sonode_walk_step(mdb_walk_state_t *wsp) 238 0 stevel { 239 0 stevel int status; 240 8348 Eric struct sotpi_sonode *stp; 241 0 stevel 242 0 stevel if (wsp->walk_addr == NULL) 243 0 stevel return (WALK_DONE); 244 0 stevel 245 8348 Eric if (mdb_vread(wsp->walk_data, sizeof (struct sotpi_sonode), 246 0 stevel wsp->walk_addr) == -1) { 247 0 stevel mdb_warn("failed to read sonode at %p", wsp->walk_addr); 248 0 stevel return (WALK_ERR); 249 0 stevel } 250 0 stevel 251 0 stevel status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 252 0 stevel wsp->walk_cbdata); 253 0 stevel 254 8348 Eric stp = wsp->walk_data; 255 0 stevel 256 8348 Eric wsp->walk_addr = (uintptr_t)stp->st_info.sti_next_so; 257 0 stevel return (status); 258 0 stevel } 259 0 stevel 260 0 stevel void 261 0 stevel sonode_walk_fini(mdb_walk_state_t *wsp) 262 0 stevel { 263 8348 Eric mdb_free(wsp->walk_data, sizeof (struct sotpi_sonode)); 264 0 stevel } 265 0 stevel 266 0 stevel struct mi_walk_data { 267 0 stevel uintptr_t mi_wd_miofirst; 268 0 stevel MI_O mi_wd_miodata; 269 0 stevel }; 270 0 stevel 271 0 stevel int 272 0 stevel mi_walk_init(mdb_walk_state_t *wsp) 273 0 stevel { 274 0 stevel struct mi_walk_data *wdp; 275 0 stevel 276 0 stevel if (wsp->walk_addr == NULL) { 277 0 stevel mdb_warn("mi doesn't support global walks\n"); 278 0 stevel return (WALK_ERR); 279 0 stevel } 280 0 stevel 281 0 stevel wdp = mdb_alloc(sizeof (struct mi_walk_data), UM_SLEEP); 282 0 stevel 283 0 stevel /* So that we do not immediately return WALK_DONE below */ 284 0 stevel wdp->mi_wd_miofirst = NULL; 285 0 stevel 286 0 stevel wsp->walk_data = wdp; 287 0 stevel return (WALK_NEXT); 288 0 stevel } 289 0 stevel 290 0 stevel int 291 0 stevel mi_walk_step(mdb_walk_state_t *wsp) 292 0 stevel { 293 0 stevel struct mi_walk_data *wdp = wsp->walk_data; 294 0 stevel MI_OP miop = &wdp->mi_wd_miodata; 295 0 stevel int status; 296 0 stevel 297 0 stevel /* Always false in the first iteration */ 298 0 stevel if ((wsp->walk_addr == (uintptr_t)NULL) || 299 0 stevel (wsp->walk_addr == wdp->mi_wd_miofirst)) { 300 0 stevel return (WALK_DONE); 301 0 stevel } 302 0 stevel 303 0 stevel if (mdb_vread(miop, sizeof (MI_O), wsp->walk_addr) == -1) { 304 0 stevel mdb_warn("failed to read MI object at %p", wsp->walk_addr); 305 0 stevel return (WALK_ERR); 306 0 stevel } 307 0 stevel 308 0 stevel /* Only true in the first iteration */ 309 3448 dh155122 if (wdp->mi_wd_miofirst == NULL) { 310 0 stevel wdp->mi_wd_miofirst = wsp->walk_addr; 311 3448 dh155122 status = WALK_NEXT; 312 3448 dh155122 } else { 313 3448 dh155122 status = wsp->walk_callback(wsp->walk_addr + sizeof (MI_O), 314 3448 dh155122 &miop[1], wsp->walk_cbdata); 315 3448 dh155122 } 316 0 stevel 317 0 stevel wsp->walk_addr = (uintptr_t)miop->mi_o_next; 318 0 stevel return (status); 319 0 stevel } 320 0 stevel 321 0 stevel void 322 0 stevel mi_walk_fini(mdb_walk_state_t *wsp) 323 0 stevel { 324 0 stevel mdb_free(wsp->walk_data, sizeof (struct mi_walk_data)); 325 0 stevel } 326 0 stevel 327 0 stevel typedef struct mi_payload_walk_arg_s { 328 3448 dh155122 const char *mi_pwa_walker; /* Underlying walker */ 329 3448 dh155122 const off_t mi_pwa_head_off; /* Offset for mi_o_head_t * in stack */ 330 0 stevel const size_t mi_pwa_size; /* size of mi payload */ 331 0 stevel const uint_t mi_pwa_flags; /* device and/or module */ 332 0 stevel } mi_payload_walk_arg_t; 333 0 stevel 334 0 stevel #define MI_PAYLOAD_DEVICE 0x1 335 0 stevel #define MI_PAYLOAD_MODULE 0x2 336 0 stevel 337 0 stevel int 338 0 stevel mi_payload_walk_init(mdb_walk_state_t *wsp) 339 0 stevel { 340 0 stevel const mi_payload_walk_arg_t *arg = wsp->walk_arg; 341 0 stevel 342 3448 dh155122 if (mdb_layered_walk(arg->mi_pwa_walker, wsp) == -1) { 343 3448 dh155122 mdb_warn("can't walk '%s'", arg->mi_pwa_walker); 344 0 stevel return (WALK_ERR); 345 0 stevel } 346 0 stevel return (WALK_NEXT); 347 0 stevel } 348 0 stevel 349 0 stevel int 350 0 stevel mi_payload_walk_step(mdb_walk_state_t *wsp) 351 0 stevel { 352 0 stevel const mi_payload_walk_arg_t *arg = wsp->walk_arg; 353 3448 dh155122 uintptr_t kaddr; 354 0 stevel 355 3448 dh155122 kaddr = wsp->walk_addr + arg->mi_pwa_head_off; 356 0 stevel 357 3448 dh155122 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 358 3448 dh155122 mdb_warn("can't read address of mi head at %p for %s", 359 3448 dh155122 kaddr, arg->mi_pwa_walker); 360 0 stevel return (WALK_ERR); 361 0 stevel } 362 0 stevel 363 3448 dh155122 if (kaddr == 0) { 364 3448 dh155122 /* Empty list */ 365 3448 dh155122 return (WALK_DONE); 366 3448 dh155122 } 367 0 stevel 368 3448 dh155122 if (mdb_pwalk("genunix`mi", wsp->walk_callback, 369 3448 dh155122 wsp->walk_cbdata, kaddr) == -1) { 370 3448 dh155122 mdb_warn("failed to walk genunix`mi"); 371 3448 dh155122 return (WALK_ERR); 372 3448 dh155122 } 373 3448 dh155122 return (WALK_NEXT); 374 0 stevel } 375 0 stevel 376 0 stevel const mi_payload_walk_arg_t mi_icmp_arg = { 377 3448 dh155122 "icmp_stacks", OFFSETOF(icmp_stack_t, is_head), sizeof (icmp_t), 378 0 stevel MI_PAYLOAD_DEVICE | MI_PAYLOAD_MODULE 379 0 stevel }; 380 0 stevel 381 0 stevel int 382 0 stevel sonode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 383 0 stevel { 384 0 stevel const char *optf = NULL; 385 0 stevel const char *optt = NULL; 386 0 stevel const char *optp = NULL; 387 0 stevel int family, type, proto; 388 0 stevel int filter = 0; 389 0 stevel struct sonode so; 390 0 stevel 391 0 stevel if (!(flags & DCMD_ADDRSPEC)) { 392 0 stevel if (mdb_walk_dcmd("genunix`sonode", "genunix`sonode", argc, 393 0 stevel argv) == -1) { 394 0 stevel mdb_warn("failed to walk sonode"); 395 0 stevel return (DCMD_ERR); 396 0 stevel } 397 0 stevel 398 0 stevel return (DCMD_OK); 399 0 stevel } 400 0 stevel 401 0 stevel if (mdb_getopts(argc, argv, 402 0 stevel 'f', MDB_OPT_STR, &optf, 403 0 stevel 't', MDB_OPT_STR, &optt, 404 0 stevel 'p', MDB_OPT_STR, &optp, 405 0 stevel NULL) != argc) 406 0 stevel return (DCMD_USAGE); 407 0 stevel 408 0 stevel if (optf != NULL) { 409 0 stevel if (strcmp("inet", optf) == 0) 410 0 stevel family = AF_INET; 411 0 stevel else if (strcmp("inet6", optf) == 0) 412 0 stevel family = AF_INET6; 413 0 stevel else if (strcmp("unix", optf) == 0) 414 0 stevel family = AF_UNIX; 415 0 stevel else 416 0 stevel family = mdb_strtoull(optf); 417 0 stevel filter = 1; 418 0 stevel } 419 0 stevel 420 0 stevel if (optt != NULL) { 421 0 stevel if (strcmp("stream", optt) == 0) 422 0 stevel type = SOCK_STREAM; 423 0 stevel else if (strcmp("dgram", optt) == 0) 424 0 stevel type = SOCK_DGRAM; 425 0 stevel else if (strcmp("raw", optt) == 0) 426 0 stevel type = SOCK_RAW; 427 0 stevel else 428 0 stevel type = mdb_strtoull(optt); 429 0 stevel filter = 1; 430 0 stevel } 431 0 stevel 432 0 stevel if (optp != NULL) { 433 0 stevel proto = mdb_strtoull(optp); 434 0 stevel filter = 1; 435 0 stevel } 436 0 stevel 437 0 stevel if (DCMD_HDRSPEC(flags) && !filter) { 438 0 stevel mdb_printf("%<u>%-?s Family Type Proto State Mode Flag " 439 0 stevel "AccessVP%</u>\n", "Sonode:"); 440 0 stevel } 441 0 stevel 442 0 stevel if (mdb_vread(&so, sizeof (so), addr) == -1) { 443 0 stevel mdb_warn("failed to read sonode at %p", addr); 444 0 stevel return (DCMD_ERR); 445 0 stevel } 446 0 stevel 447 0 stevel if ((optf != NULL) && (so.so_family != family)) 448 0 stevel return (DCMD_OK); 449 0 stevel 450 0 stevel if ((optt != NULL) && (so.so_type != type)) 451 0 stevel return (DCMD_OK); 452 0 stevel 453 0 stevel if ((optp != NULL) && (so.so_protocol != proto)) 454 0 stevel return (DCMD_OK); 455 0 stevel 456 0 stevel if (filter) { 457 0 stevel mdb_printf("%0?p\n", addr); 458 0 stevel return (DCMD_OK); 459 0 stevel } 460 0 stevel 461 0 stevel mdb_printf("%0?p ", addr); 462 0 stevel 463 0 stevel switch (so.so_family) { 464 5563 nordmark case AF_UNIX: 465 0 stevel mdb_printf("unix "); 466 0 stevel break; 467 5563 nordmark case AF_INET: 468 0 stevel mdb_printf("inet "); 469 0 stevel break; 470 5563 nordmark case AF_INET6: 471 0 stevel mdb_printf("inet6 "); 472 0 stevel break; 473 5563 nordmark default: 474 0 stevel mdb_printf("%6hi", so.so_family); 475 0 stevel } 476 0 stevel 477 0 stevel switch (so.so_type) { 478 5563 nordmark case SOCK_STREAM: 479 0 stevel mdb_printf(" strm"); 480 0 stevel break; 481 5563 nordmark case SOCK_DGRAM: 482 0 stevel mdb_printf(" dgrm"); 483 0 stevel break; 484 5563 nordmark case SOCK_RAW: 485 0 stevel mdb_printf(" raw "); 486 0 stevel break; 487 5563 nordmark default: 488 0 stevel mdb_printf(" %4hi", so.so_type); 489 0 stevel } 490 0 stevel 491 8348 Eric mdb_printf(" %5hi %05x %04x %04hx\n", 492 0 stevel so.so_protocol, so.so_state, so.so_mode, 493 8348 Eric so.so_flag); 494 0 stevel 495 0 stevel return (DCMD_OK); 496 0 stevel } 497 0 stevel 498 0 stevel #define MI_PAYLOAD 0x1 499 0 stevel #define MI_DEVICE 0x2 500 0 stevel #define MI_MODULE 0x4 501 0 stevel 502 0 stevel int 503 0 stevel mi(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 504 0 stevel { 505 0 stevel uint_t opts = 0; 506 0 stevel MI_O mio; 507 0 stevel 508 0 stevel if (!(flags & DCMD_ADDRSPEC)) 509 0 stevel return (DCMD_USAGE); 510 0 stevel 511 0 stevel if (mdb_getopts(argc, argv, 512 0 stevel 'p', MDB_OPT_SETBITS, MI_PAYLOAD, &opts, 513 0 stevel 'd', MDB_OPT_SETBITS, MI_DEVICE, &opts, 514 0 stevel 'm', MDB_OPT_SETBITS, MI_MODULE, &opts, 515 0 stevel NULL) != argc) 516 0 stevel return (DCMD_USAGE); 517 0 stevel 518 0 stevel if ((opts & (MI_DEVICE | MI_MODULE)) == (MI_DEVICE | MI_MODULE)) { 519 0 stevel mdb_warn("at most one filter, d for devices or m " 520 0 stevel "for modules, may be specified\n"); 521 0 stevel return (DCMD_USAGE); 522 0 stevel } 523 0 stevel 524 0 stevel if ((opts == 0) && (DCMD_HDRSPEC(flags))) { 525 0 stevel mdb_printf("%<u>%-?s %-?s %-?s IsDev Dev%</u>\n", 526 0 stevel "MI_O", "Next", "Prev"); 527 0 stevel } 528 0 stevel 529 0 stevel if (mdb_vread(&mio, sizeof (mio), addr) == -1) { 530 0 stevel mdb_warn("failed to read mi object MI_O at %p", addr); 531 0 stevel return (DCMD_ERR); 532 0 stevel } 533 0 stevel 534 0 stevel if (opts != 0) { 535 0 stevel if (mio.mi_o_isdev == B_FALSE) { 536 0 stevel /* mio is a module */ 537 0 stevel if (!(opts & MI_MODULE) && (opts & MI_DEVICE)) 538 0 stevel return (DCMD_OK); 539 0 stevel } else { 540 0 stevel /* mio is a device */ 541 0 stevel if (!(opts & MI_DEVICE) && (opts & MI_MODULE)) 542 0 stevel return (DCMD_OK); 543 0 stevel } 544 0 stevel 545 0 stevel if (opts & MI_PAYLOAD) 546 0 stevel mdb_printf("%p\n", addr + sizeof (MI_O)); 547 0 stevel else 548 0 stevel mdb_printf("%p\n", addr); 549 0 stevel return (DCMD_OK); 550 0 stevel } 551 0 stevel 552 0 stevel mdb_printf("%0?p %0?p %0?p ", addr, mio.mi_o_next, mio.mi_o_prev); 553 0 stevel 554 0 stevel if (mio.mi_o_isdev == B_FALSE) 555 0 stevel mdb_printf("FALSE"); 556 0 stevel else 557 0 stevel mdb_printf("TRUE "); 558 0 stevel 559 0 stevel mdb_printf(" %0?p\n", mio.mi_o_dev); 560 0 stevel 561 0 stevel return (DCMD_OK); 562 0 stevel } 563 0 stevel 564 3448 dh155122 static int 565 3448 dh155122 ns_to_stackid(uintptr_t kaddr) 566 3448 dh155122 { 567 3448 dh155122 netstack_t nss; 568 3448 dh155122 569 3448 dh155122 if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) { 570 3448 dh155122 mdb_warn("failed to read netstack_t %p", kaddr); 571 3448 dh155122 return (0); 572 3448 dh155122 } 573 3448 dh155122 return (nss.netstack_stackid); 574 3448 dh155122 } 575 3448 dh155122 576 3448 dh155122 577 3448 dh155122 578 0 stevel static void 579 0 stevel netstat_tcp_verbose_pr(const tcp_t *tcp) 580 0 stevel { 581 0 stevel mdb_printf(" %5i %08x %08x %5i %08x %08x %5li %5i\n", 582 0 stevel tcp->tcp_swnd, tcp->tcp_snxt, tcp->tcp_suna, tcp->tcp_rwnd, 583 0 stevel tcp->tcp_rack, tcp->tcp_rnxt, tcp->tcp_rto, tcp->tcp_mss); 584 0 stevel } 585 0 stevel 586 0 stevel /*ARGSUSED*/ 587 0 stevel static int 588 9089 Vasumathi netstat_tcp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 589 0 stevel { 590 9089 Vasumathi netstat_cb_data_t *ncb = cb_data; 591 9089 Vasumathi uint_t opts = ncb->opts; 592 9089 Vasumathi int af = ncb->af; 593 0 stevel uintptr_t tcp_kaddr; 594 9089 Vasumathi conn_t *connp = &ncb->conn; 595 5563 nordmark tcp_t tcps, *tcp; 596 0 stevel 597 9089 Vasumathi if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) { 598 5563 nordmark mdb_warn("failed to read conn_t at %p", kaddr); 599 5563 nordmark return (WALK_ERR); 600 5563 nordmark } 601 0 stevel 602 5563 nordmark tcp_kaddr = (uintptr_t)connp->conn_tcp; 603 5563 nordmark if (mdb_vread(&tcps, sizeof (tcp_t), tcp_kaddr) == -1) { 604 11042 Erik mdb_warn("failed to read tcp_t at %p", tcp_kaddr); 605 0 stevel return (WALK_ERR); 606 0 stevel } 607 0 stevel 608 5563 nordmark tcp = &tcps; 609 0 stevel connp->conn_tcp = tcp; 610 0 stevel tcp->tcp_connp = connp; 611 0 stevel 612 741 masputra if (!((opts & NETSTAT_ALL) || net_tcp_active(tcp)) || 613 0 stevel (af == AF_INET && !net_tcp_ipv4(tcp)) || 614 0 stevel (af == AF_INET6 && !net_tcp_ipv6(tcp))) { 615 0 stevel return (WALK_NEXT); 616 0 stevel } 617 0 stevel 618 0 stevel mdb_printf("%0?p %2i ", tcp_kaddr, tcp->tcp_state); 619 0 stevel if (af == AF_INET) { 620 11042 Erik net_ipv4addrport_pr(&connp->conn_laddr_v6, connp->conn_lport); 621 0 stevel mdb_printf(" "); 622 11042 Erik net_ipv4addrport_pr(&connp->conn_faddr_v6, connp->conn_fport); 623 0 stevel } else if (af == AF_INET6) { 624 11042 Erik net_ipv6addrport_pr(&connp->conn_laddr_v6, connp->conn_lport); 625 0 stevel mdb_printf(" "); 626 11042 Erik net_ipv6addrport_pr(&connp->conn_faddr_v6, connp->conn_fport); 627 0 stevel } 628 9089 Vasumathi mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack)); 629 0 stevel mdb_printf(" %4i\n", connp->conn_zoneid); 630 0 stevel if (opts & NETSTAT_VERBOSE) 631 0 stevel netstat_tcp_verbose_pr(tcp); 632 0 stevel 633 0 stevel return (WALK_NEXT); 634 0 stevel } 635 0 stevel 636 741 masputra /*ARGSUSED*/ 637 0 stevel static int 638 9089 Vasumathi netstat_udp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 639 0 stevel { 640 9089 Vasumathi netstat_cb_data_t *ncb = cb_data; 641 9089 Vasumathi uint_t opts = ncb->opts; 642 9089 Vasumathi int af = ncb->af; 643 741 masputra udp_t udp; 644 9089 Vasumathi conn_t *connp = &ncb->conn; 645 9089 Vasumathi char *state; 646 0 stevel 647 9089 Vasumathi if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) { 648 5563 nordmark mdb_warn("failed to read conn_t at %p", kaddr); 649 741 masputra return (WALK_ERR); 650 741 masputra } 651 741 masputra 652 5563 nordmark if (mdb_vread(&udp, sizeof (udp_t), 653 9089 Vasumathi (uintptr_t)connp->conn_udp) == -1) { 654 5563 nordmark mdb_warn("failed to read conn_udp at %p", 655 9089 Vasumathi (uintptr_t)connp->conn_udp); 656 741 masputra return (WALK_ERR); 657 741 masputra } 658 741 masputra 659 11042 Erik connp->conn_udp = &udp; 660 11042 Erik udp.udp_connp = connp; 661 11042 Erik 662 741 masputra if (!((opts & NETSTAT_ALL) || net_udp_active(&udp)) || 663 741 masputra (af == AF_INET && !net_udp_ipv4(&udp)) || 664 741 masputra (af == AF_INET6 && !net_udp_ipv6(&udp))) { 665 0 stevel return (WALK_NEXT); 666 741 masputra } 667 0 stevel 668 9089 Vasumathi if (udp.udp_state == TS_UNBND) 669 9089 Vasumathi state = "UNBOUND"; 670 9089 Vasumathi else if (udp.udp_state == TS_IDLE) 671 9089 Vasumathi state = "IDLE"; 672 9089 Vasumathi else if (udp.udp_state == TS_DATA_XFER) 673 9089 Vasumathi state = "CONNECTED"; 674 9089 Vasumathi else 675 9089 Vasumathi state = "UNKNOWN"; 676 9089 Vasumathi 677 9089 Vasumathi mdb_printf("%0?p %10s ", (uintptr_t)connp->conn_udp, state); 678 741 masputra if (af == AF_INET) { 679 11042 Erik net_ipv4addrport_pr(&connp->conn_laddr_v6, connp->conn_lport); 680 741 masputra mdb_printf(" "); 681 11042 Erik net_ipv4addrport_pr(&connp->conn_faddr_v6, connp->conn_fport); 682 741 masputra } else if (af == AF_INET6) { 683 11042 Erik net_ipv6addrport_pr(&connp->conn_laddr_v6, connp->conn_lport); 684 741 masputra mdb_printf(" "); 685 11042 Erik net_ipv6addrport_pr(&connp->conn_faddr_v6, connp->conn_fport); 686 741 masputra } 687 9089 Vasumathi mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack)); 688 9089 Vasumathi mdb_printf(" %4i\n", connp->conn_zoneid); 689 0 stevel 690 0 stevel return (WALK_NEXT); 691 0 stevel } 692 0 stevel 693 9089 Vasumathi /*ARGSUSED*/ 694 0 stevel static int 695 9089 Vasumathi netstat_icmp_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 696 741 masputra { 697 9089 Vasumathi netstat_cb_data_t *ncb = cb_data; 698 9089 Vasumathi int af = ncb->af; 699 9089 Vasumathi icmp_t icmp; 700 9089 Vasumathi conn_t *connp = &ncb->conn; 701 9089 Vasumathi char *state; 702 741 masputra 703 9089 Vasumathi if (mdb_vread(connp, sizeof (conn_t), kaddr) == -1) { 704 9089 Vasumathi mdb_warn("failed to read conn_t at %p", kaddr); 705 9089 Vasumathi return (WALK_ERR); 706 9089 Vasumathi } 707 9089 Vasumathi 708 9089 Vasumathi if (mdb_vread(&icmp, sizeof (icmp_t), 709 9089 Vasumathi (uintptr_t)connp->conn_icmp) == -1) { 710 9089 Vasumathi mdb_warn("failed to read conn_icmp at %p", 711 9089 Vasumathi (uintptr_t)connp->conn_icmp); 712 9089 Vasumathi return (WALK_ERR); 713 9089 Vasumathi } 714 9089 Vasumathi 715 11042 Erik connp->conn_icmp = &icmp; 716 11042 Erik icmp.icmp_connp = connp; 717 11042 Erik 718 11042 Erik if ((af == AF_INET && connp->conn_ipversion != IPV4_VERSION) || 719 11042 Erik (af == AF_INET6 && connp->conn_ipversion != IPV6_VERSION)) { 720 9089 Vasumathi return (WALK_NEXT); 721 9089 Vasumathi } 722 9089 Vasumathi 723 9089 Vasumathi if (icmp.icmp_state == TS_UNBND) 724 9089 Vasumathi state = "UNBOUND"; 725 9089 Vasumathi else if (icmp.icmp_state == TS_IDLE) 726 9089 Vasumathi state = "IDLE"; 727 9089 Vasumathi else if (icmp.icmp_state == TS_DATA_XFER) 728 9089 Vasumathi state = "CONNECTED"; 729 9089 Vasumathi else 730 9089 Vasumathi state = "UNKNOWN"; 731 9089 Vasumathi 732 9089 Vasumathi mdb_printf("%0?p %10s ", (uintptr_t)connp->conn_icmp, state); 733 9089 Vasumathi if (af == AF_INET) { 734 11042 Erik net_ipv4addrport_pr(&connp->conn_laddr_v6, connp->conn_lport); 735 11042 Erik mdb_printf(" "); 736 11042 Erik net_ipv4addrport_pr(&connp->conn_faddr_v6, connp->conn_fport); 737 9089 Vasumathi } else if (af == AF_INET6) { 738 11042 Erik net_ipv6addrport_pr(&connp->conn_laddr_v6, connp->conn_lport); 739 11042 Erik mdb_printf(" "); 740 11042 Erik net_ipv6addrport_pr(&connp->conn_faddr_v6, connp->conn_fport); 741 9089 Vasumathi } 742 9089 Vasumathi mdb_printf(" %5i", ns_to_stackid((uintptr_t)connp->conn_netstack)); 743 11042 Erik mdb_printf(" %4i\n", connp->conn_zoneid); 744 9089 Vasumathi 745 9089 Vasumathi return (WALK_NEXT); 746 0 stevel } 747 0 stevel 748 0 stevel /* 749 0 stevel * print the address of a unix domain socket 750 0 stevel * 751 0 stevel * so is the address of a AF_UNIX struct sonode in mdb's address space 752 0 stevel * soa is the address of the struct soaddr to print 753 0 stevel * 754 0 stevel * returns 0 on success, -1 otherwise 755 0 stevel */ 756 0 stevel static int 757 8348 Eric netstat_unix_name_pr(const struct sotpi_sonode *st, const struct soaddr *soa) 758 0 stevel { 759 8348 Eric const struct sonode *so = &st->st_sonode; 760 0 stevel const char none[] = " (none)"; 761 0 stevel 762 0 stevel if ((so->so_state & SS_ISBOUND) && (soa->soa_len != 0)) { 763 8348 Eric if (st->st_info.sti_faddr_noxlate) { 764 0 stevel mdb_printf("%-14s ", " (socketpair)"); 765 0 stevel } else { 766 0 stevel if (soa->soa_len > sizeof (sa_family_t)) { 767 0 stevel char addr[MAXPATHLEN + 1]; 768 0 stevel 769 0 stevel if (mdb_readstr(addr, sizeof (addr), 770 0 stevel (uintptr_t)&soa->soa_sa->sa_data) == -1) { 771 0 stevel mdb_warn("failed to read unix address " 772 0 stevel "at %p", &soa->soa_sa->sa_data); 773 0 stevel return (-1); 774 0 stevel } 775 0 stevel 776 0 stevel mdb_printf("%-14s ", addr); 777 0 stevel } else { 778 0 stevel mdb_printf("%-14s ", none); 779 0 stevel } 780 0 stevel } 781 0 stevel } else { 782 0 stevel mdb_printf("%-14s ", none); 783 0 stevel } 784 0 stevel 785 0 stevel return (0); 786 0 stevel } 787 0 stevel 788 0 stevel /* based on sockfs_snapshot */ 789 0 stevel /*ARGSUSED*/ 790 0 stevel static int 791 0 stevel netstat_unix_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 792 0 stevel { 793 8348 Eric const struct sotpi_sonode *st = walk_data; 794 8348 Eric const struct sonode *so = &st->st_sonode; 795 8348 Eric const struct sotpi_info *sti = &st->st_info; 796 0 stevel 797 8348 Eric if (so->so_count == 0) 798 0 stevel return (WALK_NEXT); 799 0 stevel 800 0 stevel if (so->so_family != AF_UNIX) { 801 0 stevel mdb_warn("sonode of family %hi at %p\n", so->so_family, kaddr); 802 0 stevel return (WALK_ERR); 803 0 stevel } 804 0 stevel 805 0 stevel mdb_printf("%-?p ", kaddr); 806 0 stevel 807 8348 Eric switch (sti->sti_serv_type) { 808 5563 nordmark case T_CLTS: 809 0 stevel mdb_printf("%-10s ", "dgram"); 810 0 stevel break; 811 5563 nordmark case T_COTS: 812 0 stevel mdb_printf("%-10s ", "stream"); 813 0 stevel break; 814 5563 nordmark case T_COTS_ORD: 815 0 stevel mdb_printf("%-10s ", "stream-ord"); 816 0 stevel break; 817 5563 nordmark default: 818 8348 Eric mdb_printf("%-10i ", sti->sti_serv_type); 819 0 stevel } 820 0 stevel 821 0 stevel if ((so->so_state & SS_ISBOUND) && 822 8348 Eric (sti->sti_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 823 8348 Eric mdb_printf("%0?p ", sti->sti_ux_laddr.soua_vp); 824 0 stevel } else { 825 0 stevel mdb_printf("%0?p ", NULL); 826 0 stevel } 827 0 stevel 828 0 stevel if ((so->so_state & SS_ISCONNECTED) && 829 8348 Eric (sti->sti_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT)) { 830 8348 Eric mdb_printf("%0?p ", sti->sti_ux_faddr.soua_vp); 831 0 stevel } else { 832 0 stevel mdb_printf("%0?p ", NULL); 833 0 stevel } 834 0 stevel 835 8348 Eric if (netstat_unix_name_pr(st, &sti->sti_laddr) == -1) 836 0 stevel return (WALK_ERR); 837 0 stevel 838 8348 Eric if (netstat_unix_name_pr(st, &sti->sti_faddr) == -1) 839 0 stevel return (WALK_ERR); 840 0 stevel 841 0 stevel mdb_printf("%4i\n", so->so_zoneid); 842 0 stevel 843 0 stevel return (WALK_NEXT); 844 0 stevel } 845 0 stevel 846 0 stevel static void 847 0 stevel netstat_tcp_verbose_header_pr(void) 848 0 stevel { 849 0 stevel mdb_printf(" %<u>%-5s %-8s %-8s %-5s %-8s %-8s %5s %5s%</u>\n", 850 0 stevel "Swind", "Snext", "Suna", "Rwind", "Rack", "Rnext", "Rto", "Mss"); 851 0 stevel } 852 0 stevel 853 1676 jpk static void 854 1676 jpk get_ifname(const ire_t *ire, char *intf) 855 1676 jpk { 856 1676 jpk ill_t ill; 857 1676 jpk 858 1676 jpk *intf = '\0'; 859 11042 Erik if (ire->ire_ill != NULL) { 860 11042 Erik if (mdb_vread(&ill, sizeof (ill), 861 11042 Erik (uintptr_t)ire->ire_ill) == -1) 862 1676 jpk return; 863 1676 jpk (void) mdb_readstr(intf, MIN(LIFNAMSIZ, ill.ill_name_length), 864 1676 jpk (uintptr_t)ill.ill_name); 865 1676 jpk } 866 1676 jpk } 867 1676 jpk 868 11042 Erik const in6_addr_t ipv6_all_ones = 869 11042 Erik { 0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU }; 870 11042 Erik 871 1676 jpk static void 872 11042 Erik get_ireflags(const ire_t *ire, char *flags) 873 1676 jpk { 874 1676 jpk (void) strcpy(flags, "U"); 875 11042 Erik /* RTF_INDIRECT wins over RTF_GATEWAY - don't display both */ 876 11042 Erik if (ire->ire_flags & RTF_INDIRECT) 877 11042 Erik (void) strcat(flags, "I"); 878 11042 Erik else if (ire->ire_type & IRE_OFFLINK) 879 1676 jpk (void) strcat(flags, "G"); 880 11042 Erik 881 11042 Erik /* IRE_IF_CLONE wins over RTF_HOST - don't display both */ 882 11042 Erik if (ire->ire_type & IRE_IF_CLONE) 883 11042 Erik (void) strcat(flags, "C"); 884 11042 Erik else if (ire->ire_ipversion == IPV4_VERSION) { 885 11042 Erik if (ire->ire_mask == IP_HOST_MASK) 886 11042 Erik (void) strcat(flags, "H"); 887 11042 Erik } else { 888 11042 Erik if (IN6_ARE_ADDR_EQUAL(&ire->ire_mask_v6, &ipv6_all_ones)) 889 11042 Erik (void) strcat(flags, "H"); 890 11042 Erik } 891 11042 Erik 892 11042 Erik if (ire->ire_flags & RTF_DYNAMIC) 893 1676 jpk (void) strcat(flags, "D"); 894 1676 jpk if (ire->ire_type == IRE_BROADCAST) 895 11042 Erik (void) strcat(flags, "b"); 896 11042 Erik if (ire->ire_type == IRE_MULTICAST) 897 11042 Erik (void) strcat(flags, "m"); 898 1676 jpk if (ire->ire_type == IRE_LOCAL) 899 1676 jpk (void) strcat(flags, "L"); 900 11042 Erik if (ire->ire_type == IRE_NOROUTE) 901 11042 Erik (void) strcat(flags, "N"); 902 1676 jpk if (ire->ire_flags & RTF_MULTIRT) 903 1676 jpk (void) strcat(flags, "M"); 904 1676 jpk if (ire->ire_flags & RTF_SETSRC) 905 1676 jpk (void) strcat(flags, "S"); 906 11042 Erik if (ire->ire_flags & RTF_REJECT) 907 11042 Erik (void) strcat(flags, "R"); 908 11042 Erik if (ire->ire_flags & RTF_BLACKHOLE) 909 11042 Erik (void) strcat(flags, "B"); 910 1676 jpk } 911 1676 jpk 912 1676 jpk static int 913 1676 jpk netstat_irev4_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 914 1676 jpk { 915 1676 jpk const ire_t *ire = walk_data; 916 1676 jpk uint_t *opts = cb_data; 917 1676 jpk ipaddr_t gate; 918 1676 jpk char flags[10], intf[LIFNAMSIZ + 1]; 919 1676 jpk 920 4823 seb if (ire->ire_ipversion != IPV4_VERSION) 921 1676 jpk return (WALK_NEXT); 922 1676 jpk 923 11042 Erik /* Skip certain IREs by default */ 924 11042 Erik if (!(*opts & NETSTAT_ALL) && 925 11042 Erik (ire->ire_type & 926 11042 Erik (IRE_BROADCAST|IRE_LOCAL|IRE_MULTICAST|IRE_NOROUTE|IRE_IF_CLONE))) 927 1676 jpk return (WALK_NEXT); 928 1676 jpk 929 1676 jpk if (*opts & NETSTAT_FIRST) { 930 1676 jpk *opts &= ~NETSTAT_FIRST; 931 1676 jpk mdb_printf("%<u>%s Table: IPv4%</u>\n", 932 1676 jpk (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 933 1676 jpk if (*opts & NETSTAT_VERBOSE) { 934 1676 jpk mdb_printf("%<u>%-?s %-*s %-*s %-*s Device Mxfrg Rtt " 935 1676 jpk " Ref Flg Out In/Fwd%</u>\n", 936 1676 jpk "Address", ADDR_V4_WIDTH, "Destination", 937 1676 jpk ADDR_V4_WIDTH, "Mask", ADDR_V4_WIDTH, "Gateway"); 938 1676 jpk } else { 939 1676 jpk mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use " 940 1676 jpk "Interface%</u>\n", 941 1676 jpk "Address", ADDR_V4_WIDTH, "Destination", 942 1676 jpk ADDR_V4_WIDTH, "Gateway"); 943 1676 jpk } 944 1676 jpk } 945 1676 jpk 946 11042 Erik gate = ire->ire_gateway_addr; 947 1676 jpk 948 11042 Erik get_ireflags(ire, flags); 949 1676 jpk 950 1676 jpk get_ifname(ire, intf); 951 1676 jpk 952 1676 jpk if (*opts & NETSTAT_VERBOSE) { 953 1676 jpk mdb_printf("%?p %-*I %-*I %-*I %-6s %5u%c %4u %3u %-3s %5u " 954 1676 jpk "%u\n", kaddr, ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, 955 1676 jpk ire->ire_mask, ADDR_V4_WIDTH, gate, intf, 956 11042 Erik 0, ' ', 957 11042 Erik ire->ire_metrics.iulp_rtt, ire->ire_refcnt, flags, 958 1676 jpk ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 959 1676 jpk } else { 960 1676 jpk mdb_printf("%?p %-*I %-*I %-5s %4u %5u %s\n", kaddr, 961 1676 jpk ADDR_V4_WIDTH, ire->ire_addr, ADDR_V4_WIDTH, gate, flags, 962 1676 jpk ire->ire_refcnt, 963 1676 jpk ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 964 1676 jpk } 965 1676 jpk 966 1676 jpk return (WALK_NEXT); 967 1676 jpk } 968 1676 jpk 969 1676 jpk int 970 1676 jpk ip_mask_to_plen_v6(const in6_addr_t *v6mask) 971 1676 jpk { 972 1676 jpk int plen; 973 1676 jpk int i; 974 1676 jpk uint32_t val; 975 1676 jpk 976 1676 jpk for (i = 3; i >= 0; i--) 977 1676 jpk if (v6mask->s6_addr32[i] != 0) 978 1676 jpk break; 979 1676 jpk if (i < 0) 980 1676 jpk return (0); 981 1676 jpk plen = 32 + 32 * i; 982 1676 jpk val = v6mask->s6_addr32[i]; 983 1676 jpk while (!(val & 1)) { 984 1676 jpk val >>= 1; 985 1676 jpk plen--; 986 1676 jpk } 987 1676 jpk 988 1676 jpk return (plen); 989 1676 jpk } 990 1676 jpk 991 1676 jpk static int 992 1676 jpk netstat_irev6_cb(uintptr_t kaddr, const void *walk_data, void *cb_data) 993 1676 jpk { 994 1676 jpk const ire_t *ire = walk_data; 995 1676 jpk uint_t *opts = cb_data; 996 1676 jpk const in6_addr_t *gatep; 997 1676 jpk char deststr[ADDR_V6_WIDTH + 5]; 998 1676 jpk char flags[10], intf[LIFNAMSIZ + 1]; 999 1676 jpk int masklen; 1000 1676 jpk 1001 1676 jpk if (ire->ire_ipversion != IPV6_VERSION) 1002 1676 jpk return (WALK_NEXT); 1003 1676 jpk 1004 11042 Erik /* Skip certain IREs by default */ 1005 11042 Erik if (!(*opts & NETSTAT_ALL) && 1006 11042 Erik (ire->ire_type & 1007 11042 Erik (IRE_BROADCAST|IRE_LOCAL|IRE_MULTICAST|IRE_NOROUTE|IRE_IF_CLONE))) 1008 1676 jpk return (WALK_NEXT); 1009 1676 jpk 1010 1676 jpk if (*opts & NETSTAT_FIRST) { 1011 1676 jpk *opts &= ~NETSTAT_FIRST; 1012 1676 jpk mdb_printf("\n%<u>%s Table: IPv6%</u>\n", 1013 1676 jpk (*opts & NETSTAT_VERBOSE) ? "IRE" : "Routing"); 1014 1676 jpk if (*opts & NETSTAT_VERBOSE) { 1015 1676 jpk mdb_printf("%<u>%-?s %-*s %-*s If PMTU Rtt Ref " 1016 1676 jpk "Flags Out In/Fwd%</u>\n", 1017 1676 jpk "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 1018 1676 jpk ADDR_V6_WIDTH, "Gateway"); 1019 1676 jpk } else { 1020 1676 jpk mdb_printf("%<u>%-?s %-*s %-*s Flags Ref Use If" 1021 1676 jpk "%</u>\n", 1022 1676 jpk "Address", ADDR_V6_WIDTH+4, "Destination/Mask", 1023 1676 jpk ADDR_V6_WIDTH, "Gateway"); 1024 1676 jpk } 1025 1676 jpk } 1026 1676 jpk 1027 11042 Erik gatep = &ire->ire_gateway_addr_v6; 1028 1676 jpk 1029 1676 jpk masklen = ip_mask_to_plen_v6(&ire->ire_mask_v6); 1030 1676 jpk (void) mdb_snprintf(deststr, sizeof (deststr), "%N/%d", 1031 1676 jpk &ire->ire_addr_v6, masklen); 1032 1676 jpk 1033 11042 Erik get_ireflags(ire, flags); 1034 1676 jpk 1035 1676 jpk get_ifname(ire, intf); 1036 1676 jpk 1037 1676 jpk if (*opts & NETSTAT_VERBOSE) { 1038 1676 jpk mdb_printf("%?p %-*s %-*N %-5s %5u%c %5u %3u %-5s %6u %u\n", 1039 1676 jpk kaddr, ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, 1040 11042 Erik intf, 0, ' ', 1041 11042 Erik ire->ire_metrics.iulp_rtt, ire->ire_refcnt, 1042 1676 jpk flags, ire->ire_ob_pkt_count, ire->ire_ib_pkt_count); 1043 1676 jpk } else { 1044 1676 jpk mdb_printf("%?p %-*s %-*N %-5s %3u %6u %s\n", kaddr, 1045 1676 jpk ADDR_V6_WIDTH+4, deststr, ADDR_V6_WIDTH, gatep, flags, 1046 1676 jpk ire->ire_refcnt, 1047 1676 jpk ire->ire_ob_pkt_count + ire->ire_ib_pkt_count, intf); 1048 1676 jpk } 1049 1676 jpk 1050 1676 jpk return (WALK_NEXT); 1051 1676 jpk } 1052 1676 jpk 1053 9089 Vasumathi static void 1054 9089 Vasumathi netstat_header_v4(int proto) 1055 9089 Vasumathi { 1056 9089 Vasumathi if (proto == IPPROTO_TCP) 1057 9089 Vasumathi mdb_printf("%<u>%-?s ", "TCPv4"); 1058 9089 Vasumathi else if (proto == IPPROTO_UDP) 1059 9089 Vasumathi mdb_printf("%<u>%-?s ", "UDPv4"); 1060 9089 Vasumathi else if (proto == IPPROTO_ICMP) 1061 9089 Vasumathi mdb_printf("%<u>%-?s ", "ICMPv4"); 1062 9089 Vasumathi mdb_printf("State %6s%*s %6s%*s %-5s %-4s%</u>\n", 1063 9089 Vasumathi "", ADDR_V4_WIDTH, "Local Address", 1064 9089 Vasumathi "", ADDR_V4_WIDTH, "Remote Address", "Stack", "Zone"); 1065 9089 Vasumathi } 1066 9089 Vasumathi 1067 9089 Vasumathi static void 1068 9089 Vasumathi netstat_header_v6(int proto) 1069 9089 Vasumathi { 1070 9089 Vasumathi if (proto == IPPROTO_TCP) 1071 9089 Vasumathi mdb_printf("%<u>%-?s ", "TCPv6"); 1072 9089 Vasumathi else if (proto == IPPROTO_UDP) 1073 9089 Vasumathi mdb_printf("%<u>%-?s ", "UDPv6"); 1074 9089 Vasumathi else if (proto == IPPROTO_ICMP) 1075 9089 Vasumathi mdb_printf("%<u>%-?s ", "ICMPv6"); 1076 9089 Vasumathi mdb_printf("State %6s%*s %6s%*s %-5s %-4s%</u>\n", 1077 9089 Vasumathi "", ADDR_V6_WIDTH, "Local Address", 1078 9089 Vasumathi "", ADDR_V6_WIDTH, "Remote Address", "Stack", "Zone"); 1079 9089 Vasumathi } 1080 9089 Vasumathi 1081 9089 Vasumathi static int 1082 9089 Vasumathi netstat_print_conn(const char *cache, int proto, mdb_walk_cb_t cbfunc, 1083 9089 Vasumathi void *cbdata) 1084 9089 Vasumathi { 1085 9089 Vasumathi netstat_cb_data_t *ncb = cbdata; 1086 9089 Vasumathi 1087 9089 Vasumathi if ((ncb->opts & NETSTAT_VERBOSE) && proto == IPPROTO_TCP) 1088 9089 Vasumathi netstat_tcp_verbose_header_pr(); 1089 9089 Vasumathi if (mdb_walk(cache, cbfunc, cbdata) == -1) { 1090 9089 Vasumathi mdb_warn("failed to walk %s", cache); 1091 9089 Vasumathi return (DCMD_ERR); 1092 9089 Vasumathi } 1093 9089 Vasumathi return (DCMD_OK); 1094 9089 Vasumathi } 1095 9089 Vasumathi 1096 9089 Vasumathi static int 1097 9089 Vasumathi netstat_print_common(const char *cache, int proto, mdb_walk_cb_t cbfunc, 1098 9089 Vasumathi void *cbdata) 1099 9089 Vasumathi { 1100 9089 Vasumathi netstat_cb_data_t *ncb = cbdata; 1101 9089 Vasumathi int af = ncb->af; 1102 9089 Vasumathi int status = DCMD_OK; 1103 9089 Vasumathi 1104 9089 Vasumathi if (af != AF_INET6) { 1105 9089 Vasumathi ncb->af = AF_INET; 1106 9089 Vasumathi netstat_header_v4(proto); 1107 9089 Vasumathi status = netstat_print_conn(cache, proto, cbfunc, cbdata); 1108 9089 Vasumathi } 1109 9089 Vasumathi if (status == DCMD_OK && af != AF_INET) { 1110 9089 Vasumathi ncb->af = AF_INET6; 1111 9089 Vasumathi netstat_header_v6(proto); 1112 9089 Vasumathi status = netstat_print_conn(cache, proto, cbfunc, cbdata); 1113 9089 Vasumathi } 1114 9089 Vasumathi ncb->af = af; 1115 9089 Vasumathi return (status); 1116 9089 Vasumathi } 1117 9089 Vasumathi 1118 0 stevel /*ARGSUSED*/ 1119 0 stevel int 1120 0 stevel netstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1121 0 stevel { 1122 0 stevel uint_t opts = 0; 1123 0 stevel const char *optf = NULL; 1124 0 stevel const char *optP = NULL; 1125 9089 Vasumathi netstat_cb_data_t *cbdata; 1126 9089 Vasumathi int status; 1127 9089 Vasumathi int af = 0; 1128 0 stevel 1129 0 stevel if (mdb_getopts(argc, argv, 1130 0 stevel 'a', MDB_OPT_SETBITS, NETSTAT_ALL, &opts, 1131 0 stevel 'f', MDB_OPT_STR, &optf, 1132 0 stevel 'P', MDB_OPT_STR, &optP, 1133 1676 jpk 'r', MDB_OPT_SETBITS, NETSTAT_ROUTE, &opts, 1134 1676 jpk 'v', MDB_OPT_SETBITS, NETSTAT_VERBOSE, &opts, 1135 0 stevel NULL) != argc) 1136 0 stevel return (DCMD_USAGE); 1137 0 stevel 1138 0 stevel if (optP != NULL) { 1139 9089 Vasumathi if ((strcmp("tcp", optP) != 0) && (strcmp("udp", optP) != 0) && 1140 9089 Vasumathi (strcmp("icmp", optP) != 0)) 1141 0 stevel return (DCMD_USAGE); 1142 1676 jpk if (opts & NETSTAT_ROUTE) 1143 1676 jpk return (DCMD_USAGE); 1144 0 stevel } 1145 0 stevel 1146 1676 jpk if (optf == NULL) 1147 1676 jpk opts |= NETSTAT_V4 | NETSTAT_V6 | NETSTAT_UNIX; 1148 1676 jpk else if (strcmp("inet", optf) == 0) 1149 1676 jpk opts |= NETSTAT_V4; 1150 1676 jpk else if (strcmp("inet6", optf) == 0) 1151 1676 jpk opts |= NETSTAT_V6; 1152 1676 jpk else if (strcmp("unix", optf) == 0) 1153 1676 jpk opts |= NETSTAT_UNIX; 1154 1676 jpk else 1155 1676 jpk return (DCMD_USAGE); 1156 1676 jpk 1157 1676 jpk if (opts & NETSTAT_ROUTE) { 1158 1676 jpk if (!(opts & (NETSTAT_V4|NETSTAT_V6))) 1159 0 stevel return (DCMD_USAGE); 1160 1676 jpk if (opts & NETSTAT_V4) { 1161 1676 jpk opts |= NETSTAT_FIRST; 1162 1676 jpk if (mdb_walk("ip`ire", netstat_irev4_cb, &opts) == -1) { 1163 1676 jpk mdb_warn("failed to walk ip`ire"); 1164 1676 jpk return (DCMD_ERR); 1165 1676 jpk } 1166 1676 jpk } 1167 1676 jpk if (opts & NETSTAT_V6) { 1168 1676 jpk opts |= NETSTAT_FIRST; 1169 1676 jpk if (mdb_walk("ip`ire", netstat_irev6_cb, &opts) == -1) { 1170 1676 jpk mdb_warn("failed to walk ip`ire"); 1171 1676 jpk return (DCMD_ERR); 1172 1676 jpk } 1173 1676 jpk } 1174 1676 jpk return (DCMD_OK); 1175 0 stevel } 1176 0 stevel 1177 9089 Vasumathi if ((opts & NETSTAT_UNIX) && (optP == NULL)) { 1178 0 stevel /* Print Unix Domain Sockets */ 1179 0 stevel mdb_printf("%<u>%-?s %-10s %-?s %-?s %-14s %-14s %s%</u>\n", 1180 0 stevel "AF_UNIX", "Type", "Vnode", "Conn", "Local Addr", 1181 0 stevel "Remote Addr", "Zone"); 1182 0 stevel 1183 0 stevel if (mdb_walk("genunix`sonode", netstat_unix_cb, NULL) == -1) { 1184 0 stevel mdb_warn("failed to walk genunix`sonode"); 1185 0 stevel return (DCMD_ERR); 1186 0 stevel } 1187 9089 Vasumathi if (!(opts & (NETSTAT_V4 | NETSTAT_V6))) 1188 9089 Vasumathi return (DCMD_OK); 1189 0 stevel } 1190 0 stevel 1191 9089 Vasumathi cbdata = mdb_alloc(sizeof (netstat_cb_data_t), UM_SLEEP); 1192 9089 Vasumathi cbdata->opts = opts; 1193 9089 Vasumathi if ((optf != NULL) && (opts & NETSTAT_V4)) 1194 9089 Vasumathi af = AF_INET; 1195 9089 Vasumathi else if ((optf != NULL) && (opts & NETSTAT_V6)) 1196 9089 Vasumathi af = AF_INET6; 1197 9089 Vasumathi 1198 9089 Vasumathi cbdata->af = af; 1199 9089 Vasumathi if ((optP == NULL) || (strcmp("tcp", optP) == 0)) { 1200 9089 Vasumathi status = netstat_print_common("tcp_conn_cache", IPPROTO_TCP, 1201 9089 Vasumathi netstat_tcp_cb, cbdata); 1202 9089 Vasumathi if (status != DCMD_OK) 1203 9089 Vasumathi goto out; 1204 9089 Vasumathi } 1205 9089 Vasumathi 1206 9089 Vasumathi if ((optP == NULL) || (strcmp("udp", optP) == 0)) { 1207 9089 Vasumathi status = netstat_print_common("udp_conn_cache", IPPROTO_UDP, 1208 9089 Vasumathi netstat_udp_cb, cbdata); 1209 9089 Vasumathi if (status != DCMD_OK) 1210 9089 Vasumathi goto out; 1211 9089 Vasumathi } 1212 9089 Vasumathi 1213 9089 Vasumathi if ((optP == NULL) || (strcmp("icmp", optP) == 0)) { 1214 9089 Vasumathi status = netstat_print_common("rawip_conn_cache", IPPROTO_ICMP, 1215 9089 Vasumathi netstat_icmp_cb, cbdata); 1216 9089 Vasumathi if (status != DCMD_OK) 1217 9089 Vasumathi goto out; 1218 9089 Vasumathi } 1219 9089 Vasumathi out: 1220 9089 Vasumathi mdb_free(cbdata, sizeof (netstat_cb_data_t)); 1221 9089 Vasumathi return (status); 1222 0 stevel } 1223 10491 Rishi 1224 10491 Rishi /* 1225 10491 Rishi * "::dladm show-bridge" support 1226 10491 Rishi */ 1227 10491 Rishi typedef struct { 1228 10491 Rishi uint_t opt_l; 1229 10491 Rishi uint_t opt_f; 1230 10491 Rishi uint_t opt_t; 1231 10491 Rishi const char *name; 1232 10491 Rishi clock_t lbolt; 1233 10491 Rishi boolean_t found; 1234 10491 Rishi uint_t nlinks; 1235 10491 Rishi uint_t nfwd; 1236 10491 Rishi 1237 10491 Rishi /* 1238 10491 Rishi * These structures are kept inside the 'args' for allocation reasons. 1239 10491 Rishi * They're all large data structures (over 1K), and may cause the stack 1240 10491 Rishi * to explode. mdb and kmdb will fail in these cases, and thus we 1241 10491 Rishi * allocate them from the heap. 1242 10491 Rishi */ 1243 10491 Rishi trill_inst_t ti; 1244 10491 Rishi bridge_link_t bl; 1245 10491 Rishi mac_impl_t mi; 1246 10491 Rishi } show_bridge_args_t; 1247 10491 Rishi 1248 10491 Rishi static void 1249 10491 Rishi show_vlans(const uint8_t *vlans) 1250 10491 Rishi { 1251 10491 Rishi int i, bit; 1252 10491 Rishi uint8_t val; 1253 10491 Rishi int rstart = -1, rnext = -1; 1254 10491 Rishi 1255 10491 Rishi for (i = 0; i < BRIDGE_VLAN_ARR_SIZE; i++) { 1256 10491 Rishi val = vlans[i]; 1257 10491 Rishi if (i == 0) 1258 10491 Rishi val &= ~1; 1259 10491 Rishi while ((bit = mdb_ffs(val)) != 0) { 1260 10491 Rishi bit--; 1261 10491 Rishi val &= ~(1 << bit); 1262 10491 Rishi bit += i * sizeof (*vlans) * NBBY; 1263 10491 Rishi if (bit != rnext) { 1264 10491 Rishi if (rnext != -1 && rstart + 1 != rnext) 1265 10491 Rishi mdb_printf("-%d", rnext - 1); 1266 10491 Rishi if (rstart != -1) 1267 10491 Rishi mdb_printf(","); 1268 10491 Rishi mdb_printf("%d", bit); 1269 10491 Rishi rstart = bit; 1270 10491 Rishi } 1271 10491 Rishi rnext = bit + 1; 1272 10491 Rishi } 1273 10491 Rishi } 1274 10491 Rishi if (rnext != -1 && rstart + 1 != rnext) 1275 10491 Rishi mdb_printf("-%d", rnext - 1); 1276 10491 Rishi mdb_printf("\n"); 1277 10491 Rishi } 1278 10491 Rishi 1279 10491 Rishi /* 1280 10491 Rishi * This callback is invoked by a walk of the links attached to a bridge. If 1281 10491 Rishi * we're showing link details, then they're printed here. If not, then we just 1282 10491 Rishi * count up the links for the bridge summary. 1283 10491 Rishi */ 1284 10491 Rishi static int 1285 10491 Rishi do_bridge_links(uintptr_t addr, const void *data, void *ptr) 1286 10491 Rishi { 1287 10491 Rishi show_bridge_args_t *args = ptr; 1288 10491 Rishi const bridge_link_t *blp = data; 1289 10491 Rishi char macaddr[ETHERADDRL * 3]; 1290 10491 Rishi const char *name; 1291 10491 Rishi 1292 10491 Rishi args->nlinks++; 1293 10491 Rishi 1294 10491 Rishi if (!args->opt_l) 1295 10491 Rishi return (WALK_NEXT); 1296 10491 Rishi 1297 10491 Rishi if (mdb_vread(&args->mi, sizeof (args->mi), 1298 10491 Rishi (uintptr_t)blp->bl_mh) == -1) { 1299 10491 Rishi mdb_warn("cannot read mac data at %p", blp->bl_mh); 1300 10491 Rishi name = "?"; 1301 10491 Rishi } else { 1302 10491 Rishi name = args->mi.mi_name; 1303 10491 Rishi } 1304 10491 Rishi 1305 10491 Rishi mdb_mac_addr(blp->bl_local_mac, ETHERADDRL, macaddr, 1306 10491 Rishi sizeof (macaddr)); 1307 10491 Rishi 1308 10491 Rishi mdb_printf("%-?p %-16s %-17s %03X %-4d ", addr, name, macaddr, 1309 10491 Rishi blp->bl_flags, blp->bl_pvid); 1310 10491 Rishi 1311 10491 Rishi if (blp->bl_trilldata == NULL) { 1312 10491 Rishi switch (blp->bl_state) { 1313 10491 Rishi case BLS_BLOCKLISTEN: 1314 10491 Rishi name = "BLOCK"; 1315 10491 Rishi break; 1316 10491 Rishi case BLS_LEARNING: 1317 10491 Rishi name = "LEARN"; 1318 10491 Rishi break; 1319 10491 Rishi case BLS_FORWARDING: 1320 10491 Rishi name = "FWD"; 1321 10491 Rishi break; 1322 10491 Rishi default: 1323 10491 Rishi name = "?"; 1324 10491 Rishi } 1325 10491 Rishi mdb_printf("%-5s ", name); 1326 10491 Rishi show_vlans(blp->bl_vlans); 1327 10491 Rishi } else { 1328 10491 Rishi show_vlans(blp->bl_afs); 1329 10491 Rishi } 1330 10491 Rishi 1331 10491 Rishi return (WALK_NEXT); 1332 10491 Rishi } 1333 10491 Rishi 1334 10491 Rishi /* 1335 10491 Rishi * It seems a shame to duplicate this code, but merging it with the link 1336 10491 Rishi * printing code above is more trouble than it would be worth. 1337 10491 Rishi */ 1338 10491 Rishi static void 1339 10491 Rishi print_link_name(show_bridge_args_t *args, uintptr_t addr, char sep) 1340 10491 Rishi { 1341 10491 Rishi const char *name; 1342 10491 Rishi 1343 10491 Rishi if (mdb_vread(&args->bl, sizeof (args->bl), addr) == -1) { 1344 10491 Rishi mdb_warn("cannot read bridge link at %p", addr); 1345 10491 Rishi return; 1346 10491 Rishi } 1347 10491 Rishi 1348 10491 Rishi if (mdb_vread(&args->mi, sizeof (args->mi), 1349 10491 Rishi (uintptr_t)args->bl.bl_mh) == -1) { 1350 10491 Rishi name = "?"; 1351 10491 Rishi } else { 1352 10491 Rishi name = args->mi.mi_name; 1353 10491 Rishi } 1354 10491 Rishi 1355 10491 Rishi mdb_printf("%s%c", name, sep); 1356 10491 Rishi } 1357 10491 Rishi 1358 10491 Rishi static int 1359 10491 Rishi do_bridge_fwd(uintptr_t addr, const void *data, void *ptr) 1360 10491 Rishi { 1361 10491 Rishi show_bridge_args_t *args = ptr; 1362 10491 Rishi const bridge_fwd_t *bfp = data; 1363 10491 Rishi char macaddr[ETHERADDRL * 3]; 1364 10491 Rishi int i; 1365 10491 Rishi #define MAX_FWD_LINKS 16 1366 10491 Rishi bridge_link_t *links[MAX_FWD_LINKS]; 1367 10491 Rishi uint_t nlinks; 1368 10491 Rishi 1369 10491 Rishi args->nfwd++; 1370 10491 Rishi 1371 10491 Rishi if (!args->opt_f) 1372 10491 Rishi return (WALK_NEXT); 1373 10491 Rishi 1374 10491 Rishi if ((nlinks = bfp->bf_nlinks) > MAX_FWD_LINKS) 1375 10491 Rishi nlinks = MAX_FWD_LINKS; 1376 10491 Rishi 1377 10491 Rishi if (mdb_vread(links, sizeof (links[0]) * nlinks, 1378 10491 Rishi (uintptr_t)bfp->bf_links) == -1) { 1379 10491 Rishi mdb_warn("cannot read bridge forwarding links at %p", 1380 10491 Rishi bfp->bf_links); 1381 10491 Rishi return (WALK_ERR); 1382 10491 Rishi } 1383 10491 Rishi 1384 10491 Rishi mdb_mac_addr(bfp->bf_dest, ETHERADDRL, macaddr, sizeof (macaddr)); 1385 10491 Rishi 1386 10491 Rishi mdb_printf("%-?p %-17s ", addr, macaddr); 1387 10491 Rishi if (bfp->bf_flags & BFF_LOCALADDR) 1388 10491 Rishi mdb_printf("%-7s", "[self]"); 1389 10491 Rishi else 1390 10491 Rishi mdb_printf("t-%-5d", args->lbolt - bfp->bf_lastheard); 1391 10491 Rishi mdb_printf(" %-7u ", bfp->bf_refs); 1392 10491 Rishi 1393 10491 Rishi if (bfp->bf_trill_nick != 0) { 1394 10491 Rishi mdb_printf("%d\n", bfp->bf_trill_nick); 1395 10491 Rishi } else { 1396 10491 Rishi for (i = 0; i < bfp->bf_nlinks; i++) { 1397 10491 Rishi print_link_name(args, (uintptr_t)links[i], 1398 10491 Rishi i == bfp->bf_nlinks - 1 ? '\n' : ' '); 1399 10491 Rishi } 1400 10491 Rishi } 1401 10491 Rishi 1402 10491 Rishi return (WALK_NEXT); 1403 10491 Rishi } 1404 10491 Rishi 1405 10491 Rishi static int 1406 10491 Rishi do_show_bridge(uintptr_t addr, const void *data, void *ptr) 1407 10491 Rishi { 1408 10491 Rishi show_bridge_args_t *args = ptr; 1409 10491 Rishi bridge_inst_t bi; 1410 10491 Rishi const bridge_inst_t *bip; 1411 10491 Rishi trill_node_t tn; 1412 10491 Rishi trill_sock_t tsp; 1413 10491 Rishi trill_nickinfo_t tni; 1414 10491 Rishi char bname[MAXLINKNAMELEN]; 1415 10491 Rishi char macaddr[ETHERADDRL * 3]; 1416 10491 Rishi char *cp; 1417 10491 Rishi uint_t nnicks; 1418 10491 Rishi int i; 1419 10491 Rishi 1420 10491 Rishi if (data != NULL) { 1421 10491 Rishi bip = data; 1422 10491 Rishi } else { 1423 10491 Rishi if (mdb_vread(&bi, sizeof (bi), addr) == -1) { 1424 10491 Rishi mdb_warn("cannot read bridge instance at %p", addr); 1425 10491 Rishi return (WALK_ERR); 1426 10491 Rishi } 1427 10491 Rishi bip = &bi; 1428 10491 Rishi } 1429 10491 Rishi 1430 10491 Rishi (void) strncpy(bname, bip->bi_name, sizeof (bname) - 1); 1431 10491 Rishi bname[MAXLINKNAMELEN - 1] = '\0'; 1432 10491 Rishi cp = bname + strlen(bname); 1433 10491 Rishi if (cp > bname && cp[-1] == '0') 1434 10491 Rishi cp[-1] = '\0'; 1435 10491 Rishi 1436 10491 Rishi if (args->name != NULL && strcmp(args->name, bname) != 0) 1437 10491 Rishi return (WALK_NEXT); 1438 10491 Rishi 1439 10491 Rishi args->found = B_TRUE; 1440 10491 Rishi args->nlinks = args->nfwd = 0; 1441 10491 Rishi 1442 10491 Rishi if (args->opt_l) { 1443 10491 Rishi mdb_printf("%-?s %-16s %-17s %3s %-4s ", "ADDR", "LINK", 1444 10491 Rishi "MAC-ADDR", "FLG", "PVID"); 1445 10491 Rishi if (bip->bi_trilldata == NULL) 1446 10491 Rishi mdb_printf("%-5s %s\n", "STATE", "VLANS"); 1447 10491 Rishi else 1448 10491 Rishi mdb_printf("%s\n", "FWD-VLANS"); 1449 10491 Rishi } 1450 10491 Rishi 1451 10491 Rishi if (!args->opt_f && !args->opt_t && 1452 10491 Rishi mdb_pwalk("list", do_bridge_links, args, 1453 10491 Rishi addr + offsetof(bridge_inst_t, bi_links)) != DCMD_OK) 1454 10491 Rishi return (WALK_ERR); 1455 10491 Rishi 1456 10491 Rishi if (args->opt_f) 1457 10491 Rishi mdb_printf("%-?s %-17s %-7s %-7s %s\n", "ADDR", "DEST", "TIME", 1458 10491 Rishi "REFS", "OUTPUT"); 1459 10491 Rishi 1460 10491 Rishi if (!args->opt_l && !args->opt_t && 1461 10491 Rishi mdb_pwalk("avl", do_bridge_fwd, args, 1462 10491 Rishi addr + offsetof(bridge_inst_t, bi_fwd)) != DCMD_OK) 1463 10491 Rishi return (WALK_ERR); 1464 10491 Rishi 1465 10491 Rishi nnicks = 0; 1466 10491 Rishi if (bip->bi_trilldata != NULL && !args->opt_l && !args->opt_f) { 1467 10491 Rishi if (mdb_vread(&args->ti, sizeof (args->ti), 1468 10491 Rishi (uintptr_t)bip->bi_trilldata) == -1) { 1469 10491 Rishi mdb_warn("cannot read trill instance at %p", 1470 10491 Rishi bip->bi_trilldata); 1471 10491 Rishi return (WALK_ERR); 1472 10491 Rishi } 1473 10491 Rishi if (args->opt_t) 1474 10491 Rishi mdb_printf("%-?s %-5s %-17s %s\n", "ADDR", 1475 10491 Rishi "NICK", "NEXT-HOP", "LINK"); 1476 10491 Rishi for (i = 0; i < RBRIDGE_NICKNAME_MAX; i++) { 1477 10491 Rishi if (args->ti.ti_nodes[i] == NULL) 1478 10491 Rishi continue; 1479 10491 Rishi if (args->opt_t) { 1480 10491 Rishi if (mdb_vread(&tn, sizeof (tn), 1481 10491 Rishi (uintptr_t)args->ti.ti_nodes[i]) == -1) { 1482 10491 Rishi mdb_warn("cannot read trill node %d at " 1483 10491 Rishi "%p", i, args->ti.ti_nodes[i]); 1484 10491 Rishi return (WALK_ERR); 1485 10491 Rishi } 1486 10491 Rishi if (mdb_vread(&tni, sizeof (tni), 1487 10491 Rishi (uintptr_t)tn.tn_ni) == -1) { 1488 10491 Rishi mdb_warn("cannot read trill node info " 1489 10491 Rishi "%d at %p", i, tn.tn_ni); 1490 10491 Rishi return (WALK_ERR); 1491 10491 Rishi } 1492 10491 Rishi mdb_mac_addr(tni.tni_adjsnpa, ETHERADDRL, 1493 10491 Rishi macaddr, sizeof (macaddr)); 1494 10491 Rishi if (tni.tni_nick == args->ti.ti_nick) { 1495 10491 Rishi (void) strcpy(macaddr, "[self]"); 1496 10491 Rishi } 1497 10491 Rishi mdb_printf("%-?p %-5u %-17s ", 1498 10491 Rishi args->ti.ti_nodes[i], tni.tni_nick, 1499 10491 Rishi macaddr); 1500 10491 Rishi if (tn.tn_tsp != NULL) { 1501 10491 Rishi if (mdb_vread(&tsp, sizeof (tsp), 1502 10491 Rishi (uintptr_t)tn.tn_tsp) == -1) { 1503 10491 Rishi mdb_warn("cannot read trill " 1504 10491 Rishi "socket info at %p", 1505 10491 Rishi tn.tn_tsp); 1506 10491 Rishi return (WALK_ERR); 1507 10491 Rishi } 1508 10491 Rishi if (tsp.ts_link != NULL) { 1509 10491 Rishi print_link_name(args, 1510 10491 Rishi (uintptr_t)tsp.ts_link, 1511 10491 Rishi '\n'); 1512 10491 Rishi continue; 1513 10491 Rishi } 1514 10491 Rishi } 1515 10491 Rishi mdb_printf("--\n"); 1516 10491 Rishi } else { 1517 10491 Rishi nnicks++; 1518 10491 Rishi } 1519 10491 Rishi } 1520 10491 Rishi } else { 1521 10491 Rishi if (args->opt_t) 1522 10491 Rishi mdb_printf("bridge is not running TRILL\n"); 1523 10491 Rishi } 1524 10491 Rishi 1525 10491 Rishi if (!args->opt_l && !args->opt_f && !args->opt_t) { 1526 10491 Rishi mdb_printf("%-?p %-7s %-16s %-7u %-7u", addr, 1527 10491 Rishi bip->bi_trilldata == NULL ? "stp" : "trill", bname, 1528 10491 Rishi args->nlinks, args->nfwd); 1529 10491 Rishi if (bip->bi_trilldata != NULL) 1530 10491 Rishi mdb_printf(" %-7u %u\n", nnicks, args->ti.ti_nick); 1531 10491 Rishi else 1532 10491 Rishi mdb_printf(" %-7s %s\n", "--", "--"); 1533 10491 Rishi } 1534 10491 Rishi return (WALK_NEXT); 1535 10491 Rishi } 1536 10491 Rishi 1537 10491 Rishi static int 1538 10491 Rishi dladm_show_bridge(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1539 10491 Rishi { 1540 10491 Rishi show_bridge_args_t *args; 1541 10491 Rishi GElf_Sym sym; 1542 10491 Rishi int i; 1543 10491 Rishi 1544 10491 Rishi args = mdb_zalloc(sizeof (*args), UM_SLEEP); 1545 10491 Rishi 1546 10491 Rishi i = mdb_getopts(argc, argv, 1547 10491 Rishi 'l', MDB_OPT_SETBITS, 1, &args->opt_l, 1548 10491 Rishi 'f', MDB_OPT_SETBITS, 1, &args->opt_f, 1549 10491 Rishi 't', MDB_OPT_SETBITS, 1, &args->opt_t, 1550 10491 Rishi NULL); 1551 10491 Rishi 1552 10491 Rishi argc -= i; 1553 10491 Rishi argv += i; 1554 10491 Rishi 1555 10491 Rishi if (argc > 1 || (argc == 1 && argv[0].a_type != MDB_TYPE_STRING)) { 1556 10491 Rishi mdb_free(args, sizeof (*args)); 1557 10491 Rishi return (DCMD_USAGE); 1558 10491 Rishi } 1559 10491 Rishi if (argc == 1) 1560 10491 Rishi args->name = argv[0].a_un.a_str; 1561 10491 Rishi 1562 11066 rafael if ((args->lbolt = mdb_get_lbolt()) == -1) { 1563 10491 Rishi mdb_warn("failed to read lbolt"); 1564 10491 Rishi goto err; 1565 10491 Rishi } 1566 10491 Rishi 1567 10491 Rishi if (flags & DCMD_ADDRSPEC) { 1568 10491 Rishi if (args->name != NULL) { 1569 10491 Rishi mdb_printf("bridge name and address are mutually " 1570 10491 Rishi "exclusive\n"); 1571 10491 Rishi goto err; 1572 10491 Rishi } 1573 10491 Rishi if (!args->opt_l && !args->opt_f && !args->opt_t) 1574 10491 Rishi mdb_printf("%-?s %-7s %-16s %-7s %-7s\n", "ADDR", 1575 10491 Rishi "PROTECT", "NAME", "NLINKS", "NFWD"); 1576 10491 Rishi if (do_show_bridge(addr, NULL, args) != WALK_NEXT) 1577 10491 Rishi goto err; 1578 10491 Rishi mdb_free(args, sizeof (*args)); 1579 10491 Rishi return (DCMD_OK); 1580 10491 Rishi } else { 1581 10491 Rishi if ((args->opt_l || args->opt_f || args->opt_t) && 1582 10491 Rishi args->name == NULL) { 1583 10491 Rishi mdb_printf("need bridge name or address with -[lft]\n"); 1584 10491 Rishi goto err; 1585 10491 Rishi } 1586 10491 Rishi if (mdb_lookup_by_obj("bridge", "inst_list", &sym) == -1) { 1587 10491 Rishi mdb_warn("failed to find 'bridge`inst_list'"); 1588 10491 Rishi goto err; 1589 10491 Rishi } 1590 10491 Rishi if (!args->opt_l && !args->opt_f && !args->opt_t) 1591 10491 Rishi mdb_printf("%-?s %-7s %-16s %-7s %-7s %-7s %s\n", 1592 10491 Rishi "ADDR", "PROTECT", "NAME", "NLINKS", "NFWD", 1593 10491 Rishi "NNICKS", "NICK"); 1594 10491 Rishi if (mdb_pwalk("list", do_show_bridge, args, 1595 10491 Rishi (uintptr_t)sym.st_value) != DCMD_OK) 1596 10491 Rishi goto err; 1597 10491 Rishi if (!args->found && args->name != NULL) { 1598 10491 Rishi mdb_printf("bridge instance %s not found\n", 1599 10491 Rishi args->name); 1600 10491 Rishi goto err; 1601 10491 Rishi } 1602 10491 Rishi mdb_free(args, sizeof (*args)); 1603 10491 Rishi return (DCMD_OK); 1604 10491 Rishi } 1605 10491 Rishi 1606 10491 Rishi err: 1607 10491 Rishi mdb_free(args, sizeof (*args)); 1608 10491 Rishi return (DCMD_ERR); 1609 10491 Rishi } 1610 10491 Rishi 1611 10491 Rishi /* 1612 10491 Rishi * Support for the "::dladm" dcmd 1613 10491 Rishi */ 1614 10491 Rishi int 1615 10491 Rishi dladm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1616 10491 Rishi { 1617 10491 Rishi if (argc < 1 || argv[0].a_type != MDB_TYPE_STRING) 1618 10491 Rishi return (DCMD_USAGE); 1619 10491 Rishi 1620 10491 Rishi /* 1621 10491 Rishi * This could be a bit more elaborate, once we support more of the 1622 10491 Rishi * dladm show-* subcommands. 1623 10491 Rishi */ 1624 10491 Rishi argc--; 1625 10491 Rishi argv++; 1626 10491 Rishi if (strcmp(argv[-1].a_un.a_str, "show-bridge") == 0) 1627 10491 Rishi return (dladm_show_bridge(addr, flags, argc, argv)); 1628 10491 Rishi 1629 10491 Rishi return (DCMD_USAGE); 1630 10491 Rishi } 1631 10491 Rishi 1632 10491 Rishi void 1633 10491 Rishi dladm_help(void) 1634 10491 Rishi { 1635 10491 Rishi mdb_printf("Subcommands:\n" 1636 10491 Rishi " show-bridge [-flt] [<name>]\n" 1637 10491 Rishi "\t Show bridge information; -l for links and -f for " 1638 10491 Rishi "forwarding\n" 1639 10491 Rishi "\t entries, and -t for TRILL nicknames. Address is required " 1640 10491 Rishi "if name\n" 1641 10491 Rishi "\t is not specified.\n"); 1642 10491 Rishi } 1643