mirror of
https://github.com/torvalds/linux.git
synced 2024-10-31 01:01:52 +00:00
a013689ddb
Fixes two problems: 1) we dropped down to negotiating lanman if we did not recognize the mechanism (krb5 e.g.) 2) we did not stop cifsd (thus will fail when doing rmod cifs with slab free errors) when we fail tcon but have a bad session (which is the case in which signing is required but we don't allow signing on the client) It also turns on extended security flag in the header when passing "sec=krb5" on mount command (although kerberos support is not done of course) Acked-by: Jeff Layton <jlayton@redhat.com> CC: Shaggy <shaggy@us.ibm.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
922 lines
22 KiB
C
922 lines
22 KiB
C
/*
|
|
* fs/cifs_debug.c
|
|
*
|
|
* Copyright (C) International Business Machines Corp., 2000,2005
|
|
*
|
|
* Modified by Steve French (sfrench@us.ibm.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
|
* the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#include <linux/fs.h>
|
|
#include <linux/string.h>
|
|
#include <linux/ctype.h>
|
|
#include <linux/module.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <asm/uaccess.h>
|
|
#include "cifspdu.h"
|
|
#include "cifsglob.h"
|
|
#include "cifsproto.h"
|
|
#include "cifs_debug.h"
|
|
#include "cifsfs.h"
|
|
|
|
void
|
|
cifs_dump_mem(char *label, void *data, int length)
|
|
{
|
|
int i, j;
|
|
int *intptr = data;
|
|
char *charptr = data;
|
|
char buf[10], line[80];
|
|
|
|
printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
|
|
label, length, data);
|
|
for (i = 0; i < length; i += 16) {
|
|
line[0] = 0;
|
|
for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
|
|
sprintf(buf, " %08x", intptr[i / 4 + j]);
|
|
strcat(line, buf);
|
|
}
|
|
buf[0] = ' ';
|
|
buf[2] = 0;
|
|
for (j = 0; (j < 16) && (i + j < length); j++) {
|
|
buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
|
|
strcat(line, buf);
|
|
}
|
|
printk(KERN_DEBUG "%s\n", line);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_CIFS_DEBUG2
|
|
void cifs_dump_detail(struct smb_hdr *smb)
|
|
{
|
|
cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
|
|
smb->Command, smb->Status.CifsError,
|
|
smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
|
|
cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
|
|
}
|
|
|
|
|
|
void cifs_dump_mids(struct TCP_Server_Info *server)
|
|
{
|
|
struct list_head *tmp;
|
|
struct mid_q_entry *mid_entry;
|
|
|
|
if (server == NULL)
|
|
return;
|
|
|
|
cERROR(1, ("Dump pending requests:"));
|
|
spin_lock(&GlobalMid_Lock);
|
|
list_for_each(tmp, &server->pending_mid_q) {
|
|
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
|
|
if (mid_entry) {
|
|
cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
|
|
mid_entry->midState,
|
|
(int)mid_entry->command,
|
|
mid_entry->pid,
|
|
mid_entry->tsk,
|
|
mid_entry->mid));
|
|
#ifdef CONFIG_CIFS_STATS2
|
|
cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
|
|
mid_entry->largeBuf,
|
|
mid_entry->resp_buf,
|
|
mid_entry->when_received,
|
|
jiffies));
|
|
#endif /* STATS2 */
|
|
cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
|
|
mid_entry->multiEnd));
|
|
if (mid_entry->resp_buf) {
|
|
cifs_dump_detail(mid_entry->resp_buf);
|
|
cifs_dump_mem("existing buf: ",
|
|
mid_entry->resp_buf,
|
|
62 /* fixme */);
|
|
}
|
|
}
|
|
}
|
|
spin_unlock(&GlobalMid_Lock);
|
|
}
|
|
#endif /* CONFIG_CIFS_DEBUG2 */
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
static int
|
|
cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
|
int count, int *eof, void *data)
|
|
{
|
|
struct list_head *tmp;
|
|
struct list_head *tmp1;
|
|
struct mid_q_entry *mid_entry;
|
|
struct cifsSesInfo *ses;
|
|
struct cifsTconInfo *tcon;
|
|
int i;
|
|
int length = 0;
|
|
char *original_buf = buf;
|
|
|
|
*beginBuffer = buf + offset;
|
|
|
|
length =
|
|
sprintf(buf,
|
|
"Display Internal CIFS Data Structures for Debugging\n"
|
|
"---------------------------------------------------\n");
|
|
buf += length;
|
|
length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
|
|
buf += length;
|
|
length = sprintf(buf,
|
|
"Active VFS Requests: %d\n", GlobalTotalActiveXid);
|
|
buf += length;
|
|
length = sprintf(buf, "Servers:");
|
|
buf += length;
|
|
|
|
i = 0;
|
|
read_lock(&GlobalSMBSeslock);
|
|
list_for_each(tmp, &GlobalSMBSessionList) {
|
|
i++;
|
|
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
|
|
if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
|
|
(ses->serverNOS == NULL)) {
|
|
buf += sprintf(buf, "\nentry for %s not fully "
|
|
"displayed\n\t", ses->serverName);
|
|
} else {
|
|
length =
|
|
sprintf(buf,
|
|
"\n%d) Name: %s Domain: %s Mounts: %d OS:"
|
|
" %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
|
|
" session status: %d\t",
|
|
i, ses->serverName, ses->serverDomain,
|
|
atomic_read(&ses->inUse),
|
|
ses->serverOS, ses->serverNOS,
|
|
ses->capabilities, ses->status);
|
|
buf += length;
|
|
}
|
|
if (ses->server) {
|
|
buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
|
|
"Server: %d SecMode: 0x%x Req On Wire: %d",
|
|
ses->server->tcpStatus,
|
|
atomic_read(&ses->server->socketUseCount),
|
|
ses->server->secMode,
|
|
atomic_read(&ses->server->inFlight));
|
|
|
|
#ifdef CONFIG_CIFS_STATS2
|
|
buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
|
|
atomic_read(&ses->server->inSend),
|
|
atomic_read(&ses->server->num_waiters));
|
|
#endif
|
|
|
|
length = sprintf(buf, "\nMIDs:\n");
|
|
buf += length;
|
|
|
|
spin_lock(&GlobalMid_Lock);
|
|
list_for_each(tmp1, &ses->server->pending_mid_q) {
|
|
mid_entry = list_entry(tmp1, struct
|
|
mid_q_entry,
|
|
qhead);
|
|
if (mid_entry) {
|
|
length = sprintf(buf,
|
|
"State: %d com: %d pid:"
|
|
" %d tsk: %p mid %d\n",
|
|
mid_entry->midState,
|
|
(int)mid_entry->command,
|
|
mid_entry->pid,
|
|
mid_entry->tsk,
|
|
mid_entry->mid);
|
|
buf += length;
|
|
}
|
|
}
|
|
spin_unlock(&GlobalMid_Lock);
|
|
}
|
|
|
|
}
|
|
read_unlock(&GlobalSMBSeslock);
|
|
sprintf(buf, "\n");
|
|
buf++;
|
|
|
|
length = sprintf(buf, "Shares:");
|
|
buf += length;
|
|
|
|
i = 0;
|
|
read_lock(&GlobalSMBSeslock);
|
|
list_for_each(tmp, &GlobalTreeConnectionList) {
|
|
__u32 dev_type;
|
|
i++;
|
|
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
|
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
|
length = sprintf(buf, "\n%d) %s Uses: %d ", i,
|
|
tcon->treeName, atomic_read(&tcon->useCount));
|
|
buf += length;
|
|
if (tcon->nativeFileSystem) {
|
|
length = sprintf(buf, "Type: %s ",
|
|
tcon->nativeFileSystem);
|
|
buf += length;
|
|
}
|
|
length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x"
|
|
"\nPathComponentMax: %d Status: %d",
|
|
le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
|
|
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
|
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
|
tcon->tidStatus);
|
|
buf += length;
|
|
if (dev_type == FILE_DEVICE_DISK)
|
|
length = sprintf(buf, " type: DISK ");
|
|
else if (dev_type == FILE_DEVICE_CD_ROM)
|
|
length = sprintf(buf, " type: CDROM ");
|
|
else
|
|
length =
|
|
sprintf(buf, " type: %d ", dev_type);
|
|
buf += length;
|
|
if (tcon->tidStatus == CifsNeedReconnect) {
|
|
buf += sprintf(buf, "\tDISCONNECTED ");
|
|
length += 14;
|
|
}
|
|
}
|
|
read_unlock(&GlobalSMBSeslock);
|
|
|
|
length = sprintf(buf, "\n");
|
|
buf += length;
|
|
|
|
/* BB add code to dump additional info such as TCP session info now */
|
|
/* Now calculate total size of returned data */
|
|
length = buf - original_buf;
|
|
|
|
if (offset + count >= length)
|
|
*eof = 1;
|
|
if (length < offset) {
|
|
*eof = 1;
|
|
return 0;
|
|
} else {
|
|
length = length - offset;
|
|
}
|
|
if (length > count)
|
|
length = count;
|
|
|
|
return length;
|
|
}
|
|
|
|
#ifdef CONFIG_CIFS_STATS
|
|
|
|
static int
|
|
cifs_stats_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
struct list_head *tmp;
|
|
struct cifsTconInfo *tcon;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
|
|
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
|
|
read_lock(&GlobalSMBSeslock);
|
|
#ifdef CONFIG_CIFS_STATS2
|
|
atomic_set(&totBufAllocCount, 0);
|
|
atomic_set(&totSmBufAllocCount, 0);
|
|
#endif /* CONFIG_CIFS_STATS2 */
|
|
list_for_each(tmp, &GlobalTreeConnectionList) {
|
|
tcon = list_entry(tmp, struct cifsTconInfo,
|
|
cifsConnectionList);
|
|
atomic_set(&tcon->num_smbs_sent, 0);
|
|
atomic_set(&tcon->num_writes, 0);
|
|
atomic_set(&tcon->num_reads, 0);
|
|
atomic_set(&tcon->num_oplock_brks, 0);
|
|
atomic_set(&tcon->num_opens, 0);
|
|
atomic_set(&tcon->num_closes, 0);
|
|
atomic_set(&tcon->num_deletes, 0);
|
|
atomic_set(&tcon->num_mkdirs, 0);
|
|
atomic_set(&tcon->num_rmdirs, 0);
|
|
atomic_set(&tcon->num_renames, 0);
|
|
atomic_set(&tcon->num_t2renames, 0);
|
|
atomic_set(&tcon->num_ffirst, 0);
|
|
atomic_set(&tcon->num_fnext, 0);
|
|
atomic_set(&tcon->num_fclose, 0);
|
|
atomic_set(&tcon->num_hardlinks, 0);
|
|
atomic_set(&tcon->num_symlinks, 0);
|
|
atomic_set(&tcon->num_locks, 0);
|
|
}
|
|
read_unlock(&GlobalSMBSeslock);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static int
|
|
cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
|
int count, int *eof, void *data)
|
|
{
|
|
int item_length, i, length;
|
|
struct list_head *tmp;
|
|
struct cifsTconInfo *tcon;
|
|
|
|
*beginBuffer = buf + offset;
|
|
|
|
length = sprintf(buf,
|
|
"Resources in use\nCIFS Session: %d\n",
|
|
sesInfoAllocCount.counter);
|
|
buf += length;
|
|
item_length =
|
|
sprintf(buf, "Share (unique mount targets): %d\n",
|
|
tconInfoAllocCount.counter);
|
|
length += item_length;
|
|
buf += item_length;
|
|
item_length =
|
|
sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
|
|
bufAllocCount.counter,
|
|
cifs_min_rcv + tcpSesAllocCount.counter);
|
|
length += item_length;
|
|
buf += item_length;
|
|
item_length =
|
|
sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
|
|
smBufAllocCount.counter, cifs_min_small);
|
|
length += item_length;
|
|
buf += item_length;
|
|
#ifdef CONFIG_CIFS_STATS2
|
|
item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
|
|
atomic_read(&totBufAllocCount),
|
|
atomic_read(&totSmBufAllocCount));
|
|
length += item_length;
|
|
buf += item_length;
|
|
#endif /* CONFIG_CIFS_STATS2 */
|
|
|
|
item_length =
|
|
sprintf(buf, "Operations (MIDs): %d\n",
|
|
midCount.counter);
|
|
length += item_length;
|
|
buf += item_length;
|
|
item_length = sprintf(buf,
|
|
"\n%d session %d share reconnects\n",
|
|
tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
|
|
length += item_length;
|
|
buf += item_length;
|
|
|
|
item_length = sprintf(buf,
|
|
"Total vfs operations: %d maximum at one time: %d\n",
|
|
GlobalCurrentXid, GlobalMaxActiveXid);
|
|
length += item_length;
|
|
buf += item_length;
|
|
|
|
i = 0;
|
|
read_lock(&GlobalSMBSeslock);
|
|
list_for_each(tmp, &GlobalTreeConnectionList) {
|
|
i++;
|
|
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
|
item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
|
|
buf += item_length;
|
|
length += item_length;
|
|
if (tcon->tidStatus == CifsNeedReconnect) {
|
|
buf += sprintf(buf, "\tDISCONNECTED ");
|
|
length += 14;
|
|
}
|
|
item_length = sprintf(buf, "\nSMBs: %d Oplock Breaks: %d",
|
|
atomic_read(&tcon->num_smbs_sent),
|
|
atomic_read(&tcon->num_oplock_brks));
|
|
buf += item_length;
|
|
length += item_length;
|
|
item_length = sprintf(buf, "\nReads: %d Bytes: %lld",
|
|
atomic_read(&tcon->num_reads),
|
|
(long long)(tcon->bytes_read));
|
|
buf += item_length;
|
|
length += item_length;
|
|
item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
|
|
atomic_read(&tcon->num_writes),
|
|
(long long)(tcon->bytes_written));
|
|
buf += item_length;
|
|
length += item_length;
|
|
item_length = sprintf(buf,
|
|
"\nLocks: %d HardLinks: %d Symlinks: %d",
|
|
atomic_read(&tcon->num_locks),
|
|
atomic_read(&tcon->num_hardlinks),
|
|
atomic_read(&tcon->num_symlinks));
|
|
buf += item_length;
|
|
length += item_length;
|
|
|
|
item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
|
|
atomic_read(&tcon->num_opens),
|
|
atomic_read(&tcon->num_closes),
|
|
atomic_read(&tcon->num_deletes));
|
|
buf += item_length;
|
|
length += item_length;
|
|
item_length = sprintf(buf, "\nMkdirs: %d Rmdirs: %d",
|
|
atomic_read(&tcon->num_mkdirs),
|
|
atomic_read(&tcon->num_rmdirs));
|
|
buf += item_length;
|
|
length += item_length;
|
|
item_length = sprintf(buf, "\nRenames: %d T2 Renames %d",
|
|
atomic_read(&tcon->num_renames),
|
|
atomic_read(&tcon->num_t2renames));
|
|
buf += item_length;
|
|
length += item_length;
|
|
item_length = sprintf(buf, "\nFindFirst: %d FNext %d FClose %d",
|
|
atomic_read(&tcon->num_ffirst),
|
|
atomic_read(&tcon->num_fnext),
|
|
atomic_read(&tcon->num_fclose));
|
|
buf += item_length;
|
|
length += item_length;
|
|
}
|
|
read_unlock(&GlobalSMBSeslock);
|
|
|
|
buf += sprintf(buf, "\n");
|
|
length++;
|
|
|
|
if (offset + count >= length)
|
|
*eof = 1;
|
|
if (length < offset) {
|
|
*eof = 1;
|
|
return 0;
|
|
} else {
|
|
length = length - offset;
|
|
}
|
|
if (length > count)
|
|
length = count;
|
|
|
|
return length;
|
|
}
|
|
#endif
|
|
|
|
static struct proc_dir_entry *proc_fs_cifs;
|
|
read_proc_t cifs_txanchor_read;
|
|
static read_proc_t cifsFYI_read;
|
|
static write_proc_t cifsFYI_write;
|
|
static read_proc_t oplockEnabled_read;
|
|
static write_proc_t oplockEnabled_write;
|
|
static read_proc_t lookupFlag_read;
|
|
static write_proc_t lookupFlag_write;
|
|
static read_proc_t traceSMB_read;
|
|
static write_proc_t traceSMB_write;
|
|
static read_proc_t multiuser_mount_read;
|
|
static write_proc_t multiuser_mount_write;
|
|
static read_proc_t security_flags_read;
|
|
static write_proc_t security_flags_write;
|
|
/* static read_proc_t ntlmv2_enabled_read;
|
|
static write_proc_t ntlmv2_enabled_write;
|
|
static read_proc_t packet_signing_enabled_read;
|
|
static write_proc_t packet_signing_enabled_write;*/
|
|
static read_proc_t experimEnabled_read;
|
|
static write_proc_t experimEnabled_write;
|
|
static read_proc_t linuxExtensionsEnabled_read;
|
|
static write_proc_t linuxExtensionsEnabled_write;
|
|
|
|
void
|
|
cifs_proc_init(void)
|
|
{
|
|
struct proc_dir_entry *pde;
|
|
|
|
proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
|
|
if (proc_fs_cifs == NULL)
|
|
return;
|
|
|
|
proc_fs_cifs->owner = THIS_MODULE;
|
|
create_proc_read_entry("DebugData", 0, proc_fs_cifs,
|
|
cifs_debug_data_read, NULL);
|
|
|
|
#ifdef CONFIG_CIFS_STATS
|
|
pde = create_proc_read_entry("Stats", 0, proc_fs_cifs,
|
|
cifs_stats_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = cifs_stats_write;
|
|
#endif
|
|
pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
|
|
cifsFYI_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = cifsFYI_write;
|
|
|
|
pde =
|
|
create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
|
|
traceSMB_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = traceSMB_write;
|
|
|
|
pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
|
|
oplockEnabled_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = oplockEnabled_write;
|
|
|
|
pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
|
|
experimEnabled_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = experimEnabled_write;
|
|
|
|
pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
|
|
linuxExtensionsEnabled_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = linuxExtensionsEnabled_write;
|
|
|
|
pde =
|
|
create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
|
|
multiuser_mount_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = multiuser_mount_write;
|
|
|
|
pde =
|
|
create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
|
|
security_flags_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = security_flags_write;
|
|
|
|
pde =
|
|
create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
|
|
lookupFlag_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = lookupFlag_write;
|
|
|
|
/* pde =
|
|
create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
|
|
ntlmv2_enabled_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = ntlmv2_enabled_write;
|
|
|
|
pde =
|
|
create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
|
|
packet_signing_enabled_read, NULL);
|
|
if (pde)
|
|
pde->write_proc = packet_signing_enabled_write;*/
|
|
}
|
|
|
|
void
|
|
cifs_proc_clean(void)
|
|
{
|
|
if (proc_fs_cifs == NULL)
|
|
return;
|
|
|
|
remove_proc_entry("DebugData", proc_fs_cifs);
|
|
remove_proc_entry("cifsFYI", proc_fs_cifs);
|
|
remove_proc_entry("traceSMB", proc_fs_cifs);
|
|
#ifdef CONFIG_CIFS_STATS
|
|
remove_proc_entry("Stats", proc_fs_cifs);
|
|
#endif
|
|
remove_proc_entry("MultiuserMount", proc_fs_cifs);
|
|
remove_proc_entry("OplockEnabled", proc_fs_cifs);
|
|
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
|
|
remove_proc_entry("SecurityFlags", proc_fs_cifs);
|
|
/* remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
|
|
remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
|
|
remove_proc_entry("Experimental", proc_fs_cifs);
|
|
remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
|
|
remove_proc_entry("cifs", proc_root_fs);
|
|
}
|
|
|
|
static int
|
|
cifsFYI_read(char *page, char **start, off_t off, int count,
|
|
int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "%d\n", cifsFYI);
|
|
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
cifsFYI_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
if (c == '0' || c == 'n' || c == 'N')
|
|
cifsFYI = 0;
|
|
else if (c == '1' || c == 'y' || c == 'Y')
|
|
cifsFYI = 1;
|
|
else if ((c > '1') && (c <= '9'))
|
|
cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
|
|
|
|
return count;
|
|
}
|
|
|
|
static int
|
|
oplockEnabled_read(char *page, char **start, off_t off,
|
|
int count, int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "%d\n", oplockEnabled);
|
|
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
oplockEnabled_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
if (c == '0' || c == 'n' || c == 'N')
|
|
oplockEnabled = 0;
|
|
else if (c == '1' || c == 'y' || c == 'Y')
|
|
oplockEnabled = 1;
|
|
|
|
return count;
|
|
}
|
|
|
|
static int
|
|
experimEnabled_read(char *page, char **start, off_t off,
|
|
int count, int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "%d\n", experimEnabled);
|
|
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
experimEnabled_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
if (c == '0' || c == 'n' || c == 'N')
|
|
experimEnabled = 0;
|
|
else if (c == '1' || c == 'y' || c == 'Y')
|
|
experimEnabled = 1;
|
|
else if (c == '2')
|
|
experimEnabled = 2;
|
|
|
|
return count;
|
|
}
|
|
|
|
static int
|
|
linuxExtensionsEnabled_read(char *page, char **start, off_t off,
|
|
int count, int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "%d\n", linuxExtEnabled);
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
if (c == '0' || c == 'n' || c == 'N')
|
|
linuxExtEnabled = 0;
|
|
else if (c == '1' || c == 'y' || c == 'Y')
|
|
linuxExtEnabled = 1;
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
static int
|
|
lookupFlag_read(char *page, char **start, off_t off,
|
|
int count, int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "%d\n", lookupCacheEnabled);
|
|
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
lookupFlag_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
if (c == '0' || c == 'n' || c == 'N')
|
|
lookupCacheEnabled = 0;
|
|
else if (c == '1' || c == 'y' || c == 'Y')
|
|
lookupCacheEnabled = 1;
|
|
|
|
return count;
|
|
}
|
|
static int
|
|
traceSMB_read(char *page, char **start, off_t off, int count,
|
|
int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "%d\n", traceSMB);
|
|
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
traceSMB_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
if (c == '0' || c == 'n' || c == 'N')
|
|
traceSMB = 0;
|
|
else if (c == '1' || c == 'y' || c == 'Y')
|
|
traceSMB = 1;
|
|
|
|
return count;
|
|
}
|
|
|
|
static int
|
|
multiuser_mount_read(char *page, char **start, off_t off,
|
|
int count, int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "%d\n", multiuser_mount);
|
|
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
multiuser_mount_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
char c;
|
|
int rc;
|
|
|
|
rc = get_user(c, buffer);
|
|
if (rc)
|
|
return rc;
|
|
if (c == '0' || c == 'n' || c == 'N')
|
|
multiuser_mount = 0;
|
|
else if (c == '1' || c == 'y' || c == 'Y')
|
|
multiuser_mount = 1;
|
|
|
|
return count;
|
|
}
|
|
|
|
static int
|
|
security_flags_read(char *page, char **start, off_t off,
|
|
int count, int *eof, void *data)
|
|
{
|
|
int len;
|
|
|
|
len = sprintf(page, "0x%x\n", extended_security);
|
|
|
|
len -= off;
|
|
*start = page + off;
|
|
|
|
if (len > count)
|
|
len = count;
|
|
else
|
|
*eof = 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
return len;
|
|
}
|
|
static int
|
|
security_flags_write(struct file *file, const char __user *buffer,
|
|
unsigned long count, void *data)
|
|
{
|
|
unsigned int flags;
|
|
char flags_string[12];
|
|
char c;
|
|
|
|
if ((count < 1) || (count > 11))
|
|
return -EINVAL;
|
|
|
|
memset(flags_string, 0, 12);
|
|
|
|
if (copy_from_user(flags_string, buffer, count))
|
|
return -EFAULT;
|
|
|
|
if (count < 3) {
|
|
/* single char or single char followed by null */
|
|
c = flags_string[0];
|
|
if (c == '0' || c == 'n' || c == 'N') {
|
|
extended_security = CIFSSEC_DEF; /* default */
|
|
return count;
|
|
} else if (c == '1' || c == 'y' || c == 'Y') {
|
|
extended_security = CIFSSEC_MAX;
|
|
return count;
|
|
} else if (!isdigit(c)) {
|
|
cERROR(1, ("invalid flag %c", c));
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
/* else we have a number */
|
|
|
|
flags = simple_strtoul(flags_string, NULL, 0);
|
|
|
|
cFYI(1, ("sec flags 0x%x", flags));
|
|
|
|
if (flags <= 0) {
|
|
cERROR(1, ("invalid security flags %s", flags_string));
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (flags & ~CIFSSEC_MASK) {
|
|
cERROR(1, ("attempt to set unsupported security flags 0x%x",
|
|
flags & ~CIFSSEC_MASK));
|
|
return -EINVAL;
|
|
}
|
|
/* flags look ok - update the global security flags for cifs module */
|
|
extended_security = flags;
|
|
if (extended_security & CIFSSEC_MUST_SIGN) {
|
|
/* requiring signing implies signing is allowed */
|
|
extended_security |= CIFSSEC_MAY_SIGN;
|
|
cFYI(1, ("packet signing now required"));
|
|
} else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) {
|
|
cFYI(1, ("packet signing disabled"));
|
|
}
|
|
/* BB should we turn on MAY flags for other MUST options? */
|
|
return count;
|
|
}
|
|
#endif
|