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