smbsrv.c revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/mdb_modapi.h>
#include <smbsrv/smb_vops.h>
#define SMB_DCMD_INDENT 4
int slen);
/*
* Initialize the smb_session_t walker by reading the value of smb_info
* object in the kernel's symbol table. Only global walk supported.
*/
static int
{
mdb_warn("failed to find 'smb_info'");
return (WALK_ERR);
}
} else {
mdb_printf("smb_session walk only supports global walks\n");
return (WALK_ERR);
}
mdb_warn("failed to walk 'list'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
wsp->walk_cbdata));
}
/*
* Initialize the smb_node_t walker by reading the value of smb_info
* object in the kernel's symbol table. Only global walk supported.
*/
static int
{
int i;
mdb_warn("failed to find 'smb_info'");
return (WALK_ERR);
}
} else {
mdb_printf("smb_node walk only supports global walks\n");
return (WALK_ERR);
}
for (i = 0; i < SMBND_HASH_MASK + 1; i++) {
(i * sizeof (smb_llist_t)) +
mdb_warn("failed to walk 'list'");
return (WALK_ERR);
}
}
return (WALK_NEXT);
}
static int
{
wsp->walk_cbdata));
}
/*
* ::smb_info
*
* smb_info dcmd - Print out the smb_info structure.
*/
/*ARGSUSED*/
static int
{
int print_config = FALSE;
char state_name[40];
char last_state_name[40];
return (DCMD_USAGE);
if (flags & DCMD_ADDRSPEC)
return (DCMD_USAGE);
mdb_warn("failed to find symbol smb_info");
return (DCMD_ERR);
}
mdb_warn("failed to read smb_info structure");
return (DCMD_ERR);
}
/* Lookup state string */
state_name, 40);
last_state_name, 40);
mdb_printf("SMB information:\n\n");
mdb_printf(" Active Sessions :\t%d\n",
mdb_printf("Deferred Sessions :\t%d\n",
if (print_config) {
mdb_printf("Configuration:\n\n");
(void) mdb_inc_indent(SMB_DCMD_INDENT);
mdb_printf("Max Buffer Size %d\n",
mdb_printf("Max Worker Thread %d\n",
mdb_printf("Max Connections %d\n",
mdb_printf("Keep Alive Timeout %d\n",
mdb_printf("%sRestrict Anonymous Access\n",
mdb_printf("Signing %s\n",
mdb_printf("Signing %sRequired\n",
mdb_printf("Signing Check %s\n",
mdb_printf("Oplocks %s\n",
mdb_printf("Oplock Timeout %d millisec\n",
mdb_printf("Flush %sRequired\n",
mdb_printf("Sync %s\n",
mdb_printf("Dir Symlink %s\n",
"Enabled" : "Disabled");
mdb_printf("%sAnnounce Quota\n",
(void) mdb_dec_indent(SMB_DCMD_INDENT);
mdb_printf("\n");
}
return (DCMD_OK);
}
static void
{
if (mdb_lookup_by_name("smb_svcstate_state_name",
return;
}
/* Lookup state string */
statename_addr_addr) == -1) {
return;
} else {
return;
}
}
}
static void
smb_node_help(void)
{
"Display the contents of smb_node_t, with optional filtering.\n\n");
mdb_dec_indent(2);
mdb_printf("%<b>OPTIONS%</b>\n");
mdb_inc_indent(2);
"-v\tDisplay verbose smb_node information\n"
"-p\tDisplay the full path of the vnode associated\n"
"-s\tDisplay the stack of the last 16 calls that modified the "
"reference\n\tcount\n");
}
/*
* ::smb_node
*
* smb_node dcmd - Print out smb_node structure.
*/
/*ARGSUSED*/
static int
{
int print_full_path = FALSE;
int stack_trace = FALSE;
char od_name[MAXNAMELEN];
char path_name[1024];
return (DCMD_USAGE);
/*
* If no smb_node address was specified on the command line, we can
* print out all smb nodes by invoking the smb_node walker, using
* this dcmd itself as the callback.
*/
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("failed to walk 'smb_node'");
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("SMB node information:\n\n");
else
mdb_printf("%<u>%?s %?s %18s %6s %5s %4s%</u>\n",
"SMB Nodes:", "VP", "NODE NAME",
"OFILES", "LOCKS", "REF");
}
/*
* For each smb_node, we just need to read the smb_node_t struct,
* read and then print out the following fields.
*/
if (print_full_path) {
sizeof (vnode_t)) {
(void) mdb_snprintf(od_name,
MAXNAMELEN, "N/A");
}
}
}
if (verbose) {
mdb_printf("VP :\t%p\n",
mdb_printf("Name :\t%s\n",
od_name);
if (print_full_path) {
mdb_printf("V-node Path :\t%s\n",
}
mdb_printf("Ofiles :\t%u\n",
mdb_printf("Range Locks :\t%u\n",
(void) mdb_inc_indent(SMB_DCMD_INDENT);
mdb_warn("failed to walk node's active"
" locks");
}
(void) mdb_dec_indent(SMB_DCMD_INDENT);
}
mdb_printf("Reference Count :\t%u\n",
mdb_printf("\n");
} else {
mdb_printf("%?p %?p %18s %5d %5d %4d\n",
if (print_full_path) {
sizeof (vnode_t)) {
mdb_printf("\t%s\n",
}
}
}
}
int ctr;
UM_SLEEP);
mdb_warn("failed to read audit buffer");
return (DCMD_ERR);
}
while (ctr) {
char c[MDB_SYM_NAMLEN];
int i;
mdb_printf("\nRefCnt: %u\t",
anr->anr_refcnt);
for (i = 0;
i++) {
if (mdb_lookup_by_addr(
c, sizeof (c),
&sym) == -1) {
continue;
}
mdb_printf("%s+0x%1x",
c,
++i;
break;
}
if (mdb_lookup_by_addr(
c, sizeof (c),
&sym) == -1) {
++i;
continue;
}
mdb_printf("\n\t\t%s+0x%1x",
c,
++i;
}
mdb_printf("\n");
}
ctr--;
}
}
} else {
return (DCMD_ERR);
}
return (DCMD_OK);
}
static void
smb_session_help(void)
{
"Display the contents of smb_session_t, with optional"
" filtering.\n\n");
mdb_dec_indent(2);
mdb_printf("%<b>OPTIONS%</b>\n");
mdb_inc_indent(2);
"-v\tDisplay verbose smb_session information\n"
"-r\tDisplay the list of smb requests attached\n"
"-u\tDisplay the list of users attached\n");
}
/*
* ::smb_session
*
* smb_session dcmd - Print out the smb_session structure.
*/
/*ARGSUSED*/
static int
{
int print_requests = FALSE;
int print_users = FALSE;
return (DCMD_USAGE);
/*
* If no smb_session address was specified on the command line, we can
* print out all smb sessions by invoking the smb_session walker, using
* this dcmd itself as the callback.
*/
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("failed to walk 'smb_session'");
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("SMB session information:\n\n");
else
mdb_printf("%<u>%-?s %16s %16s %5s %10s%</u>\n",
"Sessions:", "CLIENT_IP_ADDR", "LOCAL_IP_ADDR",
"KID", "STATE");
}
/*
* For each smb_session, we just need to read the smb_session_t struct,
* read and then print out the following fields.
*/
if (verbose) {
mdb_printf("IP address :\t%I\n",
mdb_printf("Local IP Address:\t%I\n",
mdb_printf("Session KID :\t%u\n",
mdb_printf("Workstation Name:\t%s\n",
mdb_printf("Session state :\t%u\n",
mdb_printf("users :\t%u\n",
mdb_printf("trees :\t%u\n",
mdb_printf("files :\t%u\n",
mdb_printf("shares :\t%u\n",
mdb_printf("xa count :\t%u\n\n",
mdb_printf("\n");
} else {
}
} else {
return (DCMD_ERR);
}
if (print_requests) {
(void) mdb_inc_indent(SMB_DCMD_INDENT);
mdb_warn("failed to walk request list\n");
(void) mdb_dec_indent(SMB_DCMD_INDENT);
return (DCMD_ERR);
}
(void) mdb_dec_indent(SMB_DCMD_INDENT);
}
if (print_users) {
(void) mdb_inc_indent(SMB_DCMD_INDENT);
mdb_warn("failed to walk user list\n");
(void) mdb_dec_indent(SMB_DCMD_INDENT);
return (DCMD_ERR);
}
(void) mdb_dec_indent(SMB_DCMD_INDENT);
}
return (DCMD_OK);
}
static int
{
return (DCMD_USAGE);
/*
* An smb_requets_t address must be specified.
*/
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("SMB request information:\n\n");
else
mdb_printf("%<u>%-?s %4s %6s %4s %4s %4s %4s%</u>\n",
"Requests: ", "COM", "STATE",
"TID", "PID", "UID", "MID");
}
if (verbose) {
mdb_printf("First SMB COM :\t%I\n",
mdb_printf("State :\t%I\n",
mdb_printf("Tree ID :\t%u\n",
mdb_printf("Process ID :\t%u\n",
mdb_printf("User ID :\t%u\n",
mdb_printf("Multiplex ID :\t%u\n",
mdb_printf("\n");
} else {
mdb_printf("%?p %04x %6x %04x %04x %04x"
" %04x\n", addr,
}
} else {
return (DCMD_ERR);
}
return (DCMD_OK);
}
static int
{
char *lock_type;
return (DCMD_USAGE);
/*
* An smb_lock_t address must be specified.
*/
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("SMB lock information:\n\n");
else
mdb_printf("%<u>%-?s %4s %16s %8s %9s%</u>\n",
"Locks: ", "TYPE", "START", "LENGTH",
"CONFLICTS");
}
case SMB_LOCK_TYPE_READWRITE:
lock_type = "RW";
break;
case SMB_LOCK_TYPE_READONLY:
lock_type = "RO";
break;
default:
lock_type = "N/A";
break;
}
if (verbose) {
mdb_printf("Type :\t%s (%u)\n",
mdb_printf("Start :\t%llx\n",
mdb_printf("Length :\t%lx\n",
mdb_printf("Session :\t%p\n",
mdb_printf("File :\t%p\n",
mdb_printf("User ID :\t%u\n",
mdb_printf("Process ID :\t%u\n",
mdb_printf("Conflicts :\t%u\n",
(void) mdb_inc_indent(SMB_DCMD_INDENT);
mdb_warn("failed to walk conflict "
"locks ");
}
(void) mdb_dec_indent(SMB_DCMD_INDENT);
}
mdb_printf("Blocked by :\t%p\n",
mdb_printf("Flags :\t0x%x\n",
mdb_printf("\n");
} else {
}
} else {
return (DCMD_ERR);
}
return (DCMD_OK);
}
static void
smb_user_help(void)
{
"Display the contents of smb_user_t, with optional filtering.\n\n");
mdb_dec_indent(2);
mdb_printf("%<b>OPTIONS%</b>\n");
mdb_inc_indent(2);
"-v\tDisplay verbose smb_user information\n"
"-q\tDon't Display the contents of the smb_user. This option "
"should be\n\tused in conjunction with -d or -f\n"
"-d\tDisplay the list of smb_odirs attached\n"
"-f\tDisplay the list of smb_ofiles attached\n"
"-t\tDisplay the list of smb_trees attached\n");
}
static int
{
int print_odir = FALSE;
int print_ofile = FALSE;
int print_tree = FALSE;
int new_argc;
return (DCMD_USAGE);
/*
* An smb_user address must be specified on the command line.
*/
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (verbose)
mdb_printf("SMB user information:\n\n");
else
mdb_printf("%<u>%-?s %4s %6s %8s %16s %8s %s%</u>\n",
"Users:", "UID", "STATE", "FLAGS", "CRED",
"REFCNT", "ACCOUNT");
}
return (DCMD_ERR);
}
if (!quiet) {
char domain[SMB_PI_MAX_DOMAIN];
char account[SMB_PI_MAX_USERNAME];
int valid_domain = 0, valid_account = 0;
valid_domain = 1;
valid_account = 1;
if (verbose) {
mdb_printf("User ID :\t%04x\n",
mdb_printf("State :\t%d\n",
mdb_printf("Flags :\t%08x\n",
mdb_printf("Privileges :\t%08x\n",
mdb_printf("Credential :\t%llx\n",
mdb_printf("Reference Count :\t%d\n",
if (valid_domain && valid_account)
mdb_printf("User Account :\t%s\\%s\n",
mdb_printf("\n");
} else {
mdb_printf("%?p %04x %6d %08x %?p %8d %s\\%s\n",
}
}
new_argc = 0;
if (!print_tree) {
new_argc++;
}
if (print_ofile) {
new_argc++;
}
if (print_odir) {
new_argc++;
}
(void) mdb_inc_indent(SMB_DCMD_INDENT);
list_addr)) {
mdb_warn("failed to walk tree list\n");
(void) mdb_dec_indent(SMB_DCMD_INDENT);
return (DCMD_ERR);
}
(void) mdb_dec_indent(SMB_DCMD_INDENT);
}
return (DCMD_OK);
}
static void
smb_tree_help(void)
{
"Display the contents of smb_tree_t, with optional filtering.\n\n");
mdb_dec_indent(2);
mdb_printf("%<b>OPTIONS%</b>\n");
mdb_inc_indent(2);
"-v\tDisplay verbose smb_tree information\n"
"-q\tDon't Display the contents of the smb_tree. This option "
"should be\n\tused in conjunction with -d or -f\n"
"-d\tDisplay the list of smb_odirs attached\n"
"-f\tDisplay the list of smb_ofiles attached\n");
}
static int
{
int print_odir = FALSE;
int print_ofile = FALSE;
return (DCMD_USAGE);
/*
* If no smb_session address was specified on the command line, we can
* print out all smb sessions by invoking the smb_session walker, using
* this dcmd itself as the callback.
*/
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("SMB tree information:\n\n");
else
mdb_printf("%<u>%-?s %4s %6s %16s %10s%</u>\n",
"Trees:", "TID", "STATE", "SMB NODE",
"SHARE NAME");
}
/*
* Read tree and print some of the fields
*/
return (DCMD_ERR);
}
if (!quiet) {
if (verbose) {
mdb_printf("Tree ID :\t%04x\n",
mdb_printf("State :\t%d\n",
mdb_printf("Share name :\t%s\n",
mdb_printf("Resource :\t%s\n",
mdb_printf("Umask :\t%04x\n",
mdb_printf("Access :\t%04x\n",
mdb_printf("Flags :\t%08x\n",
mdb_printf("SMB Node :\t%llx\n",
mdb_printf("Reference Count :\t%d\n",
mdb_printf("\n");
} else {
}
}
if (print_odir) {
(void) mdb_inc_indent(SMB_DCMD_INDENT);
mdb_warn("failed to walk odir list\n");
(void) mdb_dec_indent(SMB_DCMD_INDENT);
return (DCMD_ERR);
}
(void) mdb_dec_indent(SMB_DCMD_INDENT);
}
if (print_ofile) {
(void) mdb_inc_indent(SMB_DCMD_INDENT);
mdb_warn("failed to walk ofile list\n");
(void) mdb_dec_indent(SMB_DCMD_INDENT);
return (DCMD_ERR);
}
(void) mdb_dec_indent(SMB_DCMD_INDENT);
}
return (DCMD_OK);
}
static int
{
return (DCMD_USAGE);
/*
* If no smb_session address was specified on the command line, we can
* print out all smb sessions by invoking the smb_session walker, using
* this dcmd itself as the callback.
*/
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("SMB odir information:\n\n");
else
mdb_printf("%<u>%-?s %8s %?s %10s%</u>\n",
"odir:", "STATE", "SMB NODE", "PATTERN");
}
/*
* For each smb_session, we just need to read the smb_session_t struct,
* read and then print out the following fields.
*/
if (verbose) {
mdb_printf("State :\t%d\n",
mdb_printf("Pattern :\t%s\n",
mdb_printf("SMB Node :\t%s\n",
mdb_printf("\n");
} else {
}
} else {
return (DCMD_ERR);
}
return (DCMD_OK);
}
static int
{
return (DCMD_USAGE);
/*
* If no smb_session address was specified on the command line, we can
* print out all smb sessions by invoking the smb_session walker, using
* this dcmd itself as the callback.
*/
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
/*
* If this is the first invocation of the command, print a nice
* header line for the output that will follow.
*/
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("SMB ofile information:\n\n");
else
mdb_printf("%<u>%-?s %04s %8s %?s %8s %?s%</u>\n",
"ofiles:", "FID", "STATE", "SMB NODE", "FLAGS",
"CRED");
}
/*
* For each smb_session, we just need to read the smb_session_t struct,
* read and then print out the following fields.
*/
if (verbose) {
mdb_printf("Ofile ID :\t%04x\n",
mdb_printf("State :\t%d\n",
mdb_printf("SMB Node :\t%llx\n",
mdb_printf("LLF Offset :\t%llx (%s)\n",
"Valid" : "Invalid"));
mdb_printf("FLAGS :\t%08x\n",
mdb_printf("Credential :\t%llx\n",
mdb_printf("\n");
} else {
}
} else {
return (DCMD_ERR);
}
return (DCMD_OK);
}
/*
* ::smb_dispatch_stats
*
* smb_dispatch_stats dcmd - Prints all dispatched SMB requests statistics.
*/
/*ARGSUSED*/
static int
{
int nstats = 0, i;
return (DCMD_USAGE);
mdb_warn("failed to find dispatch object");
return (DCMD_ERR);
}
mdb_warn("failed to read from dispatch object");
return (DCMD_ERR);
}
mdb_printf("All dispatched SMB requests statistics:\n\n");
for (i = 0; i < nstats; i++) {
if (disp[i].sdt_function)
mdb_printf(" %40s\t: %lld\n",
}
return (DCMD_OK);
}
/*
* MDB module linkage information:
*
* We declare a list of structures describing our dcmds, a list of structures
* describing our walkers and a function named _mdb_init to return a pointer
* to our module information.
*/
static const mdb_dcmd_t dcmds[] = {
{ "smb_info", "[-c]",
"print smb_info information", smb_information },
{ "smb_node", "?[-vps]",
{ "smb_session", "?[-vru]",
{ "smb_request", ":[-v]",
"print smb_request_t information", smb_request },
{ "smb_lock", ":[-v]",
"print smb_lock_t information", smb_lock },
{ "smb_user", ":[-vdftq]",
{ "smb_tree", ":[-vdfq]",
{ "smb_odir", ":[-v]",
"print smb_odir_t information", smb_odir },
{ "smb_ofile", "[-v]",
"print smb_odir_t information", smb_ofile },
{ "smb_stats", NULL,
"print all smb dispatched requests statistics",
smb_stats },
{ NULL }
};
static const mdb_walker_t walkers[] = {
{ "smb_session", "walk list of smb_session_t structures",
NULL },
{ "smb_node", "walk list of smb_node_t structures",
NULL },
{ NULL }
};
static const mdb_modinfo_t modinfo = {
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}