1/*
2 *   fs/cifs_debug.c
3 *
4 *   Copyright (C) International Business Machines  Corp., 2000,2005
5 *
6 *   Modified by Steve French (sfrench@us.ibm.com)
7 *
8 *   This program is free software;  you can redistribute it and/or modify
9 *   it under the terms of the GNU General Public License as published by
10 *   the Free Software Foundation; either version 2 of the License, or
11 *   (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
16 *   the GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program;  if not, write to the Free Software
20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <linux/fs.h>
23#include <linux/string.h>
24#include <linux/ctype.h>
25#include <linux/module.h>
26#include <linux/proc_fs.h>
27#include <asm/uaccess.h>
28#include "cifspdu.h"
29#include "cifsglob.h"
30#include "cifsproto.h"
31#include "cifs_debug.h"
32#include "cifsfs.h"
33
34void
35cifs_dump_mem(char *label, void *data, int length)
36{
37	int i, j;
38	int *intptr = data;
39	char *charptr = data;
40	char buf[10], line[80];
41
42	printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
43		label, length, data);
44	for (i = 0; i < length; i += 16) {
45		line[0] = 0;
46		for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
47			sprintf(buf, " %08x", intptr[i / 4 + j]);
48			strcat(line, buf);
49		}
50		buf[0] = ' ';
51		buf[2] = 0;
52		for (j = 0; (j < 16) && (i + j < length); j++) {
53			buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
54			strcat(line, buf);
55		}
56		printk(KERN_DEBUG "%s\n", line);
57	}
58}
59
60#ifdef CONFIG_CIFS_DEBUG2
61void cifs_dump_detail(struct smb_hdr * smb)
62{
63	cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
64		  smb->Command, smb->Status.CifsError,
65		  smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
66	cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
67}
68
69
70void cifs_dump_mids(struct TCP_Server_Info * server)
71{
72	struct list_head *tmp;
73	struct mid_q_entry * mid_entry;
74
75	if (server == NULL)
76		return;
77
78	cERROR(1, ("Dump pending requests:"));
79	spin_lock(&GlobalMid_Lock);
80	list_for_each(tmp, &server->pending_mid_q) {
81		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
82		if (mid_entry) {
83			cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
84				mid_entry->midState,
85				(int)mid_entry->command,
86				mid_entry->pid,
87				mid_entry->tsk,
88				mid_entry->mid));
89#ifdef CONFIG_CIFS_STATS2
90			cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
91				mid_entry->largeBuf,
92				mid_entry->resp_buf,
93				mid_entry->when_received,
94				jiffies));
95#endif /* STATS2 */
96			cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
97				  mid_entry->multiEnd));
98			if (mid_entry->resp_buf) {
99				cifs_dump_detail(mid_entry->resp_buf);
100				cifs_dump_mem("existing buf: ",
101					mid_entry->resp_buf,
102					62);
103			}
104		}
105	}
106	spin_unlock(&GlobalMid_Lock);
107}
108#endif /* CONFIG_CIFS_DEBUG2 */
109
110#ifdef CONFIG_PROC_FS
111static int
112cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
113		     int count, int *eof, void *data)
114{
115	struct list_head *tmp;
116	struct list_head *tmp1;
117	struct mid_q_entry * mid_entry;
118	struct cifsSesInfo *ses;
119	struct cifsTconInfo *tcon;
120	int i;
121	int length = 0;
122	char * original_buf = buf;
123
124	*beginBuffer = buf + offset;
125
126	length =
127	    sprintf(buf,
128		    "Display Internal CIFS Data Structures for Debugging\n"
129		    "---------------------------------------------------\n");
130	buf += length;
131	length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
132	buf += length;
133	length = sprintf(buf,
134		"Active VFS Requests: %d\n", GlobalTotalActiveXid);
135	buf += length;
136	length = sprintf(buf, "Servers:");
137	buf += length;
138
139	i = 0;
140	read_lock(&GlobalSMBSeslock);
141	list_for_each(tmp, &GlobalSMBSessionList) {
142		i++;
143		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
144		if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
145		   (ses->serverNOS == NULL)) {
146			buf += sprintf(buf, "\nentry for %s not fully "
147					"displayed\n\t", ses->serverName);
148
149		} else {
150			length =
151			    sprintf(buf,
152				    "\n%d) Name: %s  Domain: %s Mounts: %d OS:"
153				    " %s  \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
154				    " session status: %d\t",
155				i, ses->serverName, ses->serverDomain,
156				atomic_read(&ses->inUse),
157				ses->serverOS, ses->serverNOS,
158				ses->capabilities, ses->status);
159			buf += length;
160		}
161		if (ses->server) {
162			buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
163				    "Server: %d SecMode: 0x%x Req On Wire: %d",
164				ses->server->tcpStatus,
165				atomic_read(&ses->server->socketUseCount),
166				ses->server->secMode,
167				atomic_read(&ses->server->inFlight));
168
169#ifdef CONFIG_CIFS_STATS2
170			buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
171				atomic_read(&ses->server->inSend),
172				atomic_read(&ses->server->num_waiters));
173#endif
174
175			length = sprintf(buf, "\nMIDs:\n");
176			buf += length;
177
178			spin_lock(&GlobalMid_Lock);
179			list_for_each(tmp1, &ses->server->pending_mid_q) {
180				mid_entry = list_entry(tmp1, struct
181					mid_q_entry,
182					qhead);
183				if (mid_entry) {
184					length = sprintf(buf,
185							"State: %d com: %d pid:"
186							" %d tsk: %p mid %d\n",
187							mid_entry->midState,
188							(int)mid_entry->command,
189							mid_entry->pid,
190							mid_entry->tsk,
191							mid_entry->mid);
192					buf += length;
193				}
194			}
195			spin_unlock(&GlobalMid_Lock);
196		}
197
198	}
199	read_unlock(&GlobalSMBSeslock);
200	sprintf(buf, "\n");
201	buf++;
202
203	length = sprintf(buf, "Shares:");
204	buf += length;
205
206	i = 0;
207	read_lock(&GlobalSMBSeslock);
208	list_for_each(tmp, &GlobalTreeConnectionList) {
209		__u32 dev_type;
210		i++;
211		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
212		dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
213		length =
214		    sprintf(buf,
215			    "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
216			    "Attributes: 0x%x\nPathComponentMax: %d Status: %d",
217			    i, tcon->treeName,
218			    atomic_read(&tcon->useCount),
219			    tcon->nativeFileSystem,
220			    le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
221			    le32_to_cpu(tcon->fsAttrInfo.Attributes),
222			    le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
223			    tcon->tidStatus);
224		buf += length;
225		if (dev_type == FILE_DEVICE_DISK)
226			length = sprintf(buf, " type: DISK ");
227		else if (dev_type == FILE_DEVICE_CD_ROM)
228			length = sprintf(buf, " type: CDROM ");
229		else
230			length =
231			    sprintf(buf, " type: %d ", dev_type);
232		buf += length;
233		if (tcon->tidStatus == CifsNeedReconnect) {
234			buf += sprintf(buf, "\tDISCONNECTED ");
235			length += 14;
236		}
237	}
238	read_unlock(&GlobalSMBSeslock);
239
240	length = sprintf(buf, "\n");
241	buf += length;
242
243	/* BB add code to dump additional info such as TCP session info now */
244	/* Now calculate total size of returned data */
245	length = buf - original_buf;
246
247	if (offset + count >= length)
248		*eof = 1;
249	if (length < offset) {
250		*eof = 1;
251		return 0;
252	} else {
253		length = length - offset;
254	}
255	if (length > count)
256		length = count;
257
258	return length;
259}
260
261#ifdef CONFIG_CIFS_STATS
262
263static int
264cifs_stats_write(struct file *file, const char __user *buffer,
265		 unsigned long count, void *data)
266{
267	char c;
268	int rc;
269	struct list_head *tmp;
270	struct cifsTconInfo *tcon;
271
272	rc = get_user(c, buffer);
273	if (rc)
274		return rc;
275
276	if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
277		read_lock(&GlobalSMBSeslock);
278#ifdef CONFIG_CIFS_STATS2
279		atomic_set(&totBufAllocCount, 0);
280		atomic_set(&totSmBufAllocCount, 0);
281#endif /* CONFIG_CIFS_STATS2 */
282		list_for_each(tmp, &GlobalTreeConnectionList) {
283			tcon = list_entry(tmp, struct cifsTconInfo,
284					cifsConnectionList);
285			atomic_set(&tcon->num_smbs_sent, 0);
286			atomic_set(&tcon->num_writes, 0);
287			atomic_set(&tcon->num_reads, 0);
288			atomic_set(&tcon->num_oplock_brks, 0);
289			atomic_set(&tcon->num_opens, 0);
290			atomic_set(&tcon->num_closes, 0);
291			atomic_set(&tcon->num_deletes, 0);
292			atomic_set(&tcon->num_mkdirs, 0);
293			atomic_set(&tcon->num_rmdirs, 0);
294			atomic_set(&tcon->num_renames, 0);
295			atomic_set(&tcon->num_t2renames, 0);
296			atomic_set(&tcon->num_ffirst, 0);
297			atomic_set(&tcon->num_fnext, 0);
298			atomic_set(&tcon->num_fclose, 0);
299			atomic_set(&tcon->num_hardlinks, 0);
300			atomic_set(&tcon->num_symlinks, 0);
301			atomic_set(&tcon->num_locks, 0);
302		}
303		read_unlock(&GlobalSMBSeslock);
304	}
305
306	return count;
307}
308
309static int
310cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
311		  int count, int *eof, void *data)
312{
313	int item_length, i, length;
314	struct list_head *tmp;
315	struct cifsTconInfo *tcon;
316
317	*beginBuffer = buf + offset;
318
319	length = sprintf(buf,
320			"Resources in use\nCIFS Session: %d\n",
321			sesInfoAllocCount.counter);
322	buf += length;
323	item_length =
324		sprintf(buf, "Share (unique mount targets): %d\n",
325			tconInfoAllocCount.counter);
326	length += item_length;
327	buf += item_length;
328	item_length =
329		sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
330			bufAllocCount.counter,
331			cifs_min_rcv + tcpSesAllocCount.counter);
332	length += item_length;
333	buf += item_length;
334	item_length =
335		sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
336			smBufAllocCount.counter, cifs_min_small);
337	length += item_length;
338	buf += item_length;
339#ifdef CONFIG_CIFS_STATS2
340	item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
341				atomic_read(&totBufAllocCount),
342				atomic_read(&totSmBufAllocCount));
343	length += item_length;
344	buf += item_length;
345#endif /* CONFIG_CIFS_STATS2 */
346
347	item_length =
348		sprintf(buf, "Operations (MIDs): %d\n",
349			midCount.counter);
350	length += item_length;
351	buf += item_length;
352	item_length = sprintf(buf,
353		"\n%d session %d share reconnects\n",
354		tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
355	length += item_length;
356	buf += item_length;
357
358	item_length = sprintf(buf,
359		"Total vfs operations: %d maximum at one time: %d\n",
360		GlobalCurrentXid, GlobalMaxActiveXid);
361	length += item_length;
362	buf += item_length;
363
364	i = 0;
365	read_lock(&GlobalSMBSeslock);
366	list_for_each(tmp, &GlobalTreeConnectionList) {
367		i++;
368		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
369		item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
370		buf += item_length;
371		length += item_length;
372		if (tcon->tidStatus == CifsNeedReconnect) {
373			buf += sprintf(buf, "\tDISCONNECTED ");
374			length += 14;
375		}
376		item_length = sprintf(buf, "\nSMBs: %d Oplock Breaks: %d",
377			atomic_read(&tcon->num_smbs_sent),
378			atomic_read(&tcon->num_oplock_brks));
379		buf += item_length;
380		length += item_length;
381		item_length = sprintf(buf, "\nReads:  %d Bytes: %lld",
382			atomic_read(&tcon->num_reads),
383			(long long)(tcon->bytes_read));
384		buf += item_length;
385		length += item_length;
386		item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
387			atomic_read(&tcon->num_writes),
388			(long long)(tcon->bytes_written));
389		buf += item_length;
390		length += item_length;
391		item_length = sprintf(buf,
392			"\nLocks: %d HardLinks: %d Symlinks: %d",
393			atomic_read(&tcon->num_locks),
394			atomic_read(&tcon->num_hardlinks),
395			atomic_read(&tcon->num_symlinks));
396		buf += item_length;
397		length += item_length;
398
399		item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
400			atomic_read(&tcon->num_opens),
401			atomic_read(&tcon->num_closes),
402			atomic_read(&tcon->num_deletes));
403		buf += item_length;
404		length += item_length;
405		item_length = sprintf(buf, "\nMkdirs: %d Rmdirs: %d",
406			atomic_read(&tcon->num_mkdirs),
407			atomic_read(&tcon->num_rmdirs));
408		buf += item_length;
409		length += item_length;
410		item_length = sprintf(buf, "\nRenames: %d T2 Renames %d",
411			atomic_read(&tcon->num_renames),
412			atomic_read(&tcon->num_t2renames));
413		buf += item_length;
414		length += item_length;
415		item_length = sprintf(buf, "\nFindFirst: %d FNext %d FClose %d",
416			atomic_read(&tcon->num_ffirst),
417			atomic_read(&tcon->num_fnext),
418			atomic_read(&tcon->num_fclose));
419		buf += item_length;
420		length += item_length;
421	}
422	read_unlock(&GlobalSMBSeslock);
423
424	buf += sprintf(buf, "\n");
425	length++;
426
427	if (offset + count >= length)
428		*eof = 1;
429	if (length < offset) {
430		*eof = 1;
431		return 0;
432	} else {
433		length = length - offset;
434	}
435	if (length > count)
436		length = count;
437
438	return length;
439}
440#endif
441
442static struct proc_dir_entry *proc_fs_cifs;
443read_proc_t cifs_txanchor_read;
444static read_proc_t cifsFYI_read;
445static write_proc_t cifsFYI_write;
446static read_proc_t oplockEnabled_read;
447static write_proc_t oplockEnabled_write;
448static read_proc_t lookupFlag_read;
449static write_proc_t lookupFlag_write;
450static read_proc_t traceSMB_read;
451static write_proc_t traceSMB_write;
452static read_proc_t multiuser_mount_read;
453static write_proc_t multiuser_mount_write;
454static read_proc_t security_flags_read;
455static write_proc_t security_flags_write;
456/* static read_proc_t ntlmv2_enabled_read;
457static write_proc_t ntlmv2_enabled_write;
458static read_proc_t packet_signing_enabled_read;
459static write_proc_t packet_signing_enabled_write;*/
460static read_proc_t experimEnabled_read;
461static write_proc_t experimEnabled_write;
462static read_proc_t linuxExtensionsEnabled_read;
463static write_proc_t linuxExtensionsEnabled_write;
464
465void
466cifs_proc_init(void)
467{
468	struct proc_dir_entry *pde;
469
470	proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
471	if (proc_fs_cifs == NULL)
472		return;
473
474	proc_fs_cifs->owner = THIS_MODULE;
475	create_proc_read_entry("DebugData", 0, proc_fs_cifs,
476				cifs_debug_data_read, NULL);
477
478#ifdef CONFIG_CIFS_STATS
479	pde = create_proc_read_entry("Stats", 0, proc_fs_cifs,
480				cifs_stats_read, NULL);
481	if (pde)
482		pde->write_proc = cifs_stats_write;
483#endif
484	pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
485				cifsFYI_read, NULL);
486	if (pde)
487		pde->write_proc = cifsFYI_write;
488
489	pde =
490	    create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
491				traceSMB_read, NULL);
492	if (pde)
493		pde->write_proc = traceSMB_write;
494
495	pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
496				oplockEnabled_read, NULL);
497	if (pde)
498		pde->write_proc = oplockEnabled_write;
499
500	pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
501				experimEnabled_read, NULL);
502	if (pde)
503		pde->write_proc = experimEnabled_write;
504
505	pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
506				linuxExtensionsEnabled_read, NULL);
507	if (pde)
508		pde->write_proc = linuxExtensionsEnabled_write;
509
510	pde =
511	    create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
512				multiuser_mount_read, NULL);
513	if (pde)
514		pde->write_proc = multiuser_mount_write;
515
516	pde =
517	    create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
518				security_flags_read, NULL);
519	if (pde)
520		pde->write_proc = security_flags_write;
521
522	pde =
523	create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
524				lookupFlag_read, NULL);
525	if (pde)
526		pde->write_proc = lookupFlag_write;
527
528/*	pde =
529	    create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
530				ntlmv2_enabled_read, NULL);
531	if (pde)
532		pde->write_proc = ntlmv2_enabled_write;
533
534	pde =
535	    create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
536				packet_signing_enabled_read, NULL);
537	if (pde)
538		pde->write_proc = packet_signing_enabled_write;*/
539}
540
541void
542cifs_proc_clean(void)
543{
544	if (proc_fs_cifs == NULL)
545		return;
546
547	remove_proc_entry("DebugData", proc_fs_cifs);
548	remove_proc_entry("cifsFYI", proc_fs_cifs);
549	remove_proc_entry("traceSMB", proc_fs_cifs);
550#ifdef CONFIG_CIFS_STATS
551	remove_proc_entry("Stats", proc_fs_cifs);
552#endif
553	remove_proc_entry("MultiuserMount", proc_fs_cifs);
554	remove_proc_entry("OplockEnabled", proc_fs_cifs);
555/*	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
556	remove_proc_entry("SecurityFlags", proc_fs_cifs);
557/*	remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
558	remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
559	remove_proc_entry("Experimental", proc_fs_cifs);
560	remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
561	remove_proc_entry("cifs", proc_root_fs);
562}
563
564static int
565cifsFYI_read(char *page, char **start, off_t off, int count,
566	     int *eof, void *data)
567{
568	int len;
569
570	len = sprintf(page, "%d\n", cifsFYI);
571
572	len -= off;
573	*start = page + off;
574
575	if (len > count)
576		len = count;
577	else
578		*eof = 1;
579
580	if (len < 0)
581		len = 0;
582
583	return len;
584}
585static int
586cifsFYI_write(struct file *file, const char __user *buffer,
587	      unsigned long count, void *data)
588{
589	char c;
590	int rc;
591
592	rc = get_user(c, buffer);
593	if (rc)
594		return rc;
595	if (c == '0' || c == 'n' || c == 'N')
596		cifsFYI = 0;
597	else if (c == '1' || c == 'y' || c == 'Y')
598		cifsFYI = 1;
599	else if ((c > '1') && (c <= '9'))
600		cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
601
602	return count;
603}
604
605static int
606oplockEnabled_read(char *page, char **start, off_t off,
607		   int count, int *eof, void *data)
608{
609	int len;
610
611	len = sprintf(page, "%d\n", oplockEnabled);
612
613	len -= off;
614	*start = page + off;
615
616	if (len > count)
617		len = count;
618	else
619		*eof = 1;
620
621	if (len < 0)
622		len = 0;
623
624	return len;
625}
626static int
627oplockEnabled_write(struct file *file, const char __user *buffer,
628		    unsigned long count, void *data)
629{
630	char c;
631	int rc;
632
633	rc = get_user(c, buffer);
634	if (rc)
635		return rc;
636	if (c == '0' || c == 'n' || c == 'N')
637		oplockEnabled = 0;
638	else if (c == '1' || c == 'y' || c == 'Y')
639		oplockEnabled = 1;
640
641	return count;
642}
643
644static int
645experimEnabled_read(char *page, char **start, off_t off,
646		    int count, int *eof, void *data)
647{
648	int len;
649
650	len = sprintf(page, "%d\n", experimEnabled);
651
652	len -= off;
653	*start = page + off;
654
655	if (len > count)
656		len = count;
657	else
658		*eof = 1;
659
660	if (len < 0)
661		len = 0;
662
663	return len;
664}
665static int
666experimEnabled_write(struct file *file, const char __user *buffer,
667		     unsigned long count, void *data)
668{
669	char c;
670	int rc;
671
672	rc = get_user(c, buffer);
673	if (rc)
674		return rc;
675	if (c == '0' || c == 'n' || c == 'N')
676		experimEnabled = 0;
677	else if (c == '1' || c == 'y' || c == 'Y')
678		experimEnabled = 1;
679	else if (c == '2')
680		experimEnabled = 2;
681
682	return count;
683}
684
685static int
686linuxExtensionsEnabled_read(char *page, char **start, off_t off,
687			    int count, int *eof, void *data)
688{
689	int len;
690
691	len = sprintf(page, "%d\n", linuxExtEnabled);
692	len -= off;
693	*start = page + off;
694
695	if (len > count)
696		len = count;
697	else
698		*eof = 1;
699
700	if (len < 0)
701		len = 0;
702
703	return len;
704}
705static int
706linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
707			     unsigned long count, void *data)
708{
709	char c;
710	int rc;
711
712	rc = get_user(c, buffer);
713	if (rc)
714		return rc;
715	if (c == '0' || c == 'n' || c == 'N')
716		linuxExtEnabled = 0;
717	else if (c == '1' || c == 'y' || c == 'Y')
718		linuxExtEnabled = 1;
719
720	return count;
721}
722
723
724static int
725lookupFlag_read(char *page, char **start, off_t off,
726		int count, int *eof, void *data)
727{
728	int len;
729
730	len = sprintf(page, "%d\n", lookupCacheEnabled);
731
732	len -= off;
733	*start = page + off;
734
735	if (len > count)
736		len = count;
737	else
738		*eof = 1;
739
740	if (len < 0)
741		len = 0;
742
743	return len;
744}
745static int
746lookupFlag_write(struct file *file, const char __user *buffer,
747		    unsigned long count, void *data)
748{
749	char c;
750	int rc;
751
752	rc = get_user(c, buffer);
753	if (rc)
754		return rc;
755	if (c == '0' || c == 'n' || c == 'N')
756		lookupCacheEnabled = 0;
757	else if (c == '1' || c == 'y' || c == 'Y')
758		lookupCacheEnabled = 1;
759
760	return count;
761}
762static int
763traceSMB_read(char *page, char **start, off_t off, int count,
764	      int *eof, void *data)
765{
766	int len;
767
768	len = sprintf(page, "%d\n", traceSMB);
769
770	len -= off;
771	*start = page + off;
772
773	if (len > count)
774		len = count;
775	else
776		*eof = 1;
777
778	if (len < 0)
779		len = 0;
780
781	return len;
782}
783static int
784traceSMB_write(struct file *file, const char __user *buffer,
785	       unsigned long count, void *data)
786{
787	char c;
788	int rc;
789
790	rc = get_user(c, buffer);
791	if (rc)
792		return rc;
793	if (c == '0' || c == 'n' || c == 'N')
794		traceSMB = 0;
795	else if (c == '1' || c == 'y' || c == 'Y')
796		traceSMB = 1;
797
798	return count;
799}
800
801static int
802multiuser_mount_read(char *page, char **start, off_t off,
803		     int count, int *eof, void *data)
804{
805	int len;
806
807	len = sprintf(page, "%d\n", multiuser_mount);
808
809	len -= off;
810	*start = page + off;
811
812	if (len > count)
813		len = count;
814	else
815		*eof = 1;
816
817	if (len < 0)
818		len = 0;
819
820	return len;
821}
822static int
823multiuser_mount_write(struct file *file, const char __user *buffer,
824		      unsigned long count, void *data)
825{
826	char c;
827	int rc;
828
829	rc = get_user(c, buffer);
830	if (rc)
831		return rc;
832	if (c == '0' || c == 'n' || c == 'N')
833		multiuser_mount = 0;
834	else if (c == '1' || c == 'y' || c == 'Y')
835		multiuser_mount = 1;
836
837	return count;
838}
839
840static int
841security_flags_read(char *page, char **start, off_t off,
842		       int count, int *eof, void *data)
843{
844	int len;
845
846	len = sprintf(page, "0x%x\n", extended_security);
847
848	len -= off;
849	*start = page + off;
850
851	if (len > count)
852		len = count;
853	else
854		*eof = 1;
855
856	if (len < 0)
857		len = 0;
858
859	return len;
860}
861static int
862security_flags_write(struct file *file, const char __user *buffer,
863			unsigned long count, void *data)
864{
865	unsigned int flags;
866	char flags_string[12];
867	char c;
868
869	if ((count < 1) || (count > 11))
870		return -EINVAL;
871
872	memset(flags_string, 0, 12);
873
874	if (copy_from_user(flags_string, buffer, count))
875		return -EFAULT;
876
877	if (count < 3) {
878		/* single char or single char followed by null */
879		c = flags_string[0];
880		if (c == '0' || c == 'n' || c == 'N')
881			extended_security = CIFSSEC_DEF; /* default */
882		else if (c == '1' || c == 'y' || c == 'Y')
883			extended_security = CIFSSEC_MAX;
884		return count;
885	}
886	/* else we have a number */
887
888	flags = simple_strtoul(flags_string, NULL, 0);
889
890	cFYI(1, ("sec flags 0x%x", flags));
891
892	if (flags <= 0)  {
893		cERROR(1, ("invalid security flags %s", flags_string));
894		return -EINVAL;
895	}
896
897	if (flags & ~CIFSSEC_MASK) {
898		cERROR(1, ("attempt to set unsupported security flags 0x%x",
899			flags & ~CIFSSEC_MASK));
900		return -EINVAL;
901	}
902	/* flags look ok - update the global security flags for cifs module */
903	extended_security = flags;
904	return count;
905}
906
907/* static int
908ntlmv2_enabled_read(char *page, char **start, off_t off,
909		       int count, int *eof, void *data)
910{
911	int len;
912
913	len = sprintf(page, "%d\n", ntlmv2_support);
914
915	len -= off;
916	*start = page + off;
917
918	if (len > count)
919		len = count;
920	else
921		*eof = 1;
922
923	if (len < 0)
924		len = 0;
925
926	return len;
927}
928static int
929ntlmv2_enabled_write(struct file *file, const char __user *buffer,
930			unsigned long count, void *data)
931{
932	char c;
933	int rc;
934
935	rc = get_user(c, buffer);
936	if (rc)
937		return rc;
938	if (c == '0' || c == 'n' || c == 'N')
939		ntlmv2_support = 0;
940	else if (c == '1' || c == 'y' || c == 'Y')
941		ntlmv2_support = 1;
942	else if (c == '2')
943		ntlmv2_support = 2;
944
945	return count;
946}
947
948static int
949packet_signing_enabled_read(char *page, char **start, off_t off,
950		       int count, int *eof, void *data)
951{
952	int len;
953
954	len = sprintf(page, "%d\n", sign_CIFS_PDUs);
955
956	len -= off;
957	*start = page + off;
958
959	if (len > count)
960		len = count;
961	else
962		*eof = 1;
963
964	if (len < 0)
965		len = 0;
966
967	return len;
968}
969static int
970packet_signing_enabled_write(struct file *file, const char __user *buffer,
971			unsigned long count, void *data)
972{
973	char c;
974	int rc;
975
976	rc = get_user(c, buffer);
977	if (rc)
978		return rc;
979	if (c == '0' || c == 'n' || c == 'N')
980		sign_CIFS_PDUs = 0;
981	else if (c == '1' || c == 'y' || c == 'Y')
982		sign_CIFS_PDUs = 1;
983	else if (c == '2')
984		sign_CIFS_PDUs = 2;
985
986	return count;
987} */
988
989
990#endif
991