4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <mdb/mdb_modapi.h>
26 #include <mdb/mdb_ks.h>
28 #include <sys/types.h>
29 #include <sys/systm.h>
32 #include <sys/mount.h>
34 #include <sys/procfs.h>
35 #include <sys/proc/prdata.h>
38 #include <sys/vnode.h>
39 #include <sys/fs/snode.h>
40 #include <sys/fs/fifonode.h>
41 #include <sys/fs/namenode.h>
42 #include <sys/socket.h>
43 #include <sys/stropts.h>
44 #include <sys/socketvar.h>
45 #include <sys/strsubr.h>
47 #include <../../../../kernel/fs/sockfs/socktpi_impl.h>
48 #include <inet/ipclassifier.h>
49 #include <inet/ip_if.h>
50 #include <inet/sctp/sctp_impl.h>
51 #include <inet/sctp/sctp_addr.h>
54 vfs_walk_init(mdb_walk_state_t
*wsp
)
56 if (wsp
->walk_addr
== (uintptr_t)NULL
&&
57 mdb_readvar(&wsp
->walk_addr
, "rootvfs") == -1) {
58 mdb_warn("failed to read 'rootvfs'");
62 wsp
->walk_data
= (void *)wsp
->walk_addr
;
67 vfs_walk_step(mdb_walk_state_t
*wsp
)
72 if (mdb_vread(&vfs
, sizeof (vfs
), wsp
->walk_addr
) == -1) {
73 mdb_warn("failed to read vfs_t at %p", wsp
->walk_addr
);
77 status
= wsp
->walk_callback(wsp
->walk_addr
, &vfs
, wsp
->walk_cbdata
);
79 if (vfs
.vfs_next
== wsp
->walk_data
)
82 wsp
->walk_addr
= (uintptr_t)vfs
.vfs_next
;
88 * Utility routine to read in a filesystem name given a vfs pointer. If
89 * no vfssw entry for the vfs is available (as is the case with some pseudo-
90 * filesystems), we check against some known problem fs's: doorfs and
91 * portfs. If that fails, we try to guess the filesystem name using
92 * symbol names. fsname should be a buffer of size _ST_FSTYPSZ.
95 read_fsname(uintptr_t vfsp
, char *fsname
)
98 struct vfssw vfssw_entry
;
99 GElf_Sym vfssw_sym
, test_sym
;
100 char testname
[MDB_SYM_NAMLEN
];
102 if (mdb_vread(&vfs
, sizeof (vfs
), vfsp
) == -1) {
103 mdb_warn("failed to read vfs %p", vfsp
);
107 if (mdb_lookup_by_name("vfssw", &vfssw_sym
) == -1) {
108 mdb_warn("failed to find vfssw");
113 * vfssw is an array; we need vfssw[vfs.vfs_fstype].
115 if (mdb_vread(&vfssw_entry
, sizeof (vfssw_entry
),
116 vfssw_sym
.st_value
+ (sizeof (struct vfssw
) * vfs
.vfs_fstype
))
118 mdb_warn("failed to read vfssw index %d", vfs
.vfs_fstype
);
122 if (vfs
.vfs_fstype
!= 0) {
123 if (mdb_readstr(fsname
, _ST_FSTYPSZ
,
124 (uintptr_t)vfssw_entry
.vsw_name
) == -1) {
125 mdb_warn("failed to find fs name %p",
126 vfssw_entry
.vsw_name
);
133 * Do precise detection for certain filesystem types that we
134 * know do not appear in vfssw[], and that we depend upon in other
135 * parts of the code: doorfs and portfs.
137 if (mdb_lookup_by_name("door_vfs", &test_sym
) != -1) {
138 if (test_sym
.st_value
== vfsp
) {
139 strcpy(fsname
, "doorfs");
143 if (mdb_lookup_by_name("port_vfs", &test_sym
) != -1) {
144 if (test_sym
.st_value
== vfsp
) {
145 strcpy(fsname
, "portfs");
151 * Heuristic detection for other filesystems that don't have a
152 * vfssw[] entry. These tend to be named <fsname>_vfs, so we do a
153 * lookup_by_addr and see if we find a symbol of that name.
155 if (mdb_lookup_by_addr(vfsp
, MDB_SYM_EXACT
, testname
, sizeof (testname
),
157 if ((strlen(testname
) > 4) &&
158 (strcmp(testname
+ strlen(testname
) - 4, "_vfs") == 0)) {
159 testname
[strlen(testname
) - 4] = '\0';
160 strncpy(fsname
, testname
, _ST_FSTYPSZ
);
165 mdb_warn("unknown filesystem type for vfs %p", vfsp
);
170 * Column widths for mount point display in ::fsinfo output.
173 #define FSINFO_MNTLEN 48
175 #define FSINFO_MNTLEN 56
180 fsinfo(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
185 char buf
[MAXPATHLEN
];
186 char fsname
[_ST_FSTYPSZ
];
191 char opt
[MAX_MNTOPT_STR
];
192 uintptr_t global_zone
;
194 if (!(flags
& DCMD_ADDRSPEC
)) {
195 if (mdb_walk_dcmd("vfs", "fsinfo", argc
, argv
) == -1) {
196 mdb_warn("failed to walk file system list");
202 if (mdb_getopts(argc
, argv
,
203 'v', MDB_OPT_SETBITS
, TRUE
, &opt_v
, NULL
) != argc
)
206 if (DCMD_HDRSPEC(flags
))
207 mdb_printf("%<u>%?s %-15s %s%</u>\n",
208 "VFSP", "FS", "MOUNT");
210 if (mdb_vread(&vfs
, sizeof (vfs
), addr
) == -1) {
211 mdb_warn("failed to read vfs_t %p", addr
);
215 if ((len
= mdb_read_refstr((uintptr_t)vfs
.vfs_mntpt
, buf
,
219 else if (!opt_v
&& (len
>= FSINFO_MNTLEN
))
221 * In normal mode, we truncate the path to keep the output
222 * clean. In -v mode, we just print the full path.
224 strcpy(&buf
[FSINFO_MNTLEN
- 4], "...");
226 if (read_fsname(addr
, fsname
) == -1)
229 mdb_printf("%0?p %-15s %s\n", addr
, fsname
, buf
);
235 * Print 'resource' string; this shows what we're mounted upon.
237 if (mdb_read_refstr((uintptr_t)vfs
.vfs_resource
, buf
,
241 mdb_printf("%?s %s\n", "R:", buf
);
244 * Print mount options array; it sucks to be a mimic, but we copy
245 * the same logic as in mntvnops.c for adding zone= tags, and we
246 * don't bother with the obsolete dev= option.
248 size
= vfs
.vfs_mntopts
.mo_count
* sizeof (mntopt_t
);
249 mntopts
= mdb_alloc(size
, UM_SLEEP
| UM_GC
);
251 if (mdb_vread(mntopts
, size
,
252 (uintptr_t)vfs
.vfs_mntopts
.mo_list
) == -1) {
253 mdb_warn("failed to read mntopts %p", vfs
.vfs_mntopts
.mo_list
);
257 for (i
= 0; i
< vfs
.vfs_mntopts
.mo_count
; i
++) {
258 if (mntopts
[i
].mo_flags
& MO_SET
) {
259 if (mdb_readstr(opt
, sizeof (opt
),
260 (uintptr_t)mntopts
[i
].mo_name
) == -1) {
261 mdb_warn("failed to read mntopt name %p",
266 mdb_printf("%?s ", "O:");
271 mdb_printf("%s", opt
);
272 if (mntopts
[i
].mo_flags
& MO_HASVALUE
) {
273 if (mdb_readstr(opt
, sizeof (opt
),
274 (uintptr_t)mntopts
[i
].mo_arg
) == -1) {
275 mdb_warn("failed to read mntopt "
276 "value %p", mntopts
[i
].mo_arg
);
279 mdb_printf("=%s", opt
);
284 if (mdb_readvar(&global_zone
, "global_zone") == -1) {
285 mdb_warn("failed to locate global_zone");
289 if ((vfs
.vfs_zone
!= NULL
) &&
290 ((uintptr_t)vfs
.vfs_zone
!= global_zone
)) {
293 if (mdb_vread(&z
, sizeof (z
), (uintptr_t)vfs
.vfs_zone
) == -1) {
294 mdb_warn("failed to read zone");
298 * zone names are much shorter than MAX_MNTOPT_STR
300 if (mdb_readstr(opt
, sizeof (opt
),
301 (uintptr_t)z
.zone_name
) == -1) {
302 mdb_warn("failed to read zone name");
306 mdb_printf("%?s ", "O:");
310 mdb_printf("zone=%s", opt
);
316 #define REALVP_DONE 0
318 #define REALVP_CONTINUE 2
321 next_realvp(uintptr_t invp
, struct vnode
*outvn
, uintptr_t *outvp
)
323 char fsname
[_ST_FSTYPSZ
];
326 if (mdb_vread(outvn
, sizeof (struct vnode
), invp
) == -1) {
327 mdb_warn("failed to read vnode at %p", invp
);
331 if (read_fsname((uintptr_t)outvn
->v_vfsp
, fsname
) == -1)
335 * We know how to do 'realvp' for as many filesystems as possible;
336 * for all other filesystems, we assume that the vp we are given
337 * is the realvp. In the kernel, a realvp operation will sometimes
338 * dig through multiple layers. Here, we only fetch the pointer
339 * to the next layer down. This allows dcmds to print out the
342 if (strcmp(fsname
, "fifofs") == 0) {
344 if (mdb_vread(&fn
, sizeof (fn
),
345 (uintptr_t)outvn
->v_data
) == -1) {
346 mdb_warn("failed to read fifonode");
349 *outvp
= (uintptr_t)fn
.fn_realvp
;
351 } else if (strcmp(fsname
, "namefs") == 0) {
353 if (mdb_vread(&nn
, sizeof (nn
),
354 (uintptr_t)outvn
->v_data
) == -1) {
355 mdb_warn("failed to read namenode");
358 *outvp
= (uintptr_t)nn
.nm_filevp
;
360 } else if (outvn
->v_type
== VSOCK
&& outvn
->v_stream
!= NULL
) {
361 struct stdata stream
;
364 * Sockets have a strange and different layering scheme; we
365 * hop over into the sockfs vnode (accessible via the stream
368 if (mdb_vread(&stream
, sizeof (stream
),
369 (uintptr_t)outvn
->v_stream
) == -1) {
370 mdb_warn("failed to read stream data");
373 *outvp
= (uintptr_t)stream
.sd_vnode
;
376 if (*outvp
== invp
|| *outvp
== (uintptr_t)NULL
)
377 return (REALVP_DONE
);
379 return (REALVP_CONTINUE
);
383 pfiles_print_addr(struct sockaddr
*addr
)
385 struct sockaddr_in
*s_in
;
386 struct sockaddr_un
*s_un
;
387 struct sockaddr_in6
*s_in6
;
390 switch (addr
->sa_family
) {
392 /* LINTED: alignment */
393 s_in
= (struct sockaddr_in
*)addr
;
394 mdb_nhconvert(&port
, &s_in
->sin_port
, sizeof (port
));
395 mdb_printf("AF_INET %I %d ", s_in
->sin_addr
.s_addr
, port
);
399 /* LINTED: alignment */
400 s_in6
= (struct sockaddr_in6
*)addr
;
401 mdb_nhconvert(&port
, &s_in6
->sin6_port
, sizeof (port
));
402 mdb_printf("AF_INET6 %N %d ", &(s_in6
->sin6_addr
), port
);
406 s_un
= (struct sockaddr_un
*)addr
;
407 mdb_printf("AF_UNIX %s ", s_un
->sun_path
);
410 mdb_printf("AF_?? (%d) ", addr
->sa_family
);
416 pfiles_get_sonode(vnode_t
*v_sock
, struct sonode
*sonode
)
418 if (mdb_vread(sonode
, sizeof (struct sonode
),
419 (uintptr_t)v_sock
->v_data
) == -1) {
420 mdb_warn("failed to read sonode");
428 pfiles_get_tpi_sonode(vnode_t
*v_sock
, sotpi_sonode_t
*sotpi_sonode
)
431 struct stdata stream
;
433 if (mdb_vread(&stream
, sizeof (stream
),
434 (uintptr_t)v_sock
->v_stream
) == -1) {
435 mdb_warn("failed to read stream data");
439 if (mdb_vread(v_sock
, sizeof (vnode_t
),
440 (uintptr_t)stream
.sd_vnode
) == -1) {
441 mdb_warn("failed to read stream vnode");
445 if (mdb_vread(sotpi_sonode
, sizeof (sotpi_sonode_t
),
446 (uintptr_t)v_sock
->v_data
) == -1) {
447 mdb_warn("failed to read sotpi_sonode");
455 * Do some digging to get a reasonable pathname for this vnode. 'path'
456 * should point at a buffer of MAXPATHLEN in size.
459 pfiles_dig_pathname(uintptr_t vp
, char *path
)
463 bzero(path
, MAXPATHLEN
);
465 if (mdb_vread(&v
, sizeof (v
), vp
) == -1) {
466 mdb_warn("failed to read vnode");
470 if (v
.v_path
== NULL
) {
472 * fifo's and doors are special. Some have pathnames, and
473 * some do not. And for these, it is pointless to go off to
474 * mdb_vnode2path, which is very slow.
476 * Event ports never have a pathname.
478 if (v
.v_type
== VFIFO
|| v
.v_type
== VDOOR
|| v
.v_type
== VPORT
)
482 * For sockets, we won't find a path unless we print the path
483 * associated with transport's STREAM device.
485 if (v
.v_type
== VSOCK
) {
486 struct sonode sonode
;
487 struct sockparams sockparams
;
489 if (pfiles_get_sonode(&v
, &sonode
) == -1) {
492 if (mdb_vread(&sockparams
, sizeof (sockparams
),
493 (uintptr_t)sonode
.so_sockparams
) == -1) {
494 mdb_warn("failed to read sockparams");
498 if (!SOCK_IS_NONSTR(&sonode
)) {
500 sockparams
.sp_sdev_info
.sd_vnode
;
502 vp
= (uintptr_t)NULL
;
509 * mdb_vnode2path will print an error for us as needed, but not
510 * finding a pathname is not really an error, so we plow on.
512 (void) mdb_vnode2path(vp
, path
, MAXPATHLEN
);
515 * A common problem is that device pathnames are prefixed with
516 * /dev/../devices/. We just clean those up slightly:
517 * /dev/../devices/<mumble> --> /devices/<mumble>
518 * /dev/pts/../../devices/<mumble> --> /devices/<mumble>
520 if (strncmp("/dev/../devices/", path
, strlen("/dev/../devices/")) == 0)
521 strcpy(path
, path
+ 7);
523 if (strncmp("/dev/pts/../../devices/", path
,
524 strlen("/dev/pts/../../devices/")) == 0)
525 strcpy(path
, path
+ 14);
530 const struct fs_type
{
548 #define NUM_FS_TYPES (sizeof (fs_types) / sizeof (struct fs_type))
550 struct pfiles_cbdata
{
555 #define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset))
556 #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset))
559 * SCTP interface for geting the first source address of a sctp_t.
562 sctp_getsockaddr(sctp_t
*sctp
, struct sockaddr
*addr
)
567 sctp_saddr_ipif_t
*pobj
;
568 sctp_saddr_ipif_t obj
;
573 boolean_t skip_lback
= B_FALSE
;
574 conn_t
*connp
= sctp
->sctp_connp
;
576 addr
->sa_family
= connp
->conn_family
;
577 if (sctp
->sctp_nsaddrs
== 0)
581 * Skip loopback addresses for non-loopback assoc.
583 if (sctp
->sctp_state
>= SCTPS_ESTABLISHED
&& !sctp
->sctp_loopback
) {
587 for (i
= 0; i
< SCTP_IPIF_HASH
; i
++) {
588 if (sctp
->sctp_saddrs
[i
].ipif_count
== 0)
591 pobj
= list_object(&sctp
->sctp_saddrs
[i
].sctp_ipif_list
,
592 sctp
->sctp_saddrs
[i
].sctp_ipif_list
.list_head
.list_next
);
593 if (mdb_vread(&obj
, sizeof (sctp_saddr_ipif_t
),
594 (uintptr_t)pobj
) == -1) {
595 mdb_warn("failed to read sctp_saddr_ipif_t");
599 for (l
= 0; l
< sctp
->sctp_saddrs
[i
].ipif_count
; l
++) {
605 if (mdb_vread(&ipif
, sizeof (sctp_ipif_t
),
606 (uintptr_t)obj
.saddr_ipifp
) == -1) {
607 mdb_warn("failed to read sctp_ipif_t");
610 laddr
= ipif
.sctp_ipif_saddr
;
613 if ((ipif
.sctp_ipif_state
== SCTP_IPIFS_CONDEMNED
) ||
614 SCTP_DONT_SRC(&obj
) ||
615 (ipif
.sctp_ipif_ill
->sctp_ill_flags
&
616 PHYI_LOOPBACK
) && skip_lback
) {
617 if (scanned
>= sctp
->sctp_nsaddrs
)
620 /* LINTED: alignment */
621 pnode
= list_d2l(&sctp
->sctp_saddrs
[i
].
622 sctp_ipif_list
, pobj
);
623 if (mdb_vread(&node
, sizeof (list_node_t
),
624 (uintptr_t)pnode
) == -1) {
625 mdb_warn("failed to read list_node_t");
628 pobj
= list_object(&sctp
->sctp_saddrs
[i
].
629 sctp_ipif_list
, node
.list_next
);
630 if (mdb_vread(&obj
, sizeof (sctp_saddr_ipif_t
),
631 (uintptr_t)pobj
) == -1) {
632 mdb_warn("failed to read "
633 "sctp_saddr_ipif_t");
639 switch (connp
->conn_family
) {
641 /* LINTED: alignment */
642 sin4
= (sin_t
*)addr
;
643 if ((sctp
->sctp_state
<= SCTPS_LISTEN
) &&
644 sctp
->sctp_bound_to_all
) {
645 sin4
->sin_addr
.s_addr
= INADDR_ANY
;
646 sin4
->sin_port
= connp
->conn_lport
;
649 sin4
->sin_family
= AF_INET
;
650 sin4
->sin_port
= connp
->conn_lport
;
651 IN6_V4MAPPED_TO_INADDR(&laddr
,
657 /* LINTED: alignment */
658 sin6
= (sin6_t
*)addr
;
659 if ((sctp
->sctp_state
<= SCTPS_LISTEN
) &&
660 sctp
->sctp_bound_to_all
) {
661 bzero(&sin6
->sin6_addr
,
662 sizeof (sin6
->sin6_addr
));
663 sin6
->sin6_port
= connp
->conn_lport
;
666 sin6
->sin6_family
= AF_INET6
;
667 sin6
->sin6_port
= connp
->conn_lport
;
668 sin6
->sin6_addr
= laddr
;
670 sin6
->sin6_flowinfo
= connp
->conn_flowinfo
;
671 sin6
->sin6_scope_id
= 0;
672 sin6
->__sin6_src_id
= 0;
680 if (scanned
>= sctp
->sctp_nsaddrs
)
683 /* LINTED: alignment */
684 pnode
= list_d2l(&sctp
->sctp_saddrs
[i
].sctp_ipif_list
,
686 if (mdb_vread(&node
, sizeof (list_node_t
),
687 (uintptr_t)pnode
) == -1) {
688 mdb_warn("failed to read list_node_t");
691 pobj
= list_object(&sctp
->sctp_saddrs
[i
].
692 sctp_ipif_list
, node
.list_next
);
693 if (mdb_vread(&obj
, sizeof (sctp_saddr_ipif_t
),
694 (uintptr_t)pobj
) == -1) {
695 mdb_warn("failed to read sctp_saddr_ipif_t");
705 * SCTP interface for geting the primary peer address of a sctp_t.
708 sctp_getpeeraddr(sctp_t
*sctp
, struct sockaddr
*addr
)
710 struct sockaddr_in
*sin4
;
711 struct sockaddr_in6
*sin6
;
712 sctp_faddr_t sctp_primary
;
714 conn_t
*connp
= sctp
->sctp_connp
;
716 if (sctp
->sctp_faddrs
== NULL
)
719 addr
->sa_family
= connp
->conn_family
;
720 if (mdb_vread(&sctp_primary
, sizeof (sctp_faddr_t
),
721 (uintptr_t)sctp
->sctp_primary
) == -1) {
722 mdb_warn("failed to read sctp primary faddr");
725 faddr
= sctp_primary
.sf_faddr
;
727 switch (connp
->conn_family
) {
729 /* LINTED: alignment */
730 sin4
= (struct sockaddr_in
*)addr
;
731 IN6_V4MAPPED_TO_INADDR(&faddr
, &sin4
->sin_addr
);
732 sin4
->sin_port
= connp
->conn_fport
;
733 sin4
->sin_family
= AF_INET
;
737 /* LINTED: alignment */
738 sin6
= (struct sockaddr_in6
*)addr
;
739 sin6
->sin6_addr
= faddr
;
740 sin6
->sin6_port
= connp
->conn_fport
;
741 sin6
->sin6_family
= AF_INET6
;
742 sin6
->sin6_flowinfo
= 0;
743 sin6
->sin6_scope_id
= 0;
744 sin6
->__sin6_src_id
= 0;
752 tpi_sock_print(sotpi_sonode_t
*sotpi_sonode
)
754 if (sotpi_sonode
->st_info
.sti_laddr_valid
== 1) {
755 struct sockaddr
*laddr
=
756 mdb_alloc(sotpi_sonode
->st_info
.sti_laddr_len
, UM_SLEEP
);
757 if (mdb_vread(laddr
, sotpi_sonode
->st_info
.sti_laddr_len
,
758 (uintptr_t)sotpi_sonode
->st_info
.sti_laddr_sa
) == -1) {
759 mdb_warn("failed to read sotpi_sonode socket addr");
763 mdb_printf("socket: ");
764 pfiles_print_addr(laddr
);
767 if (sotpi_sonode
->st_info
.sti_faddr_valid
== 1) {
768 struct sockaddr
*faddr
=
769 mdb_alloc(sotpi_sonode
->st_info
.sti_faddr_len
, UM_SLEEP
);
770 if (mdb_vread(faddr
, sotpi_sonode
->st_info
.sti_faddr_len
,
771 (uintptr_t)sotpi_sonode
->st_info
.sti_faddr_sa
) == -1) {
772 mdb_warn("failed to read sotpi_sonode remote addr");
776 mdb_printf("remote: ");
777 pfiles_print_addr(faddr
);
784 tcpip_sock_print(struct sonode
*socknode
)
786 switch (socknode
->so_family
) {
792 if (mdb_vread(&conn_t
, sizeof (conn_t
),
793 (uintptr_t)socknode
->so_proto_handle
) == -1) {
794 mdb_warn("failed to read conn_t V4");
798 mdb_printf("socket: ");
799 mdb_nhconvert(&port
, &conn_t
.conn_lport
, sizeof (port
));
800 mdb_printf("AF_INET %I %d ", conn_t
.conn_laddr_v4
, port
);
803 * If this is a listening socket, we don't print
804 * the remote address.
806 if (IPCL_IS_TCP(&conn_t
) && IPCL_IS_BOUND(&conn_t
) == 0 ||
807 IPCL_IS_UDP(&conn_t
) && IPCL_IS_CONNECTED(&conn_t
)) {
808 mdb_printf("remote: ");
809 mdb_nhconvert(&port
, &conn_t
.conn_fport
, sizeof (port
));
810 mdb_printf("AF_INET %I %d ", conn_t
.conn_faddr_v4
,
822 if (mdb_vread(&conn_t
, sizeof (conn_t
),
823 (uintptr_t)socknode
->so_proto_handle
) == -1) {
824 mdb_warn("failed to read conn_t V6");
828 mdb_printf("socket: ");
829 mdb_nhconvert(&port
, &conn_t
.conn_lport
, sizeof (port
));
830 mdb_printf("AF_INET6 %N %d ", &conn_t
.conn_laddr_v4
, port
);
833 * If this is a listening socket, we don't print
834 * the remote address.
836 if (IPCL_IS_TCP(&conn_t
) && IPCL_IS_BOUND(&conn_t
) == 0 ||
837 IPCL_IS_UDP(&conn_t
) && IPCL_IS_CONNECTED(&conn_t
)) {
838 mdb_printf("remote: ");
839 mdb_nhconvert(&port
, &conn_t
.conn_fport
, sizeof (port
));
840 mdb_printf("AF_INET6 %N %d ", &conn_t
.conn_faddr_v6
,
848 mdb_printf("AF_?? (%d)", socknode
->so_family
);
856 sctp_sock_print(struct sonode
*socknode
)
861 struct sockaddr
*laddr
= mdb_alloc(sizeof (struct sockaddr
), UM_SLEEP
);
862 struct sockaddr
*faddr
= mdb_alloc(sizeof (struct sockaddr
), UM_SLEEP
);
864 if (mdb_vread(&sctp_t
, sizeof (sctp_t
),
865 (uintptr_t)socknode
->so_proto_handle
) == -1) {
866 mdb_warn("failed to read sctp_t");
870 if (mdb_vread(&conns
, sizeof (conn_t
),
871 (uintptr_t)sctp_t
.sctp_connp
) == -1) {
872 mdb_warn("failed to read conn_t at %p",
873 (uintptr_t)sctp_t
.sctp_connp
);
876 sctp_t
.sctp_connp
= &conns
;
878 if (sctp_getsockaddr(&sctp_t
, laddr
) == 0) {
879 mdb_printf("socket:");
880 pfiles_print_addr(laddr
);
882 if (sctp_getpeeraddr(&sctp_t
, faddr
) == 0) {
883 mdb_printf("remote:");
884 pfiles_print_addr(faddr
);
892 sdp_sock_print(struct sonode
*socknode
)
901 int (*print
)(struct sonode
*socknode
);
903 { 2, 2, 0, tcpip_sock_print
}, /* /dev/tcp */
904 { 2, 2, 6, tcpip_sock_print
}, /* /dev/tcp */
905 { 26, 2, 0, tcpip_sock_print
}, /* /dev/tcp6 */
906 { 26, 2, 6, tcpip_sock_print
}, /* /dev/tcp6 */
907 { 2, 1, 0, tcpip_sock_print
}, /* /dev/udp */
908 { 2, 1, 17, tcpip_sock_print
}, /* /dev/udp */
909 { 26, 1, 0, tcpip_sock_print
}, /* /dev/udp6 */
910 { 26, 1, 17, tcpip_sock_print
}, /* /dev/udp6 */
911 { 2, 4, 0, tcpip_sock_print
}, /* /dev/rawip */
912 { 26, 4, 0, tcpip_sock_print
}, /* /dev/rawip6 */
913 { 2, 2, 132, sctp_sock_print
}, /* /dev/sctp */
914 { 26, 2, 132, sctp_sock_print
}, /* /dev/sctp6 */
915 { 2, 6, 132, sctp_sock_print
}, /* /dev/sctp */
916 { 26, 6, 132, sctp_sock_print
}, /* /dev/sctp6 */
917 { 24, 4, 0, tcpip_sock_print
}, /* /dev/rts */
918 { 2, 2, 257, sdp_sock_print
}, /* /dev/sdp */
919 { 26, 2, 257, sdp_sock_print
}, /* /dev/sdp */
922 #define NUM_SOCK_PRINTS \
923 (sizeof (sock_prints) / sizeof (struct sock_print))
926 pfile_callback(uintptr_t addr
, const struct file
*f
, struct pfiles_cbdata
*cb
)
931 char path
[MAXPATHLEN
];
932 uintptr_t top_vnodep
, realvpp
;
933 char fsname
[_ST_FSTYPSZ
];
938 if (addr
== (uintptr_t)NULL
) {
942 top_vnodep
= realvpp
= (uintptr_t)f
->f_vnode
;
944 if (mdb_vread(&v
, sizeof (v
), realvpp
) == -1) {
945 mdb_warn("failed to read vnode");
950 for (i
= 0; i
< NUM_FS_TYPES
; i
++) {
951 if (fs_types
[i
].type
== v
.v_type
) {
952 type
= fs_types
[i
].name
;
958 uintptr_t next_realvpp
;
960 err
= next_realvp(realvpp
, &layer_vn
, &next_realvpp
);
961 if (next_realvpp
!= (uintptr_t)NULL
)
962 realvpp
= next_realvpp
;
964 } while (err
== REALVP_CONTINUE
);
966 if (err
== REALVP_ERR
) {
967 mdb_warn("failed to do realvp() for %p", realvpp
);
971 if (read_fsname((uintptr_t)layer_vn
.v_vfsp
, fsname
) == -1)
974 mdb_printf("%4d %4s %?0p ", myfd
, type
, top_vnodep
);
977 if (pfiles_dig_pathname(top_vnodep
, path
) == -1)
980 mdb_printf("%s\n", path
);
985 * Sockets generally don't have interesting pathnames; we only
986 * show those in the '-p' view.
989 if (v
.v_type
!= VSOCK
) {
990 if (pfiles_dig_pathname(top_vnodep
, path
) == -1)
993 mdb_printf("%s%s", path
, path
[0] == '\0' ? "" : " ");
998 door_node_t doornode
;
1001 if (mdb_vread(&doornode
, sizeof (doornode
),
1002 (uintptr_t)layer_vn
.v_data
) == -1) {
1003 mdb_warn("failed to read door_node");
1007 if (mdb_vread(&pr
, sizeof (pr
),
1008 (uintptr_t)doornode
.door_target
) == -1) {
1009 mdb_warn("failed to read door server process %p",
1010 doornode
.door_target
);
1013 mdb_printf("[door to '%s' (proc=%p)]", pr
.p_user
.u_comm
,
1014 doornode
.door_target
);
1023 if (mdb_vread(&v_sock
, sizeof (v_sock
), realvpp
) == -1) {
1024 mdb_warn("failed to read socket vnode");
1029 * Sockets can be non-stream or stream, they have to be dealed
1032 if (v_sock
.v_stream
== NULL
) {
1033 if (pfiles_get_sonode(&v_sock
, &so
) == -1)
1036 /* Pick the proper methods. */
1037 for (i
= 0; i
<= NUM_SOCK_PRINTS
; i
++) {
1038 if ((sock_prints
[i
].family
== so
.so_family
&&
1039 sock_prints
[i
].type
== so
.so_type
&&
1040 sock_prints
[i
].pro
== so
.so_protocol
) ||
1041 (sock_prints
[i
].family
== so
.so_family
&&
1042 sock_prints
[i
].type
== so
.so_type
&&
1043 so
.so_type
== SOCK_RAW
)) {
1044 if ((*sock_prints
[i
].print
)(&so
) == -1)
1049 sotpi_sonode_t sotpi_sonode
;
1051 if (pfiles_get_sonode(&v_sock
, &so
) == -1)
1055 * If the socket is a fallback socket, read its related
1056 * information separately; otherwise, read it as a whole
1059 if (so
.so_state
& SS_FALLBACK_COMP
) {
1060 sotpi_sonode
.st_sonode
= so
;
1062 if (mdb_vread(&(sotpi_sonode
.st_info
),
1063 sizeof (sotpi_info_t
),
1064 (uintptr_t)so
.so_priv
) == -1)
1067 if (pfiles_get_tpi_sonode(&v_sock
,
1068 &sotpi_sonode
) == -1)
1072 if (tpi_sock_print(&sotpi_sonode
) == -1)
1080 mdb_printf("[event port (port=%p)]", v
.v_data
);
1086 prcommon_t prcommon
;
1088 if (mdb_vread(&prnode
, sizeof (prnode
),
1089 (uintptr_t)layer_vn
.v_data
) == -1) {
1090 mdb_warn("failed to read prnode");
1094 if (mdb_vread(&prcommon
, sizeof (prcommon
),
1095 (uintptr_t)prnode
.pr_common
) == -1) {
1096 mdb_warn("failed to read prcommon %p",
1101 mdb_printf("(proc=%p)", prcommon
.prc_proc
);
1115 file_t_callback(uintptr_t addr
, const struct file
*f
, struct pfiles_cbdata
*cb
)
1121 if (addr
== (uintptr_t)NULL
) {
1126 * We really need 20 digits to print a 64-bit offset_t, but this
1127 * is exceedingly rare, so we cheat and assume a column width of 10
1128 * digits, in order to fit everything cleanly into 80 columns.
1130 mdb_printf("%?0p %4d %8x %?0p %10lld %?0p %4d\n",
1131 addr
, myfd
, f
->f_flag
, f
->f_vnode
, f
->f_offset
, f
->f_cred
,
1138 pfiles(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1142 struct pfiles_cbdata cb
;
1144 bzero(&cb
, sizeof (cb
));
1146 if (!(flags
& DCMD_ADDRSPEC
))
1147 return (DCMD_USAGE
);
1149 if (mdb_getopts(argc
, argv
,
1150 'p', MDB_OPT_SETBITS
, TRUE
, &cb
.opt_p
,
1151 'f', MDB_OPT_SETBITS
, TRUE
, &opt_f
, NULL
) != argc
)
1152 return (DCMD_USAGE
);
1155 mdb_printf("%<u>%?s %4s %8s %?s %10s %?s %4s%</u>\n", "FILE",
1156 "FD", "FLAG", "VNODE", "OFFSET", "CRED", "CNT");
1157 if (mdb_pwalk("allfile", (mdb_walk_cb_t
)file_t_callback
, &cb
,
1159 mdb_warn("failed to walk 'allfile'");
1163 mdb_printf("%<u>%-4s %4s %?s ", "FD", "TYPE", "VNODE");
1168 mdb_printf("%</u>\n");
1170 if (mdb_pwalk("allfile", (mdb_walk_cb_t
)pfile_callback
, &cb
,
1172 mdb_warn("failed to walk 'allfile'");
1185 "Given the address of a process, print information about files\n"
1186 "which the process has open. By default, this includes decoded\n"
1187 "information about the file depending on file and filesystem type\n"
1189 "\t-p\tPathnames; omit decoded information. Only display "
1191 "\t-f\tfile_t view; show the file_t structure corresponding to "