aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/cifs
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/AUTHORS42
-rw-r--r--fs/cifs/CHANGES671
-rw-r--r--fs/cifs/Makefile6
-rw-r--r--fs/cifs/README475
-rw-r--r--fs/cifs/TODO104
-rw-r--r--fs/cifs/asn1.c618
-rw-r--r--fs/cifs/cifs_debug.c805
-rw-r--r--fs/cifs/cifs_debug.h66
-rw-r--r--fs/cifs/cifs_fs_sb.h39
-rw-r--r--fs/cifs/cifs_unicode.c87
-rw-r--r--fs/cifs/cifs_unicode.h353
-rw-r--r--fs/cifs/cifs_uniupr.h253
-rw-r--r--fs/cifs/cifsencrypt.c209
-rw-r--r--fs/cifs/cifsencrypt.h34
-rw-r--r--fs/cifs/cifsfs.c913
-rw-r--r--fs/cifs/cifsfs.h98
-rw-r--r--fs/cifs/cifsglob.h439
-rw-r--r--fs/cifs/cifspdu.h1987
-rw-r--r--fs/cifs/cifsproto.h269
-rw-r--r--fs/cifs/cifssmb.c4186
-rw-r--r--fs/cifs/connect.c3064
-rw-r--r--fs/cifs/dir.c523
-rw-r--r--fs/cifs/fcntl.c117
-rw-r--r--fs/cifs/file.c1675
-rw-r--r--fs/cifs/inode.c1096
-rw-r--r--fs/cifs/ioctl.c49
-rw-r--r--fs/cifs/link.c328
-rw-r--r--fs/cifs/md4.c205
-rw-r--r--fs/cifs/md5.c363
-rw-r--r--fs/cifs/md5.h38
-rw-r--r--fs/cifs/misc.c516
-rw-r--r--fs/cifs/netmisc.c904
-rw-r--r--fs/cifs/nterr.c687
-rw-r--r--fs/cifs/nterr.h556
-rw-r--r--fs/cifs/ntlmssp.h101
-rw-r--r--fs/cifs/readdir.c867
-rw-r--r--fs/cifs/rfc1002pdu.h79
-rw-r--r--fs/cifs/smbdes.c412
-rw-r--r--fs/cifs/smbencrypt.c285
-rw-r--r--fs/cifs/smberr.h115
-rw-r--r--fs/cifs/transport.c619
-rw-r--r--fs/cifs/xattr.c334
42 files changed, 24587 insertions, 0 deletions
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
new file mode 100644
index 000000000000..acce36e25d2e
--- /dev/null
+++ b/fs/cifs/AUTHORS
@@ -0,0 +1,42 @@
1Original Author
2===============
3Steve French (sfrench@samba.org)
4
5The author wishes to express his appreciation and thanks to:
6Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
7improvements. Thanks to IBM for allowing me the time and test resources to pursue
8this project. Jim McDonough from IBM (and the Samba Team) for his help.
9The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
10Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
11for proving years ago that a very good smb/cifs client could be done on a Unix like
12operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
13and others for their work on the Linux smbfs module over the years. Thanks to
14the other members of the Storage Network Industry Association CIFS Technical
15Workgroup for their work specifying this highly complex protocol and finally
16thanks to the Samba team for their technical advice and encouragement.
17
18Patch Contributors
19------------------
20Zwane Mwaikambo
21Andi Kleen
22Amrut Joshi
23Shobhit Dayal
24Sergey Vlasov
25Richard Hughes
26Yury Umanets
27Mark Hamzy
28Domen Puncer
29Jesper Juhl
30
31Test case and Bug Report contributors
32-------------------------------------
33Thanks to those in the community who have submitted detailed bug reports
34and debug of problems they have found: Jochen Dolze, David Blaine,
35Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
36Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
37Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
38mention to the Stanford Checker (SWAT) which pointed out many minor
39bugs in error paths.
40
41And thanks to the IBM LTC and Power test teams and SuSE testers for
42finding multiple bugs during excellent stress test runs.
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
new file mode 100644
index 000000000000..5316c8dd6bff
--- /dev/null
+++ b/fs/cifs/CHANGES
@@ -0,0 +1,671 @@
1Version 1.31
2------------
3Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
4transact response for an SMB request and search entry split across two frames.
5Fix updates of DOS attributes and time fields so that files on NT4 servers
6do not get marked delete on close. Display sizes of cifs buffer pools in
7cifs stats. Fix oops in unmount when cifsd thread being killed by
8shutdown. Add generic readv/writev and aio support. Report inode numbers
9consistently in readdir and lookup (when serverino mount option is
10specified use the inode number that the server reports - for both lookup
11and readdir, otherwise by default the locally generated inode number is used
12for inodes created in either path since servers are not always able to
13provide unique inode numbers when exporting multiple volumes from under one
14sharename).
15
16Version 1.30
17------------
18Allow new nouser_xattr mount parm to disable xattr support for user namespace.
19Do not flag user_xattr mount parm in dmesg. Retry failures setting file time
20(mostly affects NT4 servers) by retry with handle based network operation.
21Add new POSIX Query FS Info for returning statfs info more accurately.
22Handle passwords with multiple commas in them.
23
24Version 1.29
25------------
26Fix default mode in sysfs of cifs module parms. Remove old readdir routine.
27Fix capabilities flags for large readx so as to allow reads larger than 64K.
28
29Version 1.28
30------------
31Add module init parm for large SMB buffer size (to allow it to be changed
32from its default of 16K) which is especially useful for large file copy
33when mounting with the directio mount option. Fix oops after
34returning from mount when experimental ExtendedSecurity enabled and
35SpnegoNegotiated returning invalid error. Fix case to retry better when
36peek returns from 1 to 3 bytes on socket which should have more data.
37Fixed path based calls (such as cifs lookup) to handle path names
38longer than 530 (now can handle PATH_MAX). Fix pass through authentication
39from Samba server to DC (Samba required dummy LM password).
40
41Version 1.27
42------------
43Turn off DNOTIFY (directory change notification support) by default
44(unless built with the experimental flag) to fix hang with KDE
45file browser. Fix DNOTIFY flag mappings. Fix hang (in wait_event
46waiting on an SMB response) in SendReceive when session dies but
47reconnects quickly from another task. Add module init parms for
48minimum number of large and small network buffers in the buffer pools,
49and for the maximum number of simultaneous requests.
50
51Version 1.26
52------------
53Add setfacl support to allow setting of ACLs remotely to Samba 3.10 and later
54and other POSIX CIFS compliant servers. Fix error mapping for getfacl
55to EOPNOTSUPP when server does not support posix acls on the wire. Fix
56improperly zeroed buffer in CIFS Unix extensions set times call.
57
58Version 1.25
59------------
60Fix internationlization problem in cifs readdir with filenames that map to
61longer UTF8 strings than the string on the wire was in Unicode. Add workaround
62for readdir to netapp servers. Fix search rewind (seek into readdir to return
63non-consecutive entries). Do not do readdir when server negotiates
64buffer size to small to fit filename. Add support for reading POSIX ACLs from
65the server (add also acl and noacl mount options).
66
67Version 1.24
68------------
69Optionally allow using server side inode numbers, rather than client generated
70ones by specifying mount option "serverino" - this is required for some apps
71to work which double check hardlinked files and have persistent inode numbers.
72
73Version 1.23
74------------
75Multiple bigendian fixes. On little endian systems (for reconnect after
76network failure) fix tcp session reconnect code so we do not try first
77to reconnect on reverse of port 445. Treat reparse points (NTFS junctions)
78as directories rather than symlinks because we can do follow link on them.
79
80Version 1.22
81------------
82Add config option to enable XATTR (extended attribute) support, mapping
83xattr names in the "user." namespace space to SMB/CIFS EAs. Lots of
84minor fixes pointed out by the Stanford SWAT checker (mostly missing
85or out of order NULL pointer checks in little used error paths).
86
87Version 1.21
88------------
89Add new mount parm to control whether mode check (generic_permission) is done
90on the client. If Unix extensions are enabled and the uids on the client
91and server do not match, client permission checks are meaningless on
92server uids that do not exist on the client (this does not affect the
93normal ACL check which occurs on the server). Fix default uid
94on mknod to match create and mkdir. Add optional mount parm to allow
95override of the default uid behavior (in which the server sets the uid
96and gid of newly created files). Normally for network filesystem mounts
97user want the server to set the uid/gid on newly created files (rather than
98using uid of the client processes you would in a local filesystem).
99
100Version 1.20
101------------
102Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
103info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir
104(in build_wildcard_path_from_dentry). Fix mknod to pass type field
105(block/char/fifo) properly. Remove spurious mount warning log entry when
106credentials passed as mount argument. Set major/minor device number in
107inode for block and char devices when unix extensions enabled.
108
109Version 1.19
110------------
111Fix /proc/fs/cifs/Stats and DebugData display to handle larger
112amounts of return data. Properly limit requests to MAX_REQ (50
113is the usual maximum active multiplex SMB/CIFS requests per server).
114Do not kill cifsd (and thus hurt the other SMB session) when more than one
115session to the same server (but with different userids) exists and one
116of the two user's smb sessions is being removed while leaving the other.
117Do not loop reconnecting in cifsd demultiplex thread when admin
118kills the thread without going through unmount.
119
120Version 1.18
121------------
122Do not rename hardlinked files (since that should be a noop). Flush
123cached write behind data when reopening a file after session abend,
124except when already in write. Grab per socket sem during reconnect
125to avoid oops in sendmsg if overlapping with reconnect. Do not
126reset cached inode file size on readdir for files open for write on
127client.
128
129
130Version 1.17
131------------
132Update number of blocks in file so du command is happier (in Linux a fake
133blocksize of 512 is required for calculating number of blocks in inode).
134Fix prepare write of partial pages to read in data from server if possible.
135Fix race on tcpStatus field between unmount and reconnection code, causing
136cifsd process sometimes to hang around forever. Improve out of memory
137checks in cifs_filldir
138
139Version 1.16
140------------
141Fix incorrect file size in file handle based setattr on big endian hardware.
142Fix oops in build_path_from_dentry when out of memory. Add checks for invalid
143and closing file structs in writepage/partialpagewrite. Add statistics
144for each mounted share (new menuconfig option). Fix endianness problem in
145volume information displayed in /proc/fs/cifs/DebugData (only affects
146affects big endian architectures). Prevent renames while constructing
147path names for open, mkdir and rmdir.
148
149Version 1.15
150------------
151Change to mempools for alloc smb request buffers and multiplex structs
152to better handle low memory problems (and potential deadlocks).
153
154Version 1.14
155------------
156Fix incomplete listings of large directories on Samba servers when Unix
157extensions enabled. Fix oops when smb_buffer can not be allocated. Fix
158rename deadlock when writing out dirty pages at same time.
159
160Version 1.13
161------------
162Fix open of files in which O_CREATE can cause the mode to change in
163some cases. Fix case in which retry of write overlaps file close.
164Fix PPC64 build error. Reduce excessive stack usage in smb password
165hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
166
167Version 1.12
168------------
169Fixes for large file copy, signal handling, socket retry, buffer
170allocation and low memory situations.
171
172Version 1.11
173------------
174Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
175also now allowing support for specifying client netbiosname. NT4 support added.
176
177Version 1.10
178------------
179Fix reconnection (and certain failed mounts) to properly wake up the
180blocked users thread so it does not seem hung (in some cases was blocked
181until the cifs receive timeout expired). Fix spurious error logging
182to kernel log when application with open network files killed.
183
184Version 1.09
185------------
186Fix /proc/fs module unload warning message (that could be logged
187to the kernel log). Fix intermittent failure in connectathon
188test7 (hardlink count not immediately refreshed in case in which
189inode metadata can be incorrectly kept cached when time near zero)
190
191Version 1.08
192------------
193Allow file_mode and dir_mode (specified at mount time) to be enforced
194locally (the server already enforced its own ACLs too) for servers
195that do not report the correct mode (do not support the
196CIFS Unix Extensions).
197
198Version 1.07
199------------
200Fix some small memory leaks in some unmount error paths. Fix major leak
201of cache pages in readpages causing multiple read oriented stress
202testcases (including fsx, and even large file copy) to fail over time.
203
204Version 1.06
205------------
206Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
207This allows files that differ only in case and improves performance of file
208creation and file open to such servers. Fix semaphore conflict which causes
209slow delete of open file to Samba (which unfortunately can cause an oplock
210break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
211
212Version 1.05
213------------
214fixes to cifs_readpages for fsx test case
215
216Version 1.04
217------------
218Fix caching data integrity bug when extending file size especially when no
219oplock on file. Fix spurious logging of valid already parsed mount options
220that are parsed outside of the cifs vfs such as nosuid.
221
222
223Version 1.03
224------------
225Connect to server when port number override not specified, and tcp port
226unitialized. Reset search to restart at correct file when kernel routine
227filldir returns error during large directory searches (readdir).
228
229Version 1.02
230------------
231Fix caching problem when files opened by multiple clients in which
232page cache could contain stale data, and write through did
233not occur often enough while file was still open when read ahead
234(read oplock) not allowed. Treat "sep=" when first mount option
235as an overrride of comma as the default separator between mount
236options.
237
238Version 1.01
239------------
240Allow passwords longer than 16 bytes. Allow null password string.
241
242Version 1.00
243------------
244Gracefully clean up failed mounts when attempting to mount to servers such as
245Windows 98 that terminate tcp sessions during prototocol negotiation. Handle
246embedded commas in mount parsing of passwords.
247
248Version 0.99
249------------
250Invalidate local inode cached pages on oplock break and when last file
251instance is closed so that the client does not continue using stale local
252copy rather than later modified server copy of file. Do not reconnect
253when server drops the tcp session prematurely before negotiate
254protocol response. Fix oops in roepen_file when dentry freed. Allow
255the support for CIFS Unix Extensions to be disabled via proc interface.
256
257Version 0.98
258------------
259Fix hang in commit_write during reconnection of open files under heavy load.
260Fix unload_nls oops in a mount failure path. Serialize writes to same socket
261which also fixes any possible races when cifs signatures are enabled in SMBs
262being sent out of signature sequence number order.
263
264Version 0.97
265------------
266Fix byte range locking bug (endian problem) causing bad offset and
267length.
268
269Version 0.96
270------------
271Fix oops (in send_sig) caused by CIFS unmount code trying to
272wake up the demultiplex thread after it had exited. Do not log
273error on harmless oplock release of closed handle.
274
275Version 0.95
276------------
277Fix unsafe global variable usage and password hash failure on gcc 3.3.1
278Fix problem reconnecting secondary mounts to same server after session
279failure. Fix invalid dentry - race in mkdir when directory gets created
280by another client between the lookup and mkdir.
281
282Version 0.94
283------------
284Fix to list processing in reopen_files. Fix reconnection when server hung
285but tcpip session still alive. Set proper timeout on socket read.
286
287Version 0.93
288------------
289Add missing mount options including iocharset. SMP fixes in write and open.
290Fix errors in reconnecting after TCP session failure. Fix module unloading
291of default nls codepage
292
293Version 0.92
294------------
295Active smb transactions should never go negative (fix double FreeXid). Fix
296list processing in file routines. Check return code on kmalloc in open.
297Fix spinlock usage for SMP.
298
299Version 0.91
300------------
301Fix oops in reopen_files when invalid dentry. drop dentry on server rename
302and on revalidate errors. Fix cases where pid is now tgid. Fix return code
303on create hard link when server does not support them.
304
305Version 0.90
306------------
307Fix scheduling while atomic error in getting inode info on newly created file.
308Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
309
310Version 0.89
311------------
312Fix oops on write to dead tcp session. Remove error log write for case when file open
313O_CREAT but not O_EXCL
314
315Version 0.88
316------------
317Fix non-POSIX behavior on rename of open file and delete of open file by taking
318advantage of trans2 SetFileInfo rename facility if available on target server.
319Retry on ENOSPC and EAGAIN socket errors.
320
321Version 0.87
322------------
323Fix oops on big endian readdir. Set blksize to be even power of two (2**blkbits) to fix
324allocation size miscalculation. After oplock token lost do not read through
325cache.
326
327Version 0.86
328------------
329Fix oops on empty file readahead. Fix for file size handling for locally cached files.
330
331Version 0.85
332------------
333Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
334during auto reconnection to server after server recovered from failure.
335
336Version 0.84
337------------
338Finish support for Linux 2.5 open/create changes, which removes the
339redundant NTCreate/QPathInfo/close that was sent during file create.
340Enable oplock by default. Enable packet signing by default (needed to
341access many recent Windows servers)
342
343Version 0.83
344------------
345Fix oops when mounting to long server names caused by inverted parms to kmalloc.
346Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
347we will choose a cifs user session (smb uid) that better matches the local
348uid if a) the mount uid does not match the current uid and b) we have another
349session to the same server (ip address) for a different mount which
350matches the current local uid.
351
352Version 0.82
353------------
354Add support for mknod of block or character devices. Fix oplock
355code (distributed caching) to properly send response to oplock
356break from server.
357
358Version 0.81
359------------
360Finish up CIFS packet digital signing for the default
361NTLM security case. This should help Windows 2003
362network interoperability since it is common for
363packet signing to be required now. Fix statfs (stat -f)
364which recently started returning errors due to
365invalid value (-1 instead of 0) being set in the
366struct kstatfs f_ffiles field.
367
368Version 0.80
369-----------
370Fix oops on stopping oplock thread when removing cifs when
371built as module.
372
373Version 0.79
374------------
375Fix mount options for ro (readonly), uid, gid and file and directory mode.
376
377Version 0.78
378------------
379Fix errors displayed on failed mounts to be more understandable.
380Fixed various incorrect or misleading smb to posix error code mappings.
381
382Version 0.77
383------------
384Fix display of NTFS DFS junctions to display as symlinks.
385They are the network equivalent. Fix oops in
386cifs_partialpagewrite caused by missing spinlock protection
387of openfile linked list. Allow writebehind caching errors to
388be returned to the application at file close.
389
390Version 0.76
391------------
392Clean up options displayed in /proc/mounts by show_options to
393be more consistent with other filesystems.
394
395Version 0.75
396------------
397Fix delete of readonly file to Windows servers. Reflect
398presence or absence of read only dos attribute in mode
399bits for servers that do not support CIFS Unix extensions.
400Fix shortened results on readdir of large directories to
401servers supporting CIFS Unix extensions (caused by
402incorrect resume key).
403
404Version 0.74
405------------
406Fix truncate bug (set file size) that could cause hangs e.g. running fsx
407
408Version 0.73
409------------
410unload nls if mount fails.
411
412Version 0.72
413------------
414Add resume key support to search (readdir) code to workaround
415Windows bug. Add /proc/fs/cifs/LookupCacheEnable which
416allows disabling caching of attribute information for
417lookups.
418
419Version 0.71
420------------
421Add more oplock handling (distributed caching code). Remove
422dead code. Remove excessive stack space utilization from
423symlink routines.
424
425Version 0.70
426------------
427Fix oops in get dfs referral (triggered when null path sent in to
428mount). Add support for overriding rsize at mount time.
429
430Version 0.69
431------------
432Fix buffer overrun in readdir which caused intermittent kernel oopses.
433Fix writepage code to release kmap on write data. Allow "-ip=" new
434mount option to be passed in on parameter distinct from the first part
435(server name portion of) the UNC name. Allow override of the
436tcp port of the target server via new mount option "-port="
437
438Version 0.68
439------------
440Fix search handle leak on rewind. Fix setuid and gid so that they are
441reflected in the local inode immediately. Cleanup of whitespace
442to make 2.4 and 2.5 versions more consistent.
443
444
445Version 0.67
446------------
447Fix signal sending so that captive thread (cifsd) exits on umount
448(which was causing the warning in kmem_cache_free of the request buffers
449at rmmod time). This had broken as a sideeffect of the recent global
450kernel change to daemonize. Fix memory leak in readdir code which
451showed up in "ls -R" (and applications that did search rewinding).
452
453Version 0.66
454------------
455Reconnect tids and fids after session reconnection (still do not
456reconnect byte range locks though). Fix problem caching
457lookup information for directory inodes, improving performance,
458especially in deep directory trees. Fix various build warnings.
459
460Version 0.65
461------------
462Finish fixes to commit write for caching/readahead consistency. fsx
463now works to Samba servers. Fix oops caused when readahead
464was interrupted by a signal.
465
466Version 0.64
467------------
468Fix data corruption (in partial page after truncate) that caused fsx to
469fail to Windows servers. Cleaned up some extraneous error logging in
470common error paths. Add generic sendfile support.
471
472Version 0.63
473------------
474Fix memory leak in AllocMidQEntry.
475Finish reconnection logic, so connection with server can be dropped
476(or server rebooted) and the cifs client will reconnect.
477
478Version 0.62
479------------
480Fix temporary socket leak when bad userid or password specified
481(or other SMBSessSetup failure). Increase maximum buffer size to slightly
482over 16K to allow negotiation of up to Samba and Windows server default read
483sizes. Add support for readpages
484
485Version 0.61
486------------
487Fix oops when username not passed in on mount. Extensive fixes and improvements
488to error logging (strip redundant newlines, change debug macros to ensure newline
489passed in and to be more consistent). Fix writepage wrong file handle problem,
490a readonly file handle could be incorrectly used to attempt to write out
491file updates through the page cache to multiply open files. This could cause
492the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
493shares to the same Windows server when using different usernames
494(doing this to Samba servers worked but Windows was rejecting it) - now it is
495possible to use different userids when connecting to the same server from a
496Linux client. Fix oops when treeDisconnect called during unmount on
497previously freed socket.
498
499Version 0.60
500------------
501Fix oops in readpages caused by not setting address space operations in inode in
502rare code path.
503
504Version 0.59
505------------
506Includes support for deleting of open files and renaming over existing files (per POSIX
507requirement). Add readlink support for Windows junction points (directory symlinks).
508
509Version 0.58
510------------
511Changed read and write to go through pagecache. Added additional address space operations.
512Memory mapped operations now working.
513
514Version 0.57
515------------
516Added writepage code for additional memory mapping support. Fixed leak in xids causing
517the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on
518every stat call. Additional formatting cleanup.
519
520Version 0.56
521------------
522Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version. Formatting cleanup.
523
524Version 0.55
525------------
526Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
527Also included a modified version of his fix to protect global list manipulation of
528the smb session and tree connection and mid related global variables.
529
530Version 0.54
531------------
532Fix problem with captive thread hanging around at unmount time. Adjust to 2.5.42-pre
533changes to superblock layout. Remove wasteful allocation of smb buffers (now the send
534buffer is reused for responses). Add more oplock handling. Additional minor cleanup.
535
536Version 0.53
537------------
538More stylistic updates to better match kernel style. Add additional statistics
539for filesystem which can be viewed via /proc/fs/cifs. Add more pieces of NTLMv2
540and CIFS Packet Signing enablement.
541
542Version 0.52
543------------
544Replace call to sleep_on with safer wait_on_event.
545Make stylistic changes to better match kernel style recommendations.
546Remove most typedef usage (except for the PDUs themselves).
547
548Version 0.51
549------------
550Update mount so the -unc mount option is no longer required (the ip address can be specified
551in a UNC style device name. Implementation of readpage/writepage started.
552
553Version 0.50
554------------
555Fix intermittent problem with incorrect smb header checking on badly
556fragmented tcp responses
557
558Version 0.49
559------------
560Fixes to setting of allocation size and file size.
561
562Version 0.48
563------------
564Various 2.5.38 fixes. Now works on 2.5.38
565
566Version 0.47
567------------
568Prepare for 2.5 kernel merge. Remove ifdefs.
569
570Version 0.46
571------------
572Socket buffer management fixes. Fix dual free.
573
574Version 0.45
575------------
576Various big endian fixes for hardlinks and symlinks and also for dfs.
577
578Version 0.44
579------------
580Various big endian fixes for servers with Unix extensions such as Samba
581
582Version 0.43
583------------
584Various FindNext fixes for incorrect filenames on large directory searches on big endian
585clients. basic posix file i/o tests now work on big endian machines, not just le
586
587Version 0.42
588------------
589SessionSetup and NegotiateProtocol now work from Big Endian machines.
590Various Big Endian fixes found during testing on the Linux on 390. Various fixes for compatibility with older
591versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
592
593Version 0.41
594------------
595Various minor fixes for Connectathon Posix "basic" file i/o test suite. Directory caching fixed so hardlinked
596files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
597
598Version 0.40
599------------
600Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
601session advanced session authentication). Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
602Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
603(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
604
605Version 0.38
606------------
607Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
608it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
609
610Version 0.37
611------------
612Rewrote much of connection and mount/unmount logic to handle bugs with
613multiple uses to same share, multiple users to same server etc.
614
615Version 0.36
616------------
617Fixed major problem with dentry corruption (missing call to dput)
618
619Version 0.35
620------------
621Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
622Begin adding oplock support. Multiusermount and oplockEnabled flags added to /proc/fs/cifs
623although corresponding function not fully implemented in the vfs yet
624
625Version 0.34
626------------
627Fixed dentry caching bug, misc. cleanup
628
629Version 0.33
630------------
631Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes. Now can build
632on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
633Support for STATUS codes (newer 32 bit NT error codes) added. DFS support begun to be added.
634
635Version 0.32
636------------
637Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
638and tested against Samba 2.2.5
639
640
641Version 0.31
642------------
6431) Fixed lockrange to be correct (it was one byte too short)
644
6452) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly
646show range as locked when there is a conflict with an existing lock.
647
6483) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
649in most cases. Eventually will offer optional ability to query server for the correct perms.
650
6513) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded
652but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
653session)
654
6554) Fixed error logging of valid mount options
656
6575) Removed logging of password field.
658
6596) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
660and cleaned them up and made them more consistent with other cifs functions.
661
6627) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways
663(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
664nor is the symlink support using the Unix extensions
665
6668) Started adding the readlink and follow_link code
667
668Version 0.3
669-----------
670Initial drop
671
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
new file mode 100644
index 000000000000..7384947a0f93
--- /dev/null
+++ b/fs/cifs/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for Linux CIFS VFS client
3#
4obj-$(CONFIG_CIFS) += cifs.o
5
6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o
diff --git a/fs/cifs/README b/fs/cifs/README
new file mode 100644
index 000000000000..0f20edc935b5
--- /dev/null
+++ b/fs/cifs/README
@@ -0,0 +1,475 @@
1The CIFS VFS support for Linux supports many advanced network filesystem
2features such as heirarchical dfs like namespace, hardlinks, locking and more.
3It was designed to comply with the SNIA CIFS Technical Reference (which
4supersedes the 1992 X/Open SMB Standard) as well as to perform best practice
5practical interoperability with Windows 2000, Windows XP, Samba and equivalent
6servers.
7
8For questions or bug reports please contact:
9 sfrench@samba.org (sfrench@us.ibm.com)
10
11Build instructions:
12==================
13For Linux 2.4:
141) Get the kernel source (e.g.from http://www.kernel.org)
15and download the cifs vfs source (see the project page
16at http://us1.samba.org/samba/Linux_CIFS_client.html)
17and change directory into the top of the kernel directory
18then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
19to add the cifs vfs to your kernel configure options if
20it has not already been added (e.g. current SuSE and UL
21users do not need to apply the cifs_24.patch since the cifs vfs is
22already in the kernel configure menu) and then
23mkdir linux/fs/cifs and then copy the current cifs vfs files from
24the cifs download to your kernel build directory e.g.
25
26 cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
27
282) make menuconfig (or make xconfig)
293) select cifs from within the network filesystem choices
304) save and exit
315) make dep
326) make modules (or "make" if CIFS VFS not to be built as a module)
33
34For Linux 2.6:
351) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
36at bk://linux.bkbits.net/linux-2.5) and change directory into the top
37of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
382) make menuconfig (or make xconfig)
393) select cifs from within the network filesystem choices
404) save and exit
415) make
42
43
44Installation instructions:
45=========================
46If you have built the CIFS vfs as module (successfully) simply
47type "make modules_install" (or if you prefer, manually copy the file to
48the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
49
50If you have built the CIFS vfs into the kernel itself, follow the instructions
51for your distribution on how to install a new kernel (usually you
52would simply type "make install").
53
54If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
55the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
56similar files reside (usually /sbin). Although the helper software is not
57required, mount.cifs is recommended. Eventually the Samba 3.0 utility program
58"net" may also be helpful since it may someday provide easier mount syntax for
59users who are used to Windows e.g. net use <mount point> <UNC name or cifs URL>
60Note that running the Winbind pam/nss module (logon service) on all of your
61Linux clients is useful in mapping Uids and Gids consistently across the
62domain to the proper network user. The mount.cifs mount helper can be
63trivially built from Samba 3.0 or later source e.g. by executing:
64
65 gcc samba/source/client/mount.cifs.c -o mount.cifs
66
67If cifs is built as a module, then the size and number of network buffers
68and maximum number of simultaneous requests to one server can be configured.
69Changing these from their defaults is not recommended. By executing modinfo
70 modinfo kernel/fs/cifs/cifs.ko
71on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made
72at module initialization time (by running insmod cifs.ko) can be seen.
73
74Allowing User Mounts
75====================
76To permit users to mount and unmount over directories they own is possible
77with the cifs vfs. A way to enable such mounting is to mark the mount.cifs
78utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to
79umount shares they mount requires
801) mount.cifs version 1.4 or later
812) an entry for the share in /etc/fstab indicating that a user may
82unmount it e.g.
83//server/usersharename /mnt/username cifs user 0 0
84
85Note that when the mount.cifs utility is run suid (allowing user mounts),
86in order to reduce risks, the "nosuid" mount flag is passed in on mount to
87disallow execution of an suid program mounted on the remote target.
88When mount is executed as root, nosuid is not passed in by default,
89and execution of suid programs on the remote target would be enabled
90by default. This can be changed, as with nfs and other filesystems,
91by simply specifying "nosuid" among the mount options. For user mounts
92though to be able to pass the suid flag to mount requires rebuilding
93mount.cifs with the following flag:
94
95 gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
96
97There is a corresponding manual page for cifs mounting in the Samba 3.0 and
98later source tree in docs/manpages/mount.cifs.8
99
100Samba Considerations
101====================
102To get the maximum benefit from the CIFS VFS, we recommend using a server that
103supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
104Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
105Note that uid, gid and file permissions will display default values if you do
106not have a server that supports the Unix extensions for CIFS (such as Samba
1072.2.5 or later). To enable the Unix CIFS Extensions in the Samba server, add
108the line:
109
110 unix extensions = yes
111
112to your smb.conf file on the server. Note that the following smb.conf settings
113are also useful (on the Samba server) when the majority of clients are Unix or
114Linux:
115
116 case sensitive = yes
117 delete readonly = yes
118 ea support = yes
119
120Note that server ea support is required for supporting xattrs from the Linux
121cifs client, and that EA support is present in later versions of Samba (e.g.
1223.0.6 and later (also EA support works in all versions of Windows, at least to
123shares on NTFS filesystems). Extended Attribute (xattr) support is an optional
124feature of most Linux filesystems which may require enabling via
125make menuconfig. Client support for extended attributes (user xattr) can be
126disabled on a per-mount basis by specifying "nouser_xattr" on mount.
127
128The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba servers
129version 3.10 and later. Setting POSIX ACLs requires enabling both XATTR and
130then POSIX support in the CIFS configuration options when building the cifs
131module. POSIX ACL support can be disabled on a per mount basic by specifying
132"noacl" on mount.
133
134Some administrators may want to change Samba's smb.conf "map archive" and
135"create mask" parameters from the default. Unless the create mask is changed
136newly created files can end up with an unnecessarily restrictive default mode,
137which may not be what you want, although if the CIFS Unix extensions are
138enabled on the server and client, subsequent setattr calls (e.g. chmod) can
139fix the mode. Note that creating special devices (mknod) remotely
140may require specifying a mkdev function to Samba if you are not using
141Samba 3.0.6 or later. For more information on these see the manual pages
142("man smb.conf") on the Samba server system. Note that the cifs vfs,
143unlike the smbfs vfs, does not read the smb.conf on the client system
144(the few optional settings are passed in on mount via -o parameters instead).
145Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
146open files (required for strict POSIX compliance). Windows Servers already
147supported this feature. Samba server does not allow symlinks that refer to files
148outside of the share, so in Samba versions prior to 3.0.6, most symlinks to
149files with absolute paths (ie beginning with slash) such as:
150 ln -s /mnt/foo bar
151would be forbidden. Samba 3.0.6 server or later includes the ability to create
152such symlinks safely by converting unsafe symlinks (ie symlinks to server
153files that are outside of the share) to a samba specific format on the server
154that is ignored by local server applications and non-cifs clients and that will
155not be traversed by the Samba server). This is opaque to the Linux client
156application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
157later, but only for remote clients using the CIFS Unix extensions, and will
158be invisbile to Windows clients and typically will not affect local
159applications running on the same server as Samba.
160
161Use instructions:
162================
163Once the CIFS VFS support is built into the kernel or installed as a module
164(cifs.o), you can use mount syntax like the following to access Samba or Windows
165servers:
166
167 mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
168
169Before -o the option -v may be specified to make the mount.cifs
170mount helper display the mount steps more verbosely.
171After -o the following commonly used cifs vfs specific options
172are supported:
173
174 user=<username>
175 pass=<password>
176 domain=<domain name>
177
178Other cifs mount options are described below. Use of TCP names (in addition to
179ip addresses) is available if the mount helper (mount.cifs) is installed. If
180you do not trust the server to which are mounted, or if you do not have
181cifs signing enabled (and the physical network is insecure), consider use
182of the standard mount options "noexec" and "nosuid" to reduce the risk of
183running an altered binary on your local system (downloaded from a hostile server
184or altered by a hostile router).
185
186Although mounting using format corresponding to the CIFS URL specification is
187not possible in mount.cifs yet, it is possible to use an alternate format
188for the server and sharename (which is somewhat similar to NFS style mount
189syntax) instead of the more widely used UNC format (i.e. \\server\share):
190 mount -t cifs tcp_name_of_server:share_name /mnt -o user=myname,pass=mypasswd
191
192When using the mount helper mount.cifs, passwords may be specified via alternate
193mechanisms, instead of specifying it after -o using the normal "pass=" syntax
194on the command line:
1951) By including it in a credential file. Specify credentials=filename as one
196of the mount options. Credential files contain two lines
197 username=someuser
198 password=your_password
1992) By specifying the password in the PASSWD environment variable (similarly
200the user name can be taken from the USER environment variable).
2013) By specifying the password in a file by name via PASSWD_FILE
2024) By specifying the password in a file by file descriptor via PASSWD_FD
203
204If no password is provided, mount.cifs will prompt for password entry
205
206Restrictions
207============
208Servers must support the NTLM SMB dialect (which is the most recent, supported
209by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers)
210Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC
2111001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a
212problem as most servers support this. IPv6 support is planned for the future,
213and is almost complete.
214
215Valid filenames differ between Windows and Linux. Windows typically restricts
216filenames which contain certain reserved characters (e.g.the character :
217which is used to delimit the beginning of a stream name by Windows), while
218Linux allows a slightly wider set of valid characters in filenames. Windows
219servers can remap such characters when an explicit mapping is specified in
220the Server's registry. Samba starting with version 3.10 will allow such
221filenames (ie those which contain valid Linux characters, which normally
222would be forbidden for Windows/CIFS semantics) as long as the server is
223configured for Unix Extensions (and the client has not disabled
224/proc/fs/cifs/LinuxExtensionsEnabled).
225
226
227CIFS VFS Mount Options
228======================
229A partial list of the supported mount options follows:
230 user The user name to use when trying to establish
231 the CIFS session.
232 password The user password. If the mount helper is
233 installed, the user will be prompted for password
234 if it is not supplied.
235 ip The ip address of the target server
236 unc The target server Universal Network Name (export) to
237 mount.
238 domain Set the SMB/CIFS workgroup name prepended to the
239 username during CIFS session establishment
240 uid If CIFS Unix extensions are not supported by the server
241 this overrides the default uid for inodes. For mounts to
242 servers which do support the CIFS Unix extensions, such
243 as a properly configured Samba server, the server provides
244 the uid, gid and mode. For servers which do not support
245 the Unix extensions, the default uid (and gid) returned on
246 lookup of existing files is the uid (gid) of the person
247 who executed the mount (root, except when mount.cifs
248 is configured setuid for user mounts) unless the "uid="
249 (gid) mount option is specified. For the uid (gid) of newly
250 created files and directories, ie files created since
251 the last mount of the server share, the expected uid
252 (gid) is cached as as long as the inode remains in
253 memory on the client. Also note that permission
254 checks (authorization checks) on accesses to a file occur
255 at the server, but there are cases in which an administrator
256 may want to restrict at the client as well. For those
257 servers which do not report a uid/gid owner
258 (such as Windows), permissions can also be checked at the
259 client, and a crude form of client side permission checking
260 can be enabled by specifying file_mode and dir_mode on
261 the client
262 gid If CIFS Unix extensions are not supported by the server
263 this overrides the default gid for inodes.
264 file_mode If CIFS Unix extensions are not supported by the server
265 this overrides the default mode for file inodes.
266 dir_mode If CIFS Unix extensions are not supported by the server
267 this overrides the default mode for directory inodes.
268 port attempt to contact the server on this tcp port, before
269 trying the usual ports (port 445, then 139).
270 iocharset Codepage used to convert local path names to and from
271 Unicode. Unicode is used by default for network path
272 names if the server supports it. If iocharset is
273 not specified then the nls_default specified
274 during the local client kernel build will be used.
275 If server does not support Unicode, this parameter is
276 unused.
277 rsize default read size
278 wsize default write size
279 rw mount the network share read-write (note that the
280 server may still consider the share read-only)
281 ro mount network share read-only
282 version used to distinguish different versions of the
283 mount helper utility (not typically needed)
284 sep if first mount option (after the -o), overrides
285 the comma as the separator between the mount
286 parms. e.g.
287 -o user=myname,password=mypassword,domain=mydom
288 could be passed instead with period as the separator by
289 -o sep=.user=myname.password=mypassword.domain=mydom
290 this might be useful when comma is contained within username
291 or password or domain. This option is less important
292 when the cifs mount helper cifs.mount (version 1.1 or later)
293 is used.
294 nosuid Do not allow remote executables with the suid bit
295 program to be executed. This is only meaningful for mounts
296 to servers such as Samba which support the CIFS Unix Extensions.
297 If you do not trust the servers in your network (your mount
298 targets) it is recommended that you specify this option for
299 greater security.
300 exec Permit execution of binaries on the mount.
301 noexec Do not permit execution of binaries on the mount.
302 dev Recognize block devices on the remote mount.
303 nodev Do not recognize devices on the remote mount.
304 suid Allow remote files on this mountpoint with suid enabled to
305 be executed (default for mounts when executed as root,
306 nosuid is default for user mounts).
307 credentials Although ignored by the cifs kernel component, it is used by
308 the mount helper, mount.cifs. When mount.cifs is installed it
309 opens and reads the credential file specified in order
310 to obtain the userid and password arguments which are passed to
311 the cifs vfs.
312 guest Although ignored by the kernel component, the mount.cifs
313 mount helper will not prompt the user for a password
314 if guest is specified on the mount options. If no
315 password is specified a null password will be used.
316 perm Client does permission checks (vfs_permission check of uid
317 and gid of the file against the mode and desired operation),
318 Note that this is in addition to the normal ACL check on the
319 target machine done by the server software.
320 Client permission checking is enabled by default.
321 noperm Client does not do permission checks. This can expose
322 files on this mount to access by other users on the local
323 client system. It is typically only needed when the server
324 supports the CIFS Unix Extensions but the UIDs/GIDs on the
325 client and server system do not match closely enough to allow
326 access by the user doing the mount.
327 Note that this does not affect the normal ACL check on the
328 target machine done by the server software (of the server
329 ACL against the user name provided at mount time).
330 serverino Use servers inode numbers instead of generating automatically
331 incrementing inode numbers on the client. Although this will
332 make it easier to spot hardlinked files (as they will have
333 the same inode numbers) and inode numbers may be persistent,
334 note that the server does not guarantee that the inode numbers
335 are unique if multiple server side mounts are exported under a
336 single share (since inode numbers on the servers might not
337 be unique if multiple filesystems are mounted under the same
338 shared higher level directory). Note that this requires that
339 the server support the CIFS Unix Extensions as other servers
340 do not return a unique IndexNumber on SMB FindFirst (most
341 servers return zero as the IndexNumber). Parameter has no
342 effect to Windows servers and others which do not support the
343 CIFS Unix Extensions.
344 noserverino Client generates inode numbers (rather than using the actual one
345 from the server) by default.
346 setuids If the CIFS Unix extensions are negotiated with the server
347 the client will attempt to set the effective uid and gid of
348 the local process on newly created files, directories, and
349 devices (create, mkdir, mknod).
350 nosetuids The client will not attempt to set the uid and gid on
351 on newly created files, directories, and devices (create,
352 mkdir, mknod) which will result in the server setting the
353 uid and gid to the default (usually the server uid of the
354 usern who mounted the share). Letting the server (rather than
355 the client) set the uid and gid is the default. This
356 parameter has no effect if the CIFS Unix Extensions are not
357 negotiated.
358 netbiosname When mounting to servers via port 139, specifies the RFC1001
359 source name to use to represent the client netbios machine
360 name when doing the RFC1001 netbios session initialize.
361 direct Do not do inode data caching on files opened on this mount.
362 This precludes mmaping files on this mount. In some cases
363 with fast networks and little or no caching benefits on the
364 client (e.g. when the application is doing large sequential
365 reads bigger than page size without rereading the same data)
366 this can provide better performance than the default
367 behavior which caches reads (reaadahead) and writes
368 (writebehind) through the local Linux client pagecache
369 if oplock (caching token) is granted and held. Note that
370 direct allows write operations larger than page size
371 to be sent to the server.
372 acl Allow setfacl and getfacl to manage posix ACLs if server
373 supports them. (default)
374 noacl Do not allow setfacl and getfacl calls on this mount
375 user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended
376 attributes) to the server (default) e.g. via setfattr
377 and getfattr utilities.
378 nouser_xattr Do not allow getfattr/setfattr to get/set xattrs
379
380The mount.cifs mount helper also accepts a few mount options before -o
381including:
382
383 -S take password from stdin (equivalent to setting the environment
384 variable "PASSWD_FD=0"
385 -V print mount.cifs version
386 -? display simple usage information
387
388With recent 2.6 kernel versions of modutils, the version of the cifs kernel
389module can be displayed via modinfo.
390
391Misc /proc/fs/cifs Flags and Debug Info
392=======================================
393Informational pseudo-files:
394DebugData Displays information about active CIFS sessions
395 and shares.
396Stats Lists summary resource usage information as well as per
397 share statistics, if CONFIG_CIFS_STATS in enabled
398 in the kernel configuration.
399
400Configuration pseudo-files:
401MultiuserMount If set to one, more than one CIFS session to
402 the same server ip address can be established
403 if more than one uid accesses the same mount
404 point and if the uids user/password mapping
405 information is available. (default is 0)
406PacketSigningEnabled If set to one, cifs packet signing is enabled
407 and will be used if the server requires
408 it. If set to two, cifs packet signing is
409 required even if the server considers packet
410 signing optional. (default 1)
411cifsFYI If set to one, additional debug information is
412 logged to the system error log. (default 0)
413ExtendedSecurity If set to one, SPNEGO session establishment
414 is allowed which enables more advanced
415 secure CIFS session establishment (default 0)
416NTLMV2Enabled If set to one, more secure password hashes
417 are used when the server supports them and
418 when kerberos is not negotiated (default 0)
419traceSMB If set to one, debug information is logged to the
420 system error log with the start of smb requests
421 and responses (default 0)
422LookupCacheEnable If set to one, inode information is kept cached
423 for one second improving performance of lookups
424 (default 1)
425OplockEnabled If set to one, safe distributed caching enabled.
426 (default 1)
427LinuxExtensionsEnabled If set to one then the client will attempt to
428 use the CIFS "UNIX" extensions which are optional
429 protocol enhancements that allow CIFS servers
430 to return accurate UID/GID information as well
431 as support symbolic links. If you use servers
432 such as Samba that support the CIFS Unix
433 extensions but do not want to use symbolic link
434 support and want to map the uid and gid fields
435 to values supplied at mount (rather than the
436 actual values, then set this to zero. (default 1)
437
438These experimental features and tracing can be enabled by changing flags in
439/proc/fs/cifs (after the cifs module has been installed or built into the
440kernel, e.g. insmod cifs). To enable a feature set it to 1 e.g. to enable
441tracing to the kernel message log type:
442
443 echo 1 > /proc/fs/cifs/cifsFYI
444
445and for more extensive tracing including the start of smb requests and responses
446
447 echo 1 > /proc/fs/cifs/traceSMB
448
449Two other experimental features are under development and to test
450require enabling CONFIG_CIFS_EXPERIMENTAL
451
452 More efficient write operations and SMB buffer handling
453
454 DNOTIFY fcntl: needed for support of directory change
455 notification and perhaps later for file leases)
456
457Per share (per client mount) statistics are available in /proc/fs/cifs/Stats
458if the kernel was configured with cifs statistics enabled. The statistics
459represent the number of successful (ie non-zero return code from the server)
460SMB responses to some of the more common commands (open, delete, mkdir etc.).
461Also recorded is the total bytes read and bytes written to the server for
462that share. Note that due to client caching effects this can be less than the
463number of bytes read and written by the application running on the client.
464The statistics for the number of total SMBs and oplock breaks are different in
465that they represent all for that share, not just those for which the server
466returned success.
467
468Also note that "cat /proc/fs/cifs/DebugData" will display information about
469the active sessions and the shares that are mounted. Note: NTLMv2 enablement
470will not work since they its implementation is not quite complete yet.
471Do not alter these configuration values unless you are doing specific testing.
472Enabling extended security works to Windows 2000 Workstations and XP but not to
473Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
474(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
475complete in the CIFS VFS yet).
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
new file mode 100644
index 000000000000..f4e3e1f67ee4
--- /dev/null
+++ b/fs/cifs/TODO
@@ -0,0 +1,104 @@
1version 1.22 July 30, 2004
2
3A Partial List of Missing Features
4==================================
5
6Contributions are welcome. There are plenty of opportunities
7for visible, important contributions to this module. Here
8is a partial list of the known problems and missing features:
9
10a) Support for SecurityDescriptors for chmod/chgrp/chown so
11these can be supported for Windows servers
12
13b) Better pam/winbind integration (e.g. to handle uid mapping
14better)
15
16c) multi-user mounts - multiplexed sessionsetups over single vc
17(ie tcp session) - prettying up needed, and more testing needed
18
19d) Kerberos/SPNEGO session setup support - (started)
20
21e) NTLMv2 authentication (mostly implemented)
22
23f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
24used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
25and raw NTLMSSP already. This is important when enabling
26extended security and mounting to Windows 2003 Servers
27
28f) Directory entry caching relies on a 1 second timer, rather than
29using FindNotify or equivalent. - (started)
30
31g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
32style byte range lock differences
33
34h) quota support
35
36j) finish writepages support (multi-page write behind for improved
37performance) and syncpage
38
39k) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
40extra copy in/out of the socket buffers in some cases.
41
42l) finish support for IPv6. This is mostly complete but
43needs a simple conversion of ipv6 to sin6_addr from the
44address in string representation.
45
46m) Better optimize open (and pathbased setfilesize) to reduce the
47oplock breaks coming from windows srv. Piggyback identical file
48opens on top of each other by incrementing reference count rather
49than resending (helps reduce server resource utilization and avoid
50spurious oplock breaks).
51
52o) Improve performance of readpages by sending more than one read
53at a time when 8 pages or more are requested. In conjuntion
54add support for async_cifs_readpages.
55
56p) Add support for storing symlink and fifo info to Windows servers
57in the Extended Attribute format their SFU clients would recognize.
58
59q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
60will autorefresh (started)
61
62r) Add GUI tool to configure /proc/fs/cifs settings and for display of
63the CIFS statistics (started)
64
65q) implement support for security and trusted categories of xattrs
66(requires minor protocol extension) to enable better support for SELINUX
67
68r) Implement O_DIRECT flag on open (already supported on mount)
69
70KNOWN BUGS (updated December 10, 2004)
71====================================
721) existing symbolic links (Windows reparse points) are recognized but
73can not be created remotely. They are implemented for Samba and those that
74support the CIFS Unix extensions but Samba has a bug currently handling
75symlink text beginning with slash
762) follow_link and readdir code does not follow dfs junctions
77but recognizes them
783) create of new files to FAT partitions on Windows servers can
79succeed but still return access denied (appears to be Windows
80server not cifs client problem) and has not been reproduced recently.
81NTFS partitions do not have this problem.
824) debug connectathon lock test case 10 which fails against
83Samba (may be unmappable due to POSIX to Windows lock model
84differences but worth investigating). Also debug Samba to
85see why lock test case 7 takes longer to complete to Samba
86than to Windows.
87
88Misc testing to do
89==================
901) check out max path names and max path name components against various server
91types. Try nested symlinks (8 deep). Return max path name in stat -f information
92
932) Modify file portion of ltp so it can run against a mounted network
94share and run it against cifs vfs.
95
963) Additional performance testing and optimization using iozone and similar -
97there are some easy changes that can be done to parallelize sequential writes,
98and when signing is disabled to request larger read sizes (larger than
99negotiated size) and send larger write sizes to modern servers.
100
1014) More exhaustively test the recently added NT4 support against various
102NT4 service pack levels, and fix cifs_setattr for setting file times and
103size to fall back to level 1 when error invalid level returned.
104
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
new file mode 100644
index 000000000000..e02010dd73ec
--- /dev/null
+++ b/fs/cifs/asn1.c
@@ -0,0 +1,618 @@
1/*
2 * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
3 * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
4 *
5 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/config.h>
21#include <linux/module.h>
22#include <linux/types.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/slab.h>
26#include "cifspdu.h"
27#include "cifsglob.h"
28#include "cifs_debug.h"
29#include "cifsproto.h"
30
31/*****************************************************************************
32 *
33 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
34 *
35 *****************************************************************************/
36
37/* Class */
38#define ASN1_UNI 0 /* Universal */
39#define ASN1_APL 1 /* Application */
40#define ASN1_CTX 2 /* Context */
41#define ASN1_PRV 3 /* Private */
42
43/* Tag */
44#define ASN1_EOC 0 /* End Of Contents or N/A */
45#define ASN1_BOL 1 /* Boolean */
46#define ASN1_INT 2 /* Integer */
47#define ASN1_BTS 3 /* Bit String */
48#define ASN1_OTS 4 /* Octet String */
49#define ASN1_NUL 5 /* Null */
50#define ASN1_OJI 6 /* Object Identifier */
51#define ASN1_OJD 7 /* Object Description */
52#define ASN1_EXT 8 /* External */
53#define ASN1_SEQ 16 /* Sequence */
54#define ASN1_SET 17 /* Set */
55#define ASN1_NUMSTR 18 /* Numerical String */
56#define ASN1_PRNSTR 19 /* Printable String */
57#define ASN1_TEXSTR 20 /* Teletext String */
58#define ASN1_VIDSTR 21 /* Video String */
59#define ASN1_IA5STR 22 /* IA5 String */
60#define ASN1_UNITIM 23 /* Universal Time */
61#define ASN1_GENTIM 24 /* General Time */
62#define ASN1_GRASTR 25 /* Graphical String */
63#define ASN1_VISSTR 26 /* Visible String */
64#define ASN1_GENSTR 27 /* General String */
65
66/* Primitive / Constructed methods*/
67#define ASN1_PRI 0 /* Primitive */
68#define ASN1_CON 1 /* Constructed */
69
70/*
71 * Error codes.
72 */
73#define ASN1_ERR_NOERROR 0
74#define ASN1_ERR_DEC_EMPTY 2
75#define ASN1_ERR_DEC_EOC_MISMATCH 3
76#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
77#define ASN1_ERR_DEC_BADVALUE 5
78
79#define SPNEGO_OID_LEN 7
80#define NTLMSSP_OID_LEN 10
81static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
82static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
83
84/*
85 * ASN.1 context.
86 */
87struct asn1_ctx {
88 int error; /* Error condition */
89 unsigned char *pointer; /* Octet just to be decoded */
90 unsigned char *begin; /* First octet */
91 unsigned char *end; /* Octet after last octet */
92};
93
94/*
95 * Octet string (not null terminated)
96 */
97struct asn1_octstr {
98 unsigned char *data;
99 unsigned int len;
100};
101
102static void
103asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
104{
105 ctx->begin = buf;
106 ctx->end = buf + len;
107 ctx->pointer = buf;
108 ctx->error = ASN1_ERR_NOERROR;
109}
110
111static unsigned char
112asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
113{
114 if (ctx->pointer >= ctx->end) {
115 ctx->error = ASN1_ERR_DEC_EMPTY;
116 return 0;
117 }
118 *ch = *(ctx->pointer)++;
119 return 1;
120}
121
122static unsigned char
123asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
124{
125 unsigned char ch;
126
127 *tag = 0;
128
129 do {
130 if (!asn1_octet_decode(ctx, &ch))
131 return 0;
132 *tag <<= 7;
133 *tag |= ch & 0x7F;
134 } while ((ch & 0x80) == 0x80);
135 return 1;
136}
137
138static unsigned char
139asn1_id_decode(struct asn1_ctx *ctx,
140 unsigned int *cls, unsigned int *con, unsigned int *tag)
141{
142 unsigned char ch;
143
144 if (!asn1_octet_decode(ctx, &ch))
145 return 0;
146
147 *cls = (ch & 0xC0) >> 6;
148 *con = (ch & 0x20) >> 5;
149 *tag = (ch & 0x1F);
150
151 if (*tag == 0x1F) {
152 if (!asn1_tag_decode(ctx, tag))
153 return 0;
154 }
155 return 1;
156}
157
158static unsigned char
159asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
160{
161 unsigned char ch, cnt;
162
163 if (!asn1_octet_decode(ctx, &ch))
164 return 0;
165
166 if (ch == 0x80)
167 *def = 0;
168 else {
169 *def = 1;
170
171 if (ch < 0x80)
172 *len = ch;
173 else {
174 cnt = (unsigned char) (ch & 0x7F);
175 *len = 0;
176
177 while (cnt > 0) {
178 if (!asn1_octet_decode(ctx, &ch))
179 return 0;
180 *len <<= 8;
181 *len |= ch;
182 cnt--;
183 }
184 }
185 }
186 return 1;
187}
188
189static unsigned char
190asn1_header_decode(struct asn1_ctx *ctx,
191 unsigned char **eoc,
192 unsigned int *cls, unsigned int *con, unsigned int *tag)
193{
194 unsigned int def, len;
195
196 if (!asn1_id_decode(ctx, cls, con, tag))
197 return 0;
198
199 if (!asn1_length_decode(ctx, &def, &len))
200 return 0;
201
202 if (def)
203 *eoc = ctx->pointer + len;
204 else
205 *eoc = NULL;
206 return 1;
207}
208
209static unsigned char
210asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
211{
212 unsigned char ch;
213
214 if (eoc == NULL) {
215 if (!asn1_octet_decode(ctx, &ch))
216 return 0;
217
218 if (ch != 0x00) {
219 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
220 return 0;
221 }
222
223 if (!asn1_octet_decode(ctx, &ch))
224 return 0;
225
226 if (ch != 0x00) {
227 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
228 return 0;
229 }
230 return 1;
231 } else {
232 if (ctx->pointer != eoc) {
233 ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
234 return 0;
235 }
236 return 1;
237 }
238}
239
240/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
241 unsigned char *eoc)
242{
243 ctx->pointer = eoc;
244 return 1;
245}
246
247static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
248 unsigned char *eoc, long *integer)
249{
250 unsigned char ch;
251 unsigned int len;
252
253 if (!asn1_octet_decode(ctx, &ch))
254 return 0;
255
256 *integer = (signed char) ch;
257 len = 1;
258
259 while (ctx->pointer < eoc) {
260 if (++len > sizeof(long)) {
261 ctx->error = ASN1_ERR_DEC_BADVALUE;
262 return 0;
263 }
264
265 if (!asn1_octet_decode(ctx, &ch))
266 return 0;
267
268 *integer <<= 8;
269 *integer |= ch;
270 }
271 return 1;
272}
273
274static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
275 unsigned char *eoc,
276 unsigned int *integer)
277{
278 unsigned char ch;
279 unsigned int len;
280
281 if (!asn1_octet_decode(ctx, &ch))
282 return 0;
283
284 *integer = ch;
285 if (ch == 0)
286 len = 0;
287 else
288 len = 1;
289
290 while (ctx->pointer < eoc) {
291 if (++len > sizeof(unsigned int)) {
292 ctx->error = ASN1_ERR_DEC_BADVALUE;
293 return 0;
294 }
295
296 if (!asn1_octet_decode(ctx, &ch))
297 return 0;
298
299 *integer <<= 8;
300 *integer |= ch;
301 }
302 return 1;
303}
304
305static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
306 unsigned char *eoc,
307 unsigned long *integer)
308{
309 unsigned char ch;
310 unsigned int len;
311
312 if (!asn1_octet_decode(ctx, &ch))
313 return 0;
314
315 *integer = ch;
316 if (ch == 0)
317 len = 0;
318 else
319 len = 1;
320
321 while (ctx->pointer < eoc) {
322 if (++len > sizeof(unsigned long)) {
323 ctx->error = ASN1_ERR_DEC_BADVALUE;
324 return 0;
325 }
326
327 if (!asn1_octet_decode(ctx, &ch))
328 return 0;
329
330 *integer <<= 8;
331 *integer |= ch;
332 }
333 return 1;
334}
335
336static unsigned char
337asn1_octets_decode(struct asn1_ctx *ctx,
338 unsigned char *eoc,
339 unsigned char **octets, unsigned int *len)
340{
341 unsigned char *ptr;
342
343 *len = 0;
344
345 *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
346 if (*octets == NULL) {
347 return 0;
348 }
349
350 ptr = *octets;
351 while (ctx->pointer < eoc) {
352 if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
353 kfree(*octets);
354 *octets = NULL;
355 return 0;
356 }
357 (*len)++;
358 }
359 return 1;
360} */
361
362static unsigned char
363asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
364{
365 unsigned char ch;
366
367 *subid = 0;
368
369 do {
370 if (!asn1_octet_decode(ctx, &ch))
371 return 0;
372
373 *subid <<= 7;
374 *subid |= ch & 0x7F;
375 } while ((ch & 0x80) == 0x80);
376 return 1;
377}
378
379static int
380asn1_oid_decode(struct asn1_ctx *ctx,
381 unsigned char *eoc, unsigned long **oid, unsigned int *len)
382{
383 unsigned long subid;
384 unsigned int size;
385 unsigned long *optr;
386
387 size = eoc - ctx->pointer + 1;
388 *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
389 if (*oid == NULL) {
390 return 0;
391 }
392
393 optr = *oid;
394
395 if (!asn1_subid_decode(ctx, &subid)) {
396 kfree(*oid);
397 *oid = NULL;
398 return 0;
399 }
400
401 if (subid < 40) {
402 optr[0] = 0;
403 optr[1] = subid;
404 } else if (subid < 80) {
405 optr[0] = 1;
406 optr[1] = subid - 40;
407 } else {
408 optr[0] = 2;
409 optr[1] = subid - 80;
410 }
411
412 *len = 2;
413 optr += 2;
414
415 while (ctx->pointer < eoc) {
416 if (++(*len) > size) {
417 ctx->error = ASN1_ERR_DEC_BADVALUE;
418 kfree(*oid);
419 *oid = NULL;
420 return 0;
421 }
422
423 if (!asn1_subid_decode(ctx, optr++)) {
424 kfree(*oid);
425 *oid = NULL;
426 return 0;
427 }
428 }
429 return 1;
430}
431
432static int
433compare_oid(unsigned long *oid1, unsigned int oid1len,
434 unsigned long *oid2, unsigned int oid2len)
435{
436 unsigned int i;
437
438 if (oid1len != oid2len)
439 return 0;
440 else {
441 for (i = 0; i < oid1len; i++) {
442 if (oid1[i] != oid2[i])
443 return 0;
444 }
445 return 1;
446 }
447}
448
449 /* BB check for endian conversion issues here */
450
451int
452decode_negTokenInit(unsigned char *security_blob, int length,
453 enum securityEnum *secType)
454{
455 struct asn1_ctx ctx;
456 unsigned char *end;
457 unsigned char *sequence_end;
458 unsigned long *oid = NULL;
459 unsigned int cls, con, tag, oidlen, rc;
460 int use_ntlmssp = FALSE;
461
462 *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
463
464 /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
465
466 asn1_open(&ctx, security_blob, length);
467
468 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
469 cFYI(1, ("Error decoding negTokenInit header "));
470 return 0;
471 } else if ((cls != ASN1_APL) || (con != ASN1_CON)
472 || (tag != ASN1_EOC)) {
473 cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
474 return 0;
475 } else {
476 /* remember to free obj->oid */
477 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
478 if (rc) {
479 if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
480 rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
481 if (rc) {
482 rc = compare_oid(oid, oidlen,
483 SPNEGO_OID,
484 SPNEGO_OID_LEN);
485 kfree(oid);
486 }
487 } else
488 rc = 0;
489 }
490
491 if (!rc) {
492 cFYI(1, ("Error decoding negTokenInit header"));
493 return 0;
494 }
495
496 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
497 cFYI(1, ("Error decoding negTokenInit "));
498 return 0;
499 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
500 || (tag != ASN1_EOC)) {
501 cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
502 cls, con, tag, end, *end));
503 return 0;
504 }
505
506 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
507 cFYI(1, ("Error decoding negTokenInit "));
508 return 0;
509 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
510 || (tag != ASN1_SEQ)) {
511 cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
512 cls, con, tag, end, *end));
513 return 0;
514 }
515
516 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
517 cFYI(1, ("Error decoding 2nd part of negTokenInit "));
518 return 0;
519 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)
520 || (tag != ASN1_EOC)) {
521 cFYI(1,
522 ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
523 cls, con, tag, end, *end));
524 return 0;
525 }
526
527 if (asn1_header_decode
528 (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
529 cFYI(1, ("Error decoding 2nd part of negTokenInit "));
530 return 0;
531 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
532 || (tag != ASN1_SEQ)) {
533 cFYI(1,
534 ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
535 cls, con, tag, end, *end));
536 return 0;
537 }
538
539 while (!asn1_eoc_decode(&ctx, sequence_end)) {
540 rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
541 if (!rc) {
542 cFYI(1,
543 ("Error 1 decoding negTokenInit header exit 2"));
544 return 0;
545 }
546 if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
547 rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
548 if(rc) {
549 cFYI(1,
550 ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
551 oidlen, *oid, *(oid + 1), *(oid + 2),
552 *(oid + 3)));
553 rc = compare_oid(oid, oidlen, NTLMSSP_OID,
554 NTLMSSP_OID_LEN);
555 if(oid)
556 kfree(oid);
557 if (rc)
558 use_ntlmssp = TRUE;
559 }
560 } else {
561 cFYI(1,("This should be an oid what is going on? "));
562 }
563 }
564
565 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
566 cFYI(1,
567 ("Error decoding last part of negTokenInit exit 3"));
568 return 0;
569 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
570 cFYI(1,
571 ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
572 cls, con, tag, end, *end));
573 return 0;
574 }
575 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
576 cFYI(1,
577 ("Error decoding last part of negTokenInit exit 5"));
578 return 0;
579 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
580 || (tag != ASN1_SEQ)) {
581 cFYI(1,
582 ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
583 cls, con, tag, end, *end));
584 }
585
586 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
587 cFYI(1,
588 ("Error decoding last part of negTokenInit exit 7"));
589 return 0;
590 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
591 cFYI(1,
592 ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
593 cls, con, tag, end, *end));
594 return 0;
595 }
596 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
597 cFYI(1,
598 ("Error decoding last part of negTokenInit exit 9"));
599 return 0;
600 } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
601 || (tag != ASN1_GENSTR)) {
602 cFYI(1,
603 ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
604 cls, con, tag, end, *end));
605 return 0;
606 }
607 cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
608 }
609
610 /* if (use_kerberos)
611 *secType = Kerberos
612 else */
613 if (use_ntlmssp) {
614 *secType = NTLMSSP;
615 }
616
617 return 1;
618}
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
new file mode 100644
index 000000000000..db28b561cd4b
--- /dev/null
+++ b/fs/cifs/cifs_debug.c
@@ -0,0 +1,805 @@
1/*
2 * fs/cifs_debug.c
3 *
4 * Copyright (C) International Business Machines Corp., 2000,2003
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
33void
34cifs_dump_mem(char *label, void *data, int length)
35{
36 int i, j;
37 int *intptr = data;
38 char *charptr = data;
39 char buf[10], line[80];
40
41 printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
42 label, length, data);
43 for (i = 0; i < length; i += 16) {
44 line[0] = 0;
45 for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
46 sprintf(buf, " %08x", intptr[i / 4 + j]);
47 strcat(line, buf);
48 }
49 buf[0] = ' ';
50 buf[2] = 0;
51 for (j = 0; (j < 16) && (i + j < length); j++) {
52 buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
53 strcat(line, buf);
54 }
55 printk(KERN_DEBUG "%s\n", line);
56 }
57}
58
59#ifdef CONFIG_PROC_FS
60static int
61cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
62 int count, int *eof, void *data)
63{
64 struct list_head *tmp;
65 struct list_head *tmp1;
66 struct mid_q_entry * mid_entry;
67 struct cifsSesInfo *ses;
68 struct cifsTconInfo *tcon;
69 int i;
70 int length = 0;
71 char * original_buf = buf;
72
73 *beginBuffer = buf + offset;
74
75
76 length =
77 sprintf(buf,
78 "Display Internal CIFS Data Structures for Debugging\n"
79 "---------------------------------------------------\n");
80 buf += length;
81
82 length = sprintf(buf, "Servers:\n");
83 buf += length;
84
85 i = 0;
86 read_lock(&GlobalSMBSeslock);
87 list_for_each(tmp, &GlobalSMBSessionList) {
88 i++;
89 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
90 length =
91 sprintf(buf,
92 "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
93 i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
94 ses->serverOS, ses->serverNOS, ses->capabilities,ses->status);
95 buf += length;
96 if(ses->server) {
97 buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
98 ses->server->tcpStatus,
99 atomic_read(&ses->server->socketUseCount),
100 ses->server->secMode,
101 atomic_read(&ses->server->inFlight));
102
103 length = sprintf(buf, "\nMIDs: \n");
104 buf += length;
105
106 spin_lock(&GlobalMid_Lock);
107 list_for_each(tmp1, &ses->server->pending_mid_q) {
108 mid_entry = list_entry(tmp1, struct
109 mid_q_entry,
110 qhead);
111 if(mid_entry) {
112 length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid);
113 buf += length;
114 }
115 }
116 spin_unlock(&GlobalMid_Lock);
117 }
118
119 }
120 read_unlock(&GlobalSMBSeslock);
121 sprintf(buf, "\n");
122 buf++;
123
124 length = sprintf(buf, "\nShares:\n");
125 buf += length;
126
127 i = 0;
128 read_lock(&GlobalSMBSeslock);
129 list_for_each(tmp, &GlobalTreeConnectionList) {
130 __u32 dev_type;
131 i++;
132 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
133 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
134 length =
135 sprintf(buf,
136 "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
137 i, tcon->treeName,
138 atomic_read(&tcon->useCount),
139 tcon->nativeFileSystem,
140 le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
141 le32_to_cpu(tcon->fsAttrInfo.Attributes),
142 le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
143 tcon->tidStatus);
144 buf += length;
145 if (dev_type == FILE_DEVICE_DISK)
146 length = sprintf(buf, " type: DISK ");
147 else if (dev_type == FILE_DEVICE_CD_ROM)
148 length = sprintf(buf, " type: CDROM ");
149 else
150 length =
151 sprintf(buf, " type: %d ", dev_type);
152 buf += length;
153 if(tcon->tidStatus == CifsNeedReconnect) {
154 buf += sprintf(buf, "\tDISCONNECTED ");
155 length += 14;
156 }
157 }
158 read_unlock(&GlobalSMBSeslock);
159
160 length = sprintf(buf, "\n");
161 buf += length;
162
163 /* BB add code to dump additional info such as TCP session info now */
164 /* Now calculate total size of returned data */
165 length = buf - original_buf;
166
167 if(offset + count >= length)
168 *eof = 1;
169 if(length < offset) {
170 *eof = 1;
171 return 0;
172 } else {
173 length = length - offset;
174 }
175 if (length > count)
176 length = count;
177
178 return length;
179}
180
181#ifdef CONFIG_CIFS_STATS
182static int
183cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
184 int count, int *eof, void *data)
185{
186 int item_length,i,length;
187 struct list_head *tmp;
188 struct cifsTconInfo *tcon;
189
190 *beginBuffer = buf + offset;
191
192 length = sprintf(buf,
193 "Resources in use\nCIFS Session: %d\n",
194 sesInfoAllocCount.counter);
195 buf += length;
196 item_length =
197 sprintf(buf,"Share (unique mount targets): %d\n",
198 tconInfoAllocCount.counter);
199 length += item_length;
200 buf += item_length;
201 item_length =
202 sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
203 bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter);
204 length += item_length;
205 buf += item_length;
206 item_length =
207 sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
208 smBufAllocCount.counter,cifs_min_small);
209 length += item_length;
210 buf += item_length;
211 item_length =
212 sprintf(buf,"Operations (MIDs): %d\n",
213 midCount.counter);
214 length += item_length;
215 buf += item_length;
216 item_length = sprintf(buf,
217 "\n%d session %d share reconnects\n",
218 tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
219 length += item_length;
220 buf += item_length;
221
222 item_length = sprintf(buf,
223 "Total vfs operations: %d maximum at one time: %d\n",
224 GlobalCurrentXid,GlobalMaxActiveXid);
225 length += item_length;
226 buf += item_length;
227
228 i = 0;
229 read_lock(&GlobalSMBSeslock);
230 list_for_each(tmp, &GlobalTreeConnectionList) {
231 i++;
232 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
233 item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
234 buf += item_length;
235 length += item_length;
236 if(tcon->tidStatus == CifsNeedReconnect) {
237 buf += sprintf(buf, "\tDISCONNECTED ");
238 length += 14;
239 }
240 item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
241 atomic_read(&tcon->num_smbs_sent),
242 atomic_read(&tcon->num_oplock_brks));
243 buf += item_length;
244 length += item_length;
245 item_length = sprintf(buf,"\nReads: %d Bytes %lld",
246 atomic_read(&tcon->num_reads),
247 (long long)(tcon->bytes_read));
248 buf += item_length;
249 length += item_length;
250 item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
251 atomic_read(&tcon->num_writes),
252 (long long)(tcon->bytes_written));
253 buf += item_length;
254 length += item_length;
255 item_length = sprintf(buf,
256 "\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
257 atomic_read(&tcon->num_opens),
258 atomic_read(&tcon->num_deletes),
259 atomic_read(&tcon->num_mkdirs),
260 atomic_read(&tcon->num_rmdirs));
261 buf += item_length;
262 length += item_length;
263 item_length = sprintf(buf,
264 "\nRenames: %d T2 Renames %d",
265 atomic_read(&tcon->num_renames),
266 atomic_read(&tcon->num_t2renames));
267 buf += item_length;
268 length += item_length;
269 }
270 read_unlock(&GlobalSMBSeslock);
271
272 buf += sprintf(buf,"\n");
273 length++;
274
275 if(offset + count >= length)
276 *eof = 1;
277 if(length < offset) {
278 *eof = 1;
279 return 0;
280 } else {
281 length = length - offset;
282 }
283 if (length > count)
284 length = count;
285
286 return length;
287}
288#endif
289
290static struct proc_dir_entry *proc_fs_cifs;
291read_proc_t cifs_txanchor_read;
292static read_proc_t cifsFYI_read;
293static write_proc_t cifsFYI_write;
294static read_proc_t oplockEnabled_read;
295static write_proc_t oplockEnabled_write;
296static read_proc_t lookupFlag_read;
297static write_proc_t lookupFlag_write;
298static read_proc_t traceSMB_read;
299static write_proc_t traceSMB_write;
300static read_proc_t multiuser_mount_read;
301static write_proc_t multiuser_mount_write;
302static read_proc_t extended_security_read;
303static write_proc_t extended_security_write;
304static read_proc_t ntlmv2_enabled_read;
305static write_proc_t ntlmv2_enabled_write;
306static read_proc_t packet_signing_enabled_read;
307static write_proc_t packet_signing_enabled_write;
308static read_proc_t quotaEnabled_read;
309static write_proc_t quotaEnabled_write;
310static read_proc_t linuxExtensionsEnabled_read;
311static write_proc_t linuxExtensionsEnabled_write;
312
313void
314cifs_proc_init(void)
315{
316 struct proc_dir_entry *pde;
317
318 proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
319 if (proc_fs_cifs == NULL)
320 return;
321
322 proc_fs_cifs->owner = THIS_MODULE;
323 create_proc_read_entry("DebugData", 0, proc_fs_cifs,
324 cifs_debug_data_read, NULL);
325
326#ifdef CONFIG_CIFS_STATS
327 create_proc_read_entry("Stats", 0, proc_fs_cifs,
328 cifs_stats_read, NULL);
329#endif
330 pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
331 cifsFYI_read, NULL);
332 if (pde)
333 pde->write_proc = cifsFYI_write;
334
335 pde =
336 create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
337 traceSMB_read, NULL);
338 if (pde)
339 pde->write_proc = traceSMB_write;
340
341 pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
342 oplockEnabled_read, NULL);
343 if (pde)
344 pde->write_proc = oplockEnabled_write;
345
346 pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs,
347 quotaEnabled_read, NULL);
348 if (pde)
349 pde->write_proc = quotaEnabled_write;
350
351 pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
352 linuxExtensionsEnabled_read, NULL);
353 if (pde)
354 pde->write_proc = linuxExtensionsEnabled_write;
355
356 pde =
357 create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
358 multiuser_mount_read, NULL);
359 if (pde)
360 pde->write_proc = multiuser_mount_write;
361
362 pde =
363 create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
364 extended_security_read, NULL);
365 if (pde)
366 pde->write_proc = extended_security_write;
367
368 pde =
369 create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
370 lookupFlag_read, NULL);
371 if (pde)
372 pde->write_proc = lookupFlag_write;
373
374 pde =
375 create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
376 ntlmv2_enabled_read, NULL);
377 if (pde)
378 pde->write_proc = ntlmv2_enabled_write;
379
380 pde =
381 create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
382 packet_signing_enabled_read, NULL);
383 if (pde)
384 pde->write_proc = packet_signing_enabled_write;
385}
386
387void
388cifs_proc_clean(void)
389{
390 if (proc_fs_cifs == NULL)
391 return;
392
393 remove_proc_entry("DebugData", proc_fs_cifs);
394 remove_proc_entry("cifsFYI", proc_fs_cifs);
395 remove_proc_entry("traceSMB", proc_fs_cifs);
396#ifdef CONFIG_CIFS_STATS
397 remove_proc_entry("Stats", proc_fs_cifs);
398#endif
399 remove_proc_entry("MultiuserMount", proc_fs_cifs);
400 remove_proc_entry("OplockEnabled", proc_fs_cifs);
401 remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
402 remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
403 remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
404 remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
405 remove_proc_entry("ReenableOldCifsReaddirCode",proc_fs_cifs);
406 remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
407 remove_proc_entry("cifs", proc_root_fs);
408}
409
410static int
411cifsFYI_read(char *page, char **start, off_t off, int count,
412 int *eof, void *data)
413{
414 int len;
415
416 len = sprintf(page, "%d\n", cifsFYI);
417
418 len -= off;
419 *start = page + off;
420
421 if (len > count)
422 len = count;
423 else
424 *eof = 1;
425
426 if (len < 0)
427 len = 0;
428
429 return len;
430}
431static int
432cifsFYI_write(struct file *file, const char __user *buffer,
433 unsigned long count, void *data)
434{
435 char c;
436 int rc;
437
438 rc = get_user(c, buffer);
439 if (rc)
440 return rc;
441 if (c == '0' || c == 'n' || c == 'N')
442 cifsFYI = 0;
443 else if (c == '1' || c == 'y' || c == 'Y')
444 cifsFYI = 1;
445
446 return count;
447}
448
449static int
450oplockEnabled_read(char *page, char **start, off_t off,
451 int count, int *eof, void *data)
452{
453 int len;
454
455 len = sprintf(page, "%d\n", oplockEnabled);
456
457 len -= off;
458 *start = page + off;
459
460 if (len > count)
461 len = count;
462 else
463 *eof = 1;
464
465 if (len < 0)
466 len = 0;
467
468 return len;
469}
470static int
471oplockEnabled_write(struct file *file, const char __user *buffer,
472 unsigned long count, void *data)
473{
474 char c;
475 int rc;
476
477 rc = get_user(c, buffer);
478 if (rc)
479 return rc;
480 if (c == '0' || c == 'n' || c == 'N')
481 oplockEnabled = 0;
482 else if (c == '1' || c == 'y' || c == 'Y')
483 oplockEnabled = 1;
484
485 return count;
486}
487
488static int
489quotaEnabled_read(char *page, char **start, off_t off,
490 int count, int *eof, void *data)
491{
492 int len;
493
494 len = sprintf(page, "%d\n", experimEnabled);
495/* could also check if quotas are enabled in kernel
496 as a whole first */
497 len -= off;
498 *start = page + off;
499
500 if (len > count)
501 len = count;
502 else
503 *eof = 1;
504
505 if (len < 0)
506 len = 0;
507
508 return len;
509}
510static int
511quotaEnabled_write(struct file *file, const char __user *buffer,
512 unsigned long count, void *data)
513{
514 char c;
515 int rc;
516
517 rc = get_user(c, buffer);
518 if (rc)
519 return rc;
520 if (c == '0' || c == 'n' || c == 'N')
521 experimEnabled = 0;
522 else if (c == '1' || c == 'y' || c == 'Y')
523 experimEnabled = 1;
524
525 return count;
526}
527
528static int
529linuxExtensionsEnabled_read(char *page, char **start, off_t off,
530 int count, int *eof, void *data)
531{
532 int len;
533
534 len = sprintf(page, "%d\n", linuxExtEnabled);
535/* could also check if quotas are enabled in kernel
536 as a whole first */
537 len -= off;
538 *start = page + off;
539
540 if (len > count)
541 len = count;
542 else
543 *eof = 1;
544
545 if (len < 0)
546 len = 0;
547
548 return len;
549}
550static int
551linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
552 unsigned long count, void *data)
553{
554 char c;
555 int rc;
556
557 rc = get_user(c, buffer);
558 if (rc)
559 return rc;
560 if (c == '0' || c == 'n' || c == 'N')
561 linuxExtEnabled = 0;
562 else if (c == '1' || c == 'y' || c == 'Y')
563 linuxExtEnabled = 1;
564
565 return count;
566}
567
568
569static int
570lookupFlag_read(char *page, char **start, off_t off,
571 int count, int *eof, void *data)
572{
573 int len;
574
575 len = sprintf(page, "%d\n", lookupCacheEnabled);
576
577 len -= off;
578 *start = page + off;
579
580 if (len > count)
581 len = count;
582 else
583 *eof = 1;
584
585 if (len < 0)
586 len = 0;
587
588 return len;
589}
590static int
591lookupFlag_write(struct file *file, const char __user *buffer,
592 unsigned long count, void *data)
593{
594 char c;
595 int rc;
596
597 rc = get_user(c, buffer);
598 if (rc)
599 return rc;
600 if (c == '0' || c == 'n' || c == 'N')
601 lookupCacheEnabled = 0;
602 else if (c == '1' || c == 'y' || c == 'Y')
603 lookupCacheEnabled = 1;
604
605 return count;
606}
607static int
608traceSMB_read(char *page, char **start, off_t off, int count,
609 int *eof, void *data)
610{
611 int len;
612
613 len = sprintf(page, "%d\n", traceSMB);
614
615 len -= off;
616 *start = page + off;
617
618 if (len > count)
619 len = count;
620 else
621 *eof = 1;
622
623 if (len < 0)
624 len = 0;
625
626 return len;
627}
628static int
629traceSMB_write(struct file *file, const char __user *buffer,
630 unsigned long count, void *data)
631{
632 char c;
633 int rc;
634
635 rc = get_user(c, buffer);
636 if (rc)
637 return rc;
638 if (c == '0' || c == 'n' || c == 'N')
639 traceSMB = 0;
640 else if (c == '1' || c == 'y' || c == 'Y')
641 traceSMB = 1;
642
643 return count;
644}
645
646static int
647multiuser_mount_read(char *page, char **start, off_t off,
648 int count, int *eof, void *data)
649{
650 int len;
651
652 len = sprintf(page, "%d\n", multiuser_mount);
653
654 len -= off;
655 *start = page + off;
656
657 if (len > count)
658 len = count;
659 else
660 *eof = 1;
661
662 if (len < 0)
663 len = 0;
664
665 return len;
666}
667static int
668multiuser_mount_write(struct file *file, const char __user *buffer,
669 unsigned long count, void *data)
670{
671 char c;
672 int rc;
673
674 rc = get_user(c, buffer);
675 if (rc)
676 return rc;
677 if (c == '0' || c == 'n' || c == 'N')
678 multiuser_mount = 0;
679 else if (c == '1' || c == 'y' || c == 'Y')
680 multiuser_mount = 1;
681
682 return count;
683}
684
685static int
686extended_security_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", extended_security);
692
693 len -= off;
694 *start = page + off;
695
696 if (len > count)
697 len = count;
698 else
699 *eof = 1;
700
701 if (len < 0)
702 len = 0;
703
704 return len;
705}
706static int
707extended_security_write(struct file *file, const char __user *buffer,
708 unsigned long count, void *data)
709{
710 char c;
711 int rc;
712
713 rc = get_user(c, buffer);
714 if (rc)
715 return rc;
716 if (c == '0' || c == 'n' || c == 'N')
717 extended_security = 0;
718 else if (c == '1' || c == 'y' || c == 'Y')
719 extended_security = 1;
720
721 return count;
722}
723
724static int
725ntlmv2_enabled_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", ntlmv2_support);
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
746ntlmv2_enabled_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 ntlmv2_support = 0;
757 else if (c == '1' || c == 'y' || c == 'Y')
758 ntlmv2_support = 1;
759
760 return count;
761}
762
763static int
764packet_signing_enabled_read(char *page, char **start, off_t off,
765 int count, int *eof, void *data)
766{
767 int len;
768
769 len = sprintf(page, "%d\n", sign_CIFS_PDUs);
770
771 len -= off;
772 *start = page + off;
773
774 if (len > count)
775 len = count;
776 else
777 *eof = 1;
778
779 if (len < 0)
780 len = 0;
781
782 return len;
783}
784static int
785packet_signing_enabled_write(struct file *file, const char __user *buffer,
786 unsigned long count, void *data)
787{
788 char c;
789 int rc;
790
791 rc = get_user(c, buffer);
792 if (rc)
793 return rc;
794 if (c == '0' || c == 'n' || c == 'N')
795 sign_CIFS_PDUs = 0;
796 else if (c == '1' || c == 'y' || c == 'Y')
797 sign_CIFS_PDUs = 1;
798 else if (c == '2')
799 sign_CIFS_PDUs = 2;
800
801 return count;
802}
803
804
805#endif
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
new file mode 100644
index 000000000000..bf24d2828f68
--- /dev/null
+++ b/fs/cifs/cifs_debug.h
@@ -0,0 +1,66 @@
1/*
2 *
3 * Copyright (c) International Business Machines Corp., 2000,2002
4 * Modified by Steve French (sfrench@us.ibm.com)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
14 * the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20*/
21#define CIFS_DEBUG /* BB temporary */
22
23#ifndef _H_CIFS_DEBUG
24#define _H_CIFS_DEBUG
25
26void cifs_dump_mem(char *label, void *data, int length);
27extern int traceSMB; /* flag which enables the function below */
28void dump_smb(struct smb_hdr *, int);
29
30/*
31 * debug ON
32 * --------
33 */
34#ifdef CIFS_DEBUG
35
36
37/* information message: e.g., configuration, major event */
38extern int cifsFYI;
39#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
40
41#define cFYI(button,prspec) if (button) cifsfyi prspec
42
43#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
44
45/* debug event message: */
46extern int cifsERROR;
47
48#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
49
50/* error event message: e.g., i/o error */
51#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
52
53#define cERROR(button, prspec) if (button) cifserror prspec
54
55/*
56 * debug OFF
57 * ---------
58 */
59#else /* _CIFS_DEBUG */
60#define cERROR(button,prspec)
61#define cEVENT(format,arg...)
62#define cFYI(button, prspec)
63#define cifserror(format,arg...)
64#endif /* _CIFS_DEBUG */
65
66#endif /* _H_CIFS_DEBUG */
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
new file mode 100644
index 000000000000..77da902d8f32
--- /dev/null
+++ b/fs/cifs/cifs_fs_sb.h
@@ -0,0 +1,39 @@
1/*
2 * fs/cifs/cifs_fs_sb.h
3 *
4 * Copyright (c) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 */
18#ifndef _CIFS_FS_SB_H
19#define _CIFS_FS_SB_H
20
21#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
22#define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */
23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
24#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
25#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
26
27struct cifs_sb_info {
28 struct cifsTconInfo *tcon; /* primary mount */
29 struct list_head nested_tcon_q;
30 struct nls_table *local_nls;
31 unsigned int rsize;
32 unsigned int wsize;
33 uid_t mnt_uid;
34 gid_t mnt_gid;
35 mode_t mnt_file_mode;
36 mode_t mnt_dir_mode;
37 int mnt_cifs_flags;
38};
39#endif /* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
new file mode 100644
index 000000000000..a17adf4cb9ba
--- /dev/null
+++ b/fs/cifs/cifs_unicode.c
@@ -0,0 +1,87 @@
1/*
2 * fs/cifs/cifs_unicode.c
3 *
4 * Copyright (c) International Business Machines Corp., 2000,2002
5 * Modified by Steve French (sfrench@us.ibm.com)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
22#include "cifs_unicode.h"
23#include "cifs_uniupr.h"
24#include "cifspdu.h"
25#include "cifs_debug.h"
26
27/*
28 * NAME: cifs_strfromUCS()
29 *
30 * FUNCTION: Convert little-endian unicode string to character string
31 *
32 */
33int
34cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
35 int len, const struct nls_table *codepage)
36{
37 int i;
38 int outlen = 0;
39
40 for (i = 0; (i < len) && from[i]; i++) {
41 int charlen;
42 /* 2.4.0 kernel or greater */
43 charlen =
44 codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
45 NLS_MAX_CHARSET_SIZE);
46 if (charlen > 0) {
47 outlen += charlen;
48 } else {
49 to[outlen++] = '?';
50 }
51 }
52 to[outlen] = 0;
53 return outlen;
54}
55
56/*
57 * NAME: cifs_strtoUCS()
58 *
59 * FUNCTION: Convert character string to unicode string
60 *
61 */
62int
63cifs_strtoUCS(wchar_t * to, const char *from, int len,
64 const struct nls_table *codepage)
65{
66 int charlen;
67 int i;
68
69 for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
70
71 /* works for 2.4.0 kernel or later */
72 charlen = codepage->char2uni(from, len, &to[i]);
73 if (charlen < 1) {
74 cERROR(1,
75 ("cifs_strtoUCS: char2uni returned %d",
76 charlen));
77 to[i] = cpu_to_le16(0x003f); /* a question mark */
78 charlen = 1;
79 }
80 to[i] = cpu_to_le16(to[i]);
81
82 }
83
84 to[i] = 0;
85 return i;
86}
87
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
new file mode 100644
index 000000000000..da8dde965275
--- /dev/null
+++ b/fs/cifs/cifs_unicode.h
@@ -0,0 +1,353 @@
1/*
2 * cifs_unicode: Unicode kernel case support
3 *
4 * Function:
5 * Convert a unicode character to upper or lower case using
6 * compressed tables.
7 *
8 * Copyright (c) International Business Machines Corp., 2000,2002
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 *
25 * Notes:
26 * These APIs are based on the C library functions. The semantics
27 * should match the C functions but with expanded size operands.
28 *
29 * The upper/lower functions are based on a table created by mkupr.
30 * This is a compressed table of upper and lower case conversion.
31 *
32 */
33
34#include <asm/byteorder.h>
35#include <linux/types.h>
36#include <linux/nls.h>
37
38#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
39
40/* Just define what we want from uniupr.h. We don't want to define the tables
41 * in each source file.
42 */
43#ifndef UNICASERANGE_DEFINED
44struct UniCaseRange {
45 wchar_t start;
46 wchar_t end;
47 signed char *table;
48};
49#endif /* UNICASERANGE_DEFINED */
50
51#ifndef UNIUPR_NOUPPER
52extern signed char CifsUniUpperTable[512];
53extern const struct UniCaseRange CifsUniUpperRange[];
54#endif /* UNIUPR_NOUPPER */
55
56#ifndef UNIUPR_NOLOWER
57extern signed char UniLowerTable[512];
58extern struct UniCaseRange UniLowerRange[];
59#endif /* UNIUPR_NOLOWER */
60
61#ifdef __KERNEL__
62int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
63int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
64#endif
65
66/*
67 * UniStrcat: Concatenate the second string to the first
68 *
69 * Returns:
70 * Address of the first string
71 */
72static inline wchar_t *
73UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
74{
75 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */
76
77 while (*ucs1++) ; /* To end of first string */
78 ucs1--; /* Return to the null */
79 while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */
80 return anchor;
81}
82
83/*
84 * UniStrchr: Find a character in a string
85 *
86 * Returns:
87 * Address of first occurrence of character in string
88 * or NULL if the character is not in the string
89 */
90static inline wchar_t *
91UniStrchr(const wchar_t * ucs, wchar_t uc)
92{
93 while ((*ucs != uc) && *ucs)
94 ucs++;
95
96 if (*ucs == uc)
97 return (wchar_t *) ucs;
98 return NULL;
99}
100
101/*
102 * UniStrcmp: Compare two strings
103 *
104 * Returns:
105 * < 0: First string is less than second
106 * = 0: Strings are equal
107 * > 0: First string is greater than second
108 */
109static inline int
110UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
111{
112 while ((*ucs1 == *ucs2) && *ucs1) {
113 ucs1++;
114 ucs2++;
115 }
116 return (int) *ucs1 - (int) *ucs2;
117}
118
119/*
120 * UniStrcpy: Copy a string
121 */
122static inline wchar_t *
123UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
124{
125 wchar_t *anchor = ucs1; /* save the start of result string */
126
127 while ((*ucs1++ = *ucs2++)) ;
128 return anchor;
129}
130
131/*
132 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes)
133 */
134static inline size_t
135UniStrlen(const wchar_t * ucs1)
136{
137 int i = 0;
138
139 while (*ucs1++)
140 i++;
141 return i;
142}
143
144/*
145 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
146 */
147static inline size_t
148UniStrnlen(const wchar_t * ucs1, int maxlen)
149{
150 int i = 0;
151
152 while (*ucs1++) {
153 i++;
154 if (i >= maxlen)
155 break;
156 }
157 return i;
158}
159
160/*
161 * UniStrncat: Concatenate length limited string
162 */
163static inline wchar_t *
164UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
165{
166 wchar_t *anchor = ucs1; /* save pointer to string 1 */
167
168 while (*ucs1++) ;
169 ucs1--; /* point to null terminator of s1 */
170 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */
171 ucs1++;
172 ucs2++;
173 }
174 *ucs1 = 0; /* Null terminate the result */
175 return (anchor);
176}
177
178/*
179 * UniStrncmp: Compare length limited string
180 */
181static inline int
182UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
183{
184 if (!n)
185 return 0; /* Null strings are equal */
186 while ((*ucs1 == *ucs2) && *ucs1 && --n) {
187 ucs1++;
188 ucs2++;
189 }
190 return (int) *ucs1 - (int) *ucs2;
191}
192
193/*
194 * UniStrncmp_le: Compare length limited string - native to little-endian
195 */
196static inline int
197UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
198{
199 if (!n)
200 return 0; /* Null strings are equal */
201 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
202 ucs1++;
203 ucs2++;
204 }
205 return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
206}
207
208/*
209 * UniStrncpy: Copy length limited string with pad
210 */
211static inline wchar_t *
212UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
213{
214 wchar_t *anchor = ucs1;
215
216 while (n-- && *ucs2) /* Copy the strings */
217 *ucs1++ = *ucs2++;
218
219 n++;
220 while (n--) /* Pad with nulls */
221 *ucs1++ = 0;
222 return anchor;
223}
224
225/*
226 * UniStrncpy_le: Copy length limited string with pad to little-endian
227 */
228static inline wchar_t *
229UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
230{
231 wchar_t *anchor = ucs1;
232
233 while (n-- && *ucs2) /* Copy the strings */
234 *ucs1++ = __le16_to_cpu(*ucs2++);
235
236 n++;
237 while (n--) /* Pad with nulls */
238 *ucs1++ = 0;
239 return anchor;
240}
241
242/*
243 * UniStrstr: Find a string in a string
244 *
245 * Returns:
246 * Address of first match found
247 * NULL if no matching string is found
248 */
249static inline wchar_t *
250UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
251{
252 const wchar_t *anchor1 = ucs1;
253 const wchar_t *anchor2 = ucs2;
254
255 while (*ucs1) {
256 if (*ucs1 == *ucs2) { /* Partial match found */
257 ucs1++;
258 ucs2++;
259 } else {
260 if (!*ucs2) /* Match found */
261 return (wchar_t *) anchor1;
262 ucs1 = ++anchor1; /* No match */
263 ucs2 = anchor2;
264 }
265 }
266
267 if (!*ucs2) /* Both end together */
268 return (wchar_t *) anchor1; /* Match found */
269 return NULL; /* No match */
270}
271
272#ifndef UNIUPR_NOUPPER
273/*
274 * UniToupper: Convert a unicode character to upper case
275 */
276static inline wchar_t
277UniToupper(register wchar_t uc)
278{
279 register const struct UniCaseRange *rp;
280
281 if (uc < sizeof (CifsUniUpperTable)) { /* Latin characters */
282 return uc + CifsUniUpperTable[uc]; /* Use base tables */
283 } else {
284 rp = CifsUniUpperRange; /* Use range tables */
285 while (rp->start) {
286 if (uc < rp->start) /* Before start of range */
287 return uc; /* Uppercase = input */
288 if (uc <= rp->end) /* In range */
289 return uc + rp->table[uc - rp->start];
290 rp++; /* Try next range */
291 }
292 }
293 return uc; /* Past last range */
294}
295
296/*
297 * UniStrupr: Upper case a unicode string
298 */
299static inline wchar_t *
300UniStrupr(register wchar_t * upin)
301{
302 register wchar_t *up;
303
304 up = upin;
305 while (*up) { /* For all characters */
306 *up = UniToupper(*up);
307 up++;
308 }
309 return upin; /* Return input pointer */
310}
311#endif /* UNIUPR_NOUPPER */
312
313#ifndef UNIUPR_NOLOWER
314/*
315 * UniTolower: Convert a unicode character to lower case
316 */
317static inline wchar_t
318UniTolower(wchar_t uc)
319{
320 register struct UniCaseRange *rp;
321
322 if (uc < sizeof (UniLowerTable)) { /* Latin characters */
323 return uc + UniLowerTable[uc]; /* Use base tables */
324 } else {
325 rp = UniLowerRange; /* Use range tables */
326 while (rp->start) {
327 if (uc < rp->start) /* Before start of range */
328 return uc; /* Uppercase = input */
329 if (uc <= rp->end) /* In range */
330 return uc + rp->table[uc - rp->start];
331 rp++; /* Try next range */
332 }
333 }
334 return uc; /* Past last range */
335}
336
337/*
338 * UniStrlwr: Lower case a unicode string
339 */
340static inline wchar_t *
341UniStrlwr(register wchar_t * upin)
342{
343 register wchar_t *up;
344
345 up = upin;
346 while (*up) { /* For all characters */
347 *up = UniTolower(*up);
348 up++;
349 }
350 return upin; /* Return input pointer */
351}
352
353#endif
diff --git a/fs/cifs/cifs_uniupr.h b/fs/cifs/cifs_uniupr.h
new file mode 100644
index 000000000000..decd138f14d4
--- /dev/null
+++ b/fs/cifs/cifs_uniupr.h
@@ -0,0 +1,253 @@
1/*
2 * Copyright (c) International Business Machines Corp., 2000,2002
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * uniupr.h - Unicode compressed case ranges
19 *
20*/
21
22#ifndef UNIUPR_NOUPPER
23/*
24 * Latin upper case
25 */
26signed char CifsUniUpperTable[512] = {
27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */
33 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */
34 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */
41 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */
42 -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */
43 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */
44 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */
45 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */
46 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */
47 -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */
48 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */
49 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */
50 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */
51 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */
52 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */
53 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */
54 -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */
55 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */
56 -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */
57 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */
58 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */
59};
60
61/* Upper case range - Greek */
62static signed char UniCaseRangeU03a0[47] = {
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */
64 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */
65 -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
66 -63, -63,
67};
68
69/* Upper case range - Cyrillic */
70static signed char UniCaseRangeU0430[48] = {
71 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */
72 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */
73 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */
74};
75
76/* Upper case range - Extended cyrillic */
77static signed char UniCaseRangeU0490[61] = {
78 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */
79 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */
80 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */
81 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
82};
83
84/* Upper case range - Extended latin and greek */
85static signed char UniCaseRangeU1e00[509] = {
86 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */
87 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */
88 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */
89 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */
90 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */
91 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */
92 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */
93 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */
94 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */
95 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */
96 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */
97 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */
98 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */
99 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */
100 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */
101 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
102 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */
103 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */
104 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */
105 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */
106 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */
107 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */
108 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */
109 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */
110 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */
111 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */
112 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */
113 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */
114 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */
115 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */
116 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */
117 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118};
119
120/* Upper case range - Wide latin */
121static signed char UniCaseRangeUff40[27] = {
122 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */
123 -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
124};
125
126/*
127 * Upper Case Range
128 */
129const struct UniCaseRange CifsUniUpperRange[] = {
130 {0x03a0, 0x03ce, UniCaseRangeU03a0},
131 {0x0430, 0x045f, UniCaseRangeU0430},
132 {0x0490, 0x04cc, UniCaseRangeU0490},
133 {0x1e00, 0x1ffc, UniCaseRangeU1e00},
134 {0xff40, 0xff5a, UniCaseRangeUff40},
135 {0}
136};
137#endif
138
139#ifndef UNIUPR_NOLOWER
140/*
141 * Latin lower case
142 */
143static signed char CifsUniLowerTable[512] = {
144 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */
145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */
147 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */
148 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 040-04f */
149 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, /* 050-05f */
150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 060-06f */
151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 070-07f */
152 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */
153 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */
155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */
156 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 0c0-0cf */
157 32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0, /* 0d0-0df */
158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0e0-0ef */
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0f0-0ff */
160 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 100-10f */
161 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 110-11f */
162 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 120-12f */
163 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* 130-13f */
164 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, /* 140-14f */
165 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 150-15f */
166 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 160-16f */
167 1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0, /* 170-17f */
168 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0, /* 180-18f */
169 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 190-19f */
170 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, /* 1a0-1af */
171 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, /* 1b0-1bf */
172 0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, /* 1c0-1cf */
173 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, /* 1d0-1df */
174 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e0-1ef */
175 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1f0-1ff */
176};
177
178/* Lower case range - Greek */
179static signed char UniCaseRangeL0380[44] = {
180 0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63, /* 380-38f */
181 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 390-39f */
182 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
183};
184
185/* Lower case range - Cyrillic */
186static signed char UniCaseRangeL0400[48] = {
187 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80, /* 400-40f */
188 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 410-41f */
189 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* 420-42f */
190};
191
192/* Lower case range - Extended cyrillic */
193static signed char UniCaseRangeL0490[60] = {
194 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 490-49f */
195 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4a0-4af */
196 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 4b0-4bf */
197 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
198};
199
200/* Lower case range - Extended latin and greek */
201static signed char UniCaseRangeL1e00[504] = {
202 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e00-1e0f */
203 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e10-1e1f */
204 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e20-1e2f */
205 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e30-1e3f */
206 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e40-1e4f */
207 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e50-1e5f */
208 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e60-1e6f */
209 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e70-1e7f */
210 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1e80-1e8f */
211 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 1e90-1e9f */
212 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ea0-1eaf */
213 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1eb0-1ebf */
214 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ec0-1ecf */
215 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ed0-1edf */
216 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, /* 1ee0-1eef */
217 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */
218 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f00-1f0f */
219 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f10-1f1f */
220 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f20-1f2f */
221 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f30-1f3f */
222 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0, /* 1f40-1f4f */
223 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8, /* 1f50-1f5f */
224 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f60-1f6f */
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f70-1f7f */
226 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f80-1f8f */
227 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1f90-1f9f */
228 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8, /* 1fa0-1faf */
229 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0, /* 1fb0-1fbf */
230 0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0, /* 1fc0-1fcf */
231 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0, /* 1fd0-1fdf */
232 0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0, /* 1fe0-1fef */
233 0, 0, 0, 0, 0, 0, 0, 0,
234};
235
236/* Lower case range - Wide latin */
237static signed char UniCaseRangeLff20[27] = {
238 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, /* ff20-ff2f */
239 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
240};
241
242/*
243 * Lower Case Range
244 */
245const static struct UniCaseRange CifsUniLowerRange[] = {
246 0x0380, 0x03ab, UniCaseRangeL0380,
247 0x0400, 0x042f, UniCaseRangeL0400,
248 0x0490, 0x04cb, UniCaseRangeL0490,
249 0x1e00, 0x1ff7, UniCaseRangeL1e00,
250 0xff20, 0xff3a, UniCaseRangeLff20,
251 0, 0, 0
252};
253#endif
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
new file mode 100644
index 000000000000..78829e7d8cd0
--- /dev/null
+++ b/fs/cifs/cifsencrypt.c
@@ -0,0 +1,209 @@
1/*
2 * fs/cifs/cifsencrypt.c
3 *
4 * Copyright (C) International Business Machines Corp., 2003
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/fs.h>
23#include "cifspdu.h"
24#include "cifsglob.h"
25#include "cifs_debug.h"
26#include "md5.h"
27#include "cifs_unicode.h"
28#include "cifsproto.h"
29
30/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
31/* the 16 byte signature must be allocated by the caller */
32/* Note we only use the 1st eight bytes */
33/* Note that the smb header signature field on input contains the
34 sequence number before this function is called */
35
36extern void mdfour(unsigned char *out, unsigned char *in, int n);
37extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
38
39static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
40{
41 struct MD5Context context;
42
43 if((cifs_pdu == NULL) || (signature == NULL))
44 return -EINVAL;
45
46 MD5Init(&context);
47 MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
48 MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
49 MD5Final(signature,&context);
50 return 0;
51}
52
53int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
54 __u32 * pexpected_response_sequence_number)
55{
56 int rc = 0;
57 char smb_signature[20];
58
59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
60 /* BB remember to add code to save expected sequence number in midQ entry BB */
61
62 if((cifs_pdu == NULL) || (ses == NULL))
63 return -EINVAL;
64
65 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
66 return rc;
67
68 spin_lock(&GlobalMid_Lock);
69 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
70 cifs_pdu->Signature.Sequence.Reserved = 0;
71
72 *pexpected_response_sequence_number = ses->sequence_number++;
73 ses->sequence_number++;
74 spin_unlock(&GlobalMid_Lock);
75
76 rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
77 if(rc)
78 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
79 else
80 memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
81
82 return rc;
83}
84
85int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
86 __u32 expected_sequence_number)
87{
88 unsigned int rc;
89 char server_response_sig[8];
90 char what_we_think_sig_should_be[20];
91
92 if((cifs_pdu == NULL) || (mac_key == NULL))
93 return -EINVAL;
94
95 if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
96 return 0;
97
98 if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
99 struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
100 if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
101 return 0;
102 }
103
104 /* BB what if signatures are supposed to be on for session but server does not
105 send one? BB */
106
107 /* Do not need to verify session setups with signature "BSRSPYL " */
108 if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
109 cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
110
111 /* save off the origiginal signature so we can modify the smb and check
112 its signature against what the server sent */
113 memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
114
115 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
116 cifs_pdu->Signature.Sequence.Reserved = 0;
117
118 rc = cifs_calculate_signature(cifs_pdu, mac_key,
119 what_we_think_sig_should_be);
120
121 if(rc)
122 return rc;
123
124
125/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
126
127 if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
128 return -EACCES;
129 else
130 return 0;
131
132}
133
134/* We fill in key by putting in 40 byte array which was allocated by caller */
135int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
136{
137 char temp_key[16];
138 if ((key == NULL) || (rn == NULL))
139 return -EINVAL;
140
141 E_md4hash(password, temp_key);
142 mdfour(key,temp_key,16);
143 memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
144 return 0;
145}
146
147int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
148{
149 char temp_hash[16];
150 struct HMACMD5Context ctx;
151 char * ucase_buf;
152 wchar_t * unicode_buf;
153 unsigned int i,user_name_len,dom_name_len;
154
155 if(ses == NULL)
156 return -EINVAL;
157
158 E_md4hash(ses->password, temp_hash);
159
160 hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
161 user_name_len = strlen(ses->userName);
162 if(user_name_len > MAX_USERNAME_SIZE)
163 return -EINVAL;
164 dom_name_len = strlen(ses->domainName);
165 if(dom_name_len > MAX_USERNAME_SIZE)
166 return -EINVAL;
167
168 ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
169 if(ucase_buf == NULL)
170 return -ENOMEM;
171 unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
172 if(unicode_buf == NULL) {
173 kfree(ucase_buf);
174 return -ENOMEM;
175 }
176
177 for(i=0;i<user_name_len;i++)
178 ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
179 ucase_buf[i] = 0;
180 user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
181 unicode_buf[user_name_len] = 0;
182 user_name_len++;
183
184 for(i=0;i<dom_name_len;i++)
185 ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
186 ucase_buf[i] = 0;
187 dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
188
189 unicode_buf[user_name_len + dom_name_len] = 0;
190 hmac_md5_update((const unsigned char *) unicode_buf,
191 (user_name_len+dom_name_len)*2,&ctx);
192
193 hmac_md5_final(ses->mac_signing_key,&ctx);
194 kfree(ucase_buf);
195 kfree(unicode_buf);
196 return 0;
197}
198void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
199{
200 struct HMACMD5Context context;
201 memcpy(v2_session_response + 8, ses->server->cryptKey,8);
202 /* gen_blob(v2_session_response + 16); */
203 hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
204
205 hmac_md5_update(ses->server->cryptKey,8,&context);
206/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
207
208 hmac_md5_final(v2_session_response,&context);
209}
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h
new file mode 100644
index 000000000000..03e359b32861
--- /dev/null
+++ b/fs/cifs/cifsencrypt.h
@@ -0,0 +1,34 @@
1/*
2 * fs/cifs/cifsencrypt.h
3 *
4 * Copyright (c) International Business Machines Corp., 2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Externs for misc. small encryption routines
8 * so we do not have to put them in cifsproto.h
9 *
10 * This library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25/* md4.c */
26extern void mdfour(unsigned char *out, unsigned char *in, int n);
27/* smbdes.c */
28extern void E_P16(unsigned char *p14, unsigned char *p16);
29extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
30extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
31extern void E_old_pw_hash(unsigned char *, unsigned char *, unsigned char *);
32
33
34
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
new file mode 100644
index 000000000000..5082fce3c566
--- /dev/null
+++ b/fs/cifs/cifsfs.c
@@ -0,0 +1,913 @@
1/*
2 * fs/cifs/cifsfs.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Common Internet FileSystem (CIFS) client
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/* Note that BB means BUGBUG (ie something to fix eventually) */
25
26#include <linux/module.h>
27#include <linux/fs.h>
28#include <linux/mount.h>
29#include <linux/slab.h>
30#include <linux/init.h>
31#include <linux/list.h>
32#include <linux/seq_file.h>
33#include <linux/vfs.h>
34#include <linux/mempool.h>
35#include "cifsfs.h"
36#include "cifspdu.h"
37#define DECLARE_GLOBALS_HERE
38#include "cifsglob.h"
39#include "cifsproto.h"
40#include "cifs_debug.h"
41#include "cifs_fs_sb.h"
42#include <linux/mm.h>
43#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
44
45#ifdef CONFIG_CIFS_QUOTA
46static struct quotactl_ops cifs_quotactl_ops;
47#endif
48
49int cifsFYI = 0;
50int cifsERROR = 1;
51int traceSMB = 0;
52unsigned int oplockEnabled = 1;
53unsigned int experimEnabled = 0;
54unsigned int linuxExtEnabled = 1;
55unsigned int lookupCacheEnabled = 1;
56unsigned int multiuser_mount = 0;
57unsigned int extended_security = 0;
58unsigned int ntlmv2_support = 0;
59unsigned int sign_CIFS_PDUs = 1;
60extern struct task_struct * oplockThread; /* remove sparse warning */
61struct task_struct * oplockThread = NULL;
62unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
63module_param(CIFSMaxBufSize, int, 0);
64MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
65unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
66module_param(cifs_min_rcv, int, 0);
67MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
68unsigned int cifs_min_small = 30;
69module_param(cifs_min_small, int, 0);
70MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256");
71unsigned int cifs_max_pending = CIFS_MAX_REQ;
72module_param(cifs_max_pending, int, 0);
73MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
74
75static DECLARE_COMPLETION(cifs_oplock_exited);
76
77extern mempool_t *cifs_sm_req_poolp;
78extern mempool_t *cifs_req_poolp;
79extern mempool_t *cifs_mid_poolp;
80
81extern kmem_cache_t *cifs_oplock_cachep;
82
83static int
84cifs_read_super(struct super_block *sb, void *data,
85 const char *devname, int silent)
86{
87 struct inode *inode;
88 struct cifs_sb_info *cifs_sb;
89 int rc = 0;
90
91 sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
92 sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
93 cifs_sb = CIFS_SB(sb);
94 if(cifs_sb == NULL)
95 return -ENOMEM;
96 else
97 memset(cifs_sb,0,sizeof(struct cifs_sb_info));
98
99
100 rc = cifs_mount(sb, cifs_sb, data, devname);
101
102 if (rc) {
103 if (!silent)
104 cERROR(1,
105 ("cifs_mount failed w/return code = %d", rc));
106 goto out_mount_failed;
107 }
108
109 sb->s_magic = CIFS_MAGIC_NUMBER;
110 sb->s_op = &cifs_super_ops;
111/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
112 sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
113#ifdef CONFIG_CIFS_QUOTA
114 sb->s_qcop = &cifs_quotactl_ops;
115#endif
116 sb->s_blocksize = CIFS_MAX_MSGSIZE;
117 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
118 inode = iget(sb, ROOT_I);
119
120 if (!inode) {
121 rc = -ENOMEM;
122 goto out_no_root;
123 }
124
125 sb->s_root = d_alloc_root(inode);
126
127 if (!sb->s_root) {
128 rc = -ENOMEM;
129 goto out_no_root;
130 }
131
132 return 0;
133
134out_no_root:
135 cERROR(1, ("cifs_read_super: get root inode failed"));
136 if (inode)
137 iput(inode);
138
139out_mount_failed:
140 if(cifs_sb) {
141 if(cifs_sb->local_nls)
142 unload_nls(cifs_sb->local_nls);
143 kfree(cifs_sb);
144 }
145 return rc;
146}
147
148static void
149cifs_put_super(struct super_block *sb)
150{
151 int rc = 0;
152 struct cifs_sb_info *cifs_sb;
153
154 cFYI(1, ("In cifs_put_super"));
155 cifs_sb = CIFS_SB(sb);
156 if(cifs_sb == NULL) {
157 cFYI(1,("Empty cifs superblock info passed to unmount"));
158 return;
159 }
160 rc = cifs_umount(sb, cifs_sb);
161 if (rc) {
162 cERROR(1, ("cifs_umount failed with return code %d", rc));
163 }
164 unload_nls(cifs_sb->local_nls);
165 kfree(cifs_sb);
166 return;
167}
168
169static int
170cifs_statfs(struct super_block *sb, struct kstatfs *buf)
171{
172 int xid, rc = -EOPNOTSUPP;
173 struct cifs_sb_info *cifs_sb;
174 struct cifsTconInfo *pTcon;
175
176 xid = GetXid();
177
178 cifs_sb = CIFS_SB(sb);
179 pTcon = cifs_sb->tcon;
180
181 buf->f_type = CIFS_MAGIC_NUMBER;
182
183 /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
184 buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably
185 be length of total path, note that some servers may be
186 able to support more than this, but best to be safe
187 since Win2k and others can not handle very long filenames */
188 buf->f_files = 0; /* undefined */
189 buf->f_ffree = 0; /* unlimited */
190
191#ifdef CONFIG_CIFS_EXPERIMENTAL
192/* BB we could add a second check for a QFS Unix capability bit */
193 if (pTcon->ses->capabilities & CAP_UNIX)
194 rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls);
195
196 /* Only need to call the old QFSInfo if failed
197 on newer one */
198 if(rc)
199#endif /* CIFS_EXPERIMENTAL */
200 rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
201
202 /*
203 int f_type;
204 __fsid_t f_fsid;
205 int f_namelen; */
206 /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
207 FreeXid(xid);
208 return 0; /* always return success? what if volume is no longer available? */
209}
210
211static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
212{
213 struct cifs_sb_info *cifs_sb;
214
215 cifs_sb = CIFS_SB(inode->i_sb);
216
217 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
218 return 0;
219 } else /* file mode might have been restricted at mount time
220 on the client (above and beyond ACL on servers) for
221 servers which do not support setting and viewing mode bits,
222 so allowing client to check permissions is useful */
223 return generic_permission(inode, mask, NULL);
224}
225
226static kmem_cache_t *cifs_inode_cachep;
227static kmem_cache_t *cifs_req_cachep;
228static kmem_cache_t *cifs_mid_cachep;
229kmem_cache_t *cifs_oplock_cachep;
230static kmem_cache_t *cifs_sm_req_cachep;
231mempool_t *cifs_sm_req_poolp;
232mempool_t *cifs_req_poolp;
233mempool_t *cifs_mid_poolp;
234
235static struct inode *
236cifs_alloc_inode(struct super_block *sb)
237{
238 struct cifsInodeInfo *cifs_inode;
239 cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
240 if (!cifs_inode)
241 return NULL;
242 cifs_inode->cifsAttrs = 0x20; /* default */
243 atomic_set(&cifs_inode->inUse, 0);
244 cifs_inode->time = 0;
245 /* Until the file is open and we have gotten oplock
246 info back from the server, can not assume caching of
247 file data or metadata */
248 cifs_inode->clientCanCacheRead = FALSE;
249 cifs_inode->clientCanCacheAll = FALSE;
250 cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
251 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
252
253 INIT_LIST_HEAD(&cifs_inode->openFileList);
254 return &cifs_inode->vfs_inode;
255}
256
257static void
258cifs_destroy_inode(struct inode *inode)
259{
260 kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
261}
262
263/*
264 * cifs_show_options() is for displaying mount options in /proc/mounts.
265 * Not all settable options are displayed but most of the important
266 * ones are.
267 */
268static int
269cifs_show_options(struct seq_file *s, struct vfsmount *m)
270{
271 struct cifs_sb_info *cifs_sb;
272
273 cifs_sb = CIFS_SB(m->mnt_sb);
274
275 if (cifs_sb) {
276 if (cifs_sb->tcon) {
277 seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
278 if (cifs_sb->tcon->ses) {
279 if (cifs_sb->tcon->ses->userName)
280 seq_printf(s, ",username=%s",
281 cifs_sb->tcon->ses->userName);
282 if(cifs_sb->tcon->ses->domainName)
283 seq_printf(s, ",domain=%s",
284 cifs_sb->tcon->ses->domainName);
285 }
286 }
287 seq_printf(s, ",rsize=%d",cifs_sb->rsize);
288 seq_printf(s, ",wsize=%d",cifs_sb->wsize);
289 }
290 return 0;
291}
292
293#ifdef CONFIG_CIFS_QUOTA
294int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
295 struct fs_disk_quota * pdquota)
296{
297 int xid;
298 int rc = 0;
299 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
300 struct cifsTconInfo *pTcon;
301
302 if(cifs_sb)
303 pTcon = cifs_sb->tcon;
304 else
305 return -EIO;
306
307
308 xid = GetXid();
309 if(pTcon) {
310 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
311 } else {
312 return -EIO;
313 }
314
315 FreeXid(xid);
316 return rc;
317}
318
319int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
320 struct fs_disk_quota * pdquota)
321{
322 int xid;
323 int rc = 0;
324 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
325 struct cifsTconInfo *pTcon;
326
327 if(cifs_sb)
328 pTcon = cifs_sb->tcon;
329 else
330 return -EIO;
331
332 xid = GetXid();
333 if(pTcon) {
334 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
335 } else {
336 rc = -EIO;
337 }
338
339 FreeXid(xid);
340 return rc;
341}
342
343int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
344{
345 int xid;
346 int rc = 0;
347 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
348 struct cifsTconInfo *pTcon;
349
350 if(cifs_sb)
351 pTcon = cifs_sb->tcon;
352 else
353 return -EIO;
354
355 xid = GetXid();
356 if(pTcon) {
357 cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
358 } else {
359 rc = -EIO;
360 }
361
362 FreeXid(xid);
363 return rc;
364}
365
366int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
367{
368 int xid;
369 int rc = 0;
370 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
371 struct cifsTconInfo *pTcon;
372
373 if(cifs_sb) {
374 pTcon = cifs_sb->tcon;
375 } else {
376 return -EIO;
377 }
378 xid = GetXid();
379 if(pTcon) {
380 cFYI(1,("pqstats %p",qstats));
381 } else {
382 rc = -EIO;
383 }
384
385 FreeXid(xid);
386 return rc;
387}
388
389static struct quotactl_ops cifs_quotactl_ops = {
390 .set_xquota = cifs_xquota_set,
391 .get_xquota = cifs_xquota_set,
392 .set_xstate = cifs_xstate_set,
393 .get_xstate = cifs_xstate_get,
394};
395#endif
396
397static int cifs_remount(struct super_block *sb, int *flags, char *data)
398{
399 *flags |= MS_NODIRATIME;
400 return 0;
401}
402
403struct super_operations cifs_super_ops = {
404 .read_inode = cifs_read_inode,
405 .put_super = cifs_put_super,
406 .statfs = cifs_statfs,
407 .alloc_inode = cifs_alloc_inode,
408 .destroy_inode = cifs_destroy_inode,
409/* .drop_inode = generic_delete_inode,
410 .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
411 unless later we add lazy close of inodes or unless the kernel forgets to call
412 us with the same number of releases (closes) as opens */
413 .show_options = cifs_show_options,
414/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
415 .remount_fs = cifs_remount,
416};
417
418static struct super_block *
419cifs_get_sb(struct file_system_type *fs_type,
420 int flags, const char *dev_name, void *data)
421{
422 int rc;
423 struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
424
425 cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
426
427 if (IS_ERR(sb))
428 return sb;
429
430 sb->s_flags = flags;
431
432 rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
433 if (rc) {
434 up_write(&sb->s_umount);
435 deactivate_super(sb);
436 return ERR_PTR(rc);
437 }
438 sb->s_flags |= MS_ACTIVE;
439 return sb;
440}
441
442static ssize_t
443cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
444 loff_t * poffset)
445{
446 if(file->f_dentry == NULL)
447 return -EIO;
448 else if(file->f_dentry->d_inode == NULL)
449 return -EIO;
450
451 cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
452
453 if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
454 return generic_file_read(file,read_data,read_size,poffset);
455 } else {
456 /* BB do we need to lock inode from here until after invalidate? */
457/* if(file->f_dentry->d_inode->i_mapping) {
458 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
459 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
460 }*/
461/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
462
463 /* BB we should make timer configurable - perhaps
464 by simply calling cifs_revalidate here */
465 /* invalidate_remote_inode(file->f_dentry->d_inode);*/
466 return generic_file_read(file,read_data,read_size,poffset);
467 }
468}
469
470static ssize_t
471cifs_write_wrapper(struct file * file, const char __user *write_data,
472 size_t write_size, loff_t * poffset)
473{
474 ssize_t written;
475
476 if(file->f_dentry == NULL)
477 return -EIO;
478 else if(file->f_dentry->d_inode == NULL)
479 return -EIO;
480
481 cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
482
483 written = generic_file_write(file,write_data,write_size,poffset);
484 if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
485 if(file->f_dentry->d_inode->i_mapping) {
486 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
487 }
488 }
489 return written;
490}
491
492
493static struct file_system_type cifs_fs_type = {
494 .owner = THIS_MODULE,
495 .name = "cifs",
496 .get_sb = cifs_get_sb,
497 .kill_sb = kill_anon_super,
498 /* .fs_flags */
499};
500struct inode_operations cifs_dir_inode_ops = {
501 .create = cifs_create,
502 .lookup = cifs_lookup,
503 .getattr = cifs_getattr,
504 .unlink = cifs_unlink,
505 .link = cifs_hardlink,
506 .mkdir = cifs_mkdir,
507 .rmdir = cifs_rmdir,
508 .rename = cifs_rename,
509 .permission = cifs_permission,
510/* revalidate:cifs_revalidate, */
511 .setattr = cifs_setattr,
512 .symlink = cifs_symlink,
513 .mknod = cifs_mknod,
514#ifdef CONFIG_CIFS_XATTR
515 .setxattr = cifs_setxattr,
516 .getxattr = cifs_getxattr,
517 .listxattr = cifs_listxattr,
518 .removexattr = cifs_removexattr,
519#endif
520};
521
522struct inode_operations cifs_file_inode_ops = {
523/* revalidate:cifs_revalidate, */
524 .setattr = cifs_setattr,
525 .getattr = cifs_getattr, /* do we need this anymore? */
526 .rename = cifs_rename,
527 .permission = cifs_permission,
528#ifdef CONFIG_CIFS_XATTR
529 .setxattr = cifs_setxattr,
530 .getxattr = cifs_getxattr,
531 .listxattr = cifs_listxattr,
532 .removexattr = cifs_removexattr,
533#endif
534};
535
536struct inode_operations cifs_symlink_inode_ops = {
537 .readlink = generic_readlink,
538 .follow_link = cifs_follow_link,
539 .put_link = cifs_put_link,
540 .permission = cifs_permission,
541 /* BB add the following two eventually */
542 /* revalidate: cifs_revalidate,
543 setattr: cifs_notify_change, *//* BB do we need notify change */
544#ifdef CONFIG_CIFS_XATTR
545 .setxattr = cifs_setxattr,
546 .getxattr = cifs_getxattr,
547 .listxattr = cifs_listxattr,
548 .removexattr = cifs_removexattr,
549#endif
550};
551
552struct file_operations cifs_file_ops = {
553 .read = cifs_read_wrapper,
554 .write = cifs_write_wrapper,
555 .open = cifs_open,
556 .release = cifs_close,
557 .lock = cifs_lock,
558 .fsync = cifs_fsync,
559 .flush = cifs_flush,
560 .mmap = cifs_file_mmap,
561 .sendfile = generic_file_sendfile,
562#ifdef CONFIG_CIFS_EXPERIMENTAL
563 .readv = generic_file_readv,
564 .writev = generic_file_writev,
565 .aio_read = generic_file_aio_read,
566 .aio_write = generic_file_aio_write,
567 .dir_notify = cifs_dir_notify,
568#endif /* CONFIG_CIFS_EXPERIMENTAL */
569};
570
571struct file_operations cifs_file_direct_ops = {
572 /* no mmap, no aio, no readv -
573 BB reevaluate whether they can be done with directio, no cache */
574 .read = cifs_user_read,
575 .write = cifs_user_write,
576 .open = cifs_open,
577 .release = cifs_close,
578 .lock = cifs_lock,
579 .fsync = cifs_fsync,
580 .flush = cifs_flush,
581 .sendfile = generic_file_sendfile, /* BB removeme BB */
582#ifdef CONFIG_CIFS_EXPERIMENTAL
583 .dir_notify = cifs_dir_notify,
584#endif /* CONFIG_CIFS_EXPERIMENTAL */
585};
586
587struct file_operations cifs_dir_ops = {
588 .readdir = cifs_readdir,
589 .release = cifs_closedir,
590 .read = generic_read_dir,
591#ifdef CONFIG_CIFS_EXPERIMENTAL
592 .dir_notify = cifs_dir_notify,
593#endif /* CONFIG_CIFS_EXPERIMENTAL */
594};
595
596static void
597cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
598{
599 struct cifsInodeInfo *cifsi = inode;
600
601 if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
602 SLAB_CTOR_CONSTRUCTOR) {
603 inode_init_once(&cifsi->vfs_inode);
604 INIT_LIST_HEAD(&cifsi->lockList);
605 }
606}
607
608static int
609cifs_init_inodecache(void)
610{
611 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
612 sizeof (struct cifsInodeInfo),
613 0, SLAB_RECLAIM_ACCOUNT,
614 cifs_init_once, NULL);
615 if (cifs_inode_cachep == NULL)
616 return -ENOMEM;
617
618 return 0;
619}
620
621static void
622cifs_destroy_inodecache(void)
623{
624 if (kmem_cache_destroy(cifs_inode_cachep))
625 printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
626}
627
628static int
629cifs_init_request_bufs(void)
630{
631 if(CIFSMaxBufSize < 8192) {
632 /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
633 Unicode path name has to fit in any SMB/CIFS path based frames */
634 CIFSMaxBufSize = 8192;
635 } else if (CIFSMaxBufSize > 1024*127) {
636 CIFSMaxBufSize = 1024 * 127;
637 } else {
638 CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
639 }
640/* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */
641 cifs_req_cachep = kmem_cache_create("cifs_request",
642 CIFSMaxBufSize +
643 MAX_CIFS_HDR_SIZE, 0,
644 SLAB_HWCACHE_ALIGN, NULL, NULL);
645 if (cifs_req_cachep == NULL)
646 return -ENOMEM;
647
648 if(cifs_min_rcv < 1)
649 cifs_min_rcv = 1;
650 else if (cifs_min_rcv > 64) {
651 cifs_min_rcv = 64;
652 cERROR(1,("cifs_min_rcv set to maximum (64)"));
653 }
654
655 cifs_req_poolp = mempool_create(cifs_min_rcv,
656 mempool_alloc_slab,
657 mempool_free_slab,
658 cifs_req_cachep);
659
660 if(cifs_req_poolp == NULL) {
661 kmem_cache_destroy(cifs_req_cachep);
662 return -ENOMEM;
663 }
664 /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
665 almost all handle based requests (but not write response, nor is it
666 sufficient for path based requests). A smaller size would have
667 been more efficient (compacting multiple slab items on one 4k page)
668 for the case in which debug was on, but this larger size allows
669 more SMBs to use small buffer alloc and is still much more
670 efficient to alloc 1 per page off the slab compared to 17K (5page)
671 alloc of large cifs buffers even when page debugging is on */
672 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
673 MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
674 if (cifs_sm_req_cachep == NULL) {
675 mempool_destroy(cifs_req_poolp);
676 kmem_cache_destroy(cifs_req_cachep);
677 return -ENOMEM;
678 }
679
680 if(cifs_min_small < 2)
681 cifs_min_small = 2;
682 else if (cifs_min_small > 256) {
683 cifs_min_small = 256;
684 cFYI(1,("cifs_min_small set to maximum (256)"));
685 }
686
687 cifs_sm_req_poolp = mempool_create(cifs_min_small,
688 mempool_alloc_slab,
689 mempool_free_slab,
690 cifs_sm_req_cachep);
691
692 if(cifs_sm_req_poolp == NULL) {
693 mempool_destroy(cifs_req_poolp);
694 kmem_cache_destroy(cifs_req_cachep);
695 kmem_cache_destroy(cifs_sm_req_cachep);
696 return -ENOMEM;
697 }
698
699 return 0;
700}
701
702static void
703cifs_destroy_request_bufs(void)
704{
705 mempool_destroy(cifs_req_poolp);
706 if (kmem_cache_destroy(cifs_req_cachep))
707 printk(KERN_WARNING
708 "cifs_destroy_request_cache: error not all structures were freed\n");
709 mempool_destroy(cifs_sm_req_poolp);
710 if (kmem_cache_destroy(cifs_sm_req_cachep))
711 printk(KERN_WARNING
712 "cifs_destroy_request_cache: cifs_small_rq free error\n");
713}
714
715static int
716cifs_init_mids(void)
717{
718 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
719 sizeof (struct mid_q_entry), 0,
720 SLAB_HWCACHE_ALIGN, NULL, NULL);
721 if (cifs_mid_cachep == NULL)
722 return -ENOMEM;
723
724 cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */,
725 mempool_alloc_slab,
726 mempool_free_slab,
727 cifs_mid_cachep);
728 if(cifs_mid_poolp == NULL) {
729 kmem_cache_destroy(cifs_mid_cachep);
730 return -ENOMEM;
731 }
732
733 cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
734 sizeof (struct oplock_q_entry), 0,
735 SLAB_HWCACHE_ALIGN, NULL, NULL);
736 if (cifs_oplock_cachep == NULL) {
737 kmem_cache_destroy(cifs_mid_cachep);
738 mempool_destroy(cifs_mid_poolp);
739 return -ENOMEM;
740 }
741
742 return 0;
743}
744
745static void
746cifs_destroy_mids(void)
747{
748 mempool_destroy(cifs_mid_poolp);
749 if (kmem_cache_destroy(cifs_mid_cachep))
750 printk(KERN_WARNING
751 "cifs_destroy_mids: error not all structures were freed\n");
752
753 if (kmem_cache_destroy(cifs_oplock_cachep))
754 printk(KERN_WARNING
755 "error not all oplock structures were freed\n");
756}
757
758static int cifs_oplock_thread(void * dummyarg)
759{
760 struct oplock_q_entry * oplock_item;
761 struct cifsTconInfo *pTcon;
762 struct inode * inode;
763 __u16 netfid;
764 int rc;
765
766 daemonize("cifsoplockd");
767 allow_signal(SIGTERM);
768
769 oplockThread = current;
770 do {
771 set_current_state(TASK_INTERRUPTIBLE);
772
773 schedule_timeout(1*HZ);
774 spin_lock(&GlobalMid_Lock);
775 if(list_empty(&GlobalOplock_Q)) {
776 spin_unlock(&GlobalMid_Lock);
777 set_current_state(TASK_INTERRUPTIBLE);
778 schedule_timeout(39*HZ);
779 } else {
780 oplock_item = list_entry(GlobalOplock_Q.next,
781 struct oplock_q_entry, qhead);
782 if(oplock_item) {
783 cFYI(1,("found oplock item to write out"));
784 pTcon = oplock_item->tcon;
785 inode = oplock_item->pinode;
786 netfid = oplock_item->netfid;
787 spin_unlock(&GlobalMid_Lock);
788 DeleteOplockQEntry(oplock_item);
789 /* can not grab inode sem here since it would
790 deadlock when oplock received on delete
791 since vfs_unlink holds the i_sem across
792 the call */
793 /* down(&inode->i_sem);*/
794 if (S_ISREG(inode->i_mode)) {
795 rc = filemap_fdatawrite(inode->i_mapping);
796 if(CIFS_I(inode)->clientCanCacheRead == 0) {
797 filemap_fdatawait(inode->i_mapping);
798 invalidate_remote_inode(inode);
799 }
800 } else
801 rc = 0;
802 /* up(&inode->i_sem);*/
803 if (rc)
804 CIFS_I(inode)->write_behind_rc = rc;
805 cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
806
807 /* releasing a stale oplock after recent reconnection
808 of smb session using a now incorrect file
809 handle is not a data integrity issue but do
810 not bother sending an oplock release if session
811 to server still is disconnected since oplock
812 already released by the server in that case */
813 if(pTcon->tidStatus != CifsNeedReconnect) {
814 rc = CIFSSMBLock(0, pTcon, netfid,
815 0 /* len */ , 0 /* offset */, 0,
816 0, LOCKING_ANDX_OPLOCK_RELEASE,
817 0 /* wait flag */);
818 cFYI(1,("Oplock release rc = %d ",rc));
819 }
820 } else
821 spin_unlock(&GlobalMid_Lock);
822 }
823 } while(!signal_pending(current));
824 complete_and_exit (&cifs_oplock_exited, 0);
825}
826
827static int __init
828init_cifs(void)
829{
830 int rc = 0;
831#ifdef CONFIG_PROC_FS
832 cifs_proc_init();
833#endif
834 INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
835 INIT_LIST_HEAD(&GlobalSMBSessionList);
836 INIT_LIST_HEAD(&GlobalTreeConnectionList);
837 INIT_LIST_HEAD(&GlobalOplock_Q);
838/*
839 * Initialize Global counters
840 */
841 atomic_set(&sesInfoAllocCount, 0);
842 atomic_set(&tconInfoAllocCount, 0);
843 atomic_set(&tcpSesAllocCount,0);
844 atomic_set(&tcpSesReconnectCount, 0);
845 atomic_set(&tconInfoReconnectCount, 0);
846
847 atomic_set(&bufAllocCount, 0);
848 atomic_set(&midCount, 0);
849 GlobalCurrentXid = 0;
850 GlobalTotalActiveXid = 0;
851 GlobalMaxActiveXid = 0;
852 rwlock_init(&GlobalSMBSeslock);
853 spin_lock_init(&GlobalMid_Lock);
854
855 if(cifs_max_pending < 2) {
856 cifs_max_pending = 2;
857 cFYI(1,("cifs_max_pending set to min of 2"));
858 } else if(cifs_max_pending > 256) {
859 cifs_max_pending = 256;
860 cFYI(1,("cifs_max_pending set to max of 256"));
861 }
862
863 rc = cifs_init_inodecache();
864 if (!rc) {
865 rc = cifs_init_mids();
866 if (!rc) {
867 rc = cifs_init_request_bufs();
868 if (!rc) {
869 rc = register_filesystem(&cifs_fs_type);
870 if (!rc) {
871 rc = (int)kernel_thread(cifs_oplock_thread, NULL,
872 CLONE_FS | CLONE_FILES | CLONE_VM);
873 if(rc > 0)
874 return 0;
875 else
876 cERROR(1,("error %d create oplock thread",rc));
877 }
878 cifs_destroy_request_bufs();
879 }
880 cifs_destroy_mids();
881 }
882 cifs_destroy_inodecache();
883 }
884#ifdef CONFIG_PROC_FS
885 cifs_proc_clean();
886#endif
887 return rc;
888}
889
890static void __exit
891exit_cifs(void)
892{
893 cFYI(0, ("In unregister ie exit_cifs"));
894#ifdef CONFIG_PROC_FS
895 cifs_proc_clean();
896#endif
897 unregister_filesystem(&cifs_fs_type);
898 cifs_destroy_inodecache();
899 cifs_destroy_mids();
900 cifs_destroy_request_bufs();
901 if(oplockThread) {
902 send_sig(SIGTERM, oplockThread, 1);
903 wait_for_completion(&cifs_oplock_exited);
904 }
905}
906
907MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
908MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
909MODULE_DESCRIPTION
910 ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
911MODULE_VERSION(CIFS_VERSION);
912module_init(init_cifs)
913module_exit(exit_cifs)
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
new file mode 100644
index 000000000000..451f18af3206
--- /dev/null
+++ b/fs/cifs/cifsfs.h
@@ -0,0 +1,98 @@
1/*
2 * fs/cifs/cifsfs.h
3 *
4 * Copyright (c) International Business Machines Corp., 2002
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifndef _CIFSFS_H
23#define _CIFSFS_H
24
25#define ROOT_I 2
26
27#ifndef FALSE
28#define FALSE 0
29#endif
30
31#ifndef TRUE
32#define TRUE 1
33#endif
34
35extern struct address_space_operations cifs_addr_ops;
36
37/* Functions related to super block operations */
38extern struct super_operations cifs_super_ops;
39extern void cifs_read_inode(struct inode *);
40extern void cifs_delete_inode(struct inode *);
41/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
42
43/* Functions related to inodes */
44extern struct inode_operations cifs_dir_inode_ops;
45extern int cifs_create(struct inode *, struct dentry *, int,
46 struct nameidata *);
47extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
48 struct nameidata *);
49extern int cifs_unlink(struct inode *, struct dentry *);
50extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
51extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t);
52extern int cifs_mkdir(struct inode *, struct dentry *, int);
53extern int cifs_rmdir(struct inode *, struct dentry *);
54extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
55 struct dentry *);
56extern int cifs_revalidate(struct dentry *);
57extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
58extern int cifs_setattr(struct dentry *, struct iattr *);
59
60extern struct inode_operations cifs_file_inode_ops;
61extern struct inode_operations cifs_symlink_inode_ops;
62
63/* Functions related to files and directories */
64extern struct file_operations cifs_file_ops;
65extern struct file_operations cifs_file_direct_ops; /* if directio mount */
66extern int cifs_open(struct inode *inode, struct file *file);
67extern int cifs_close(struct inode *inode, struct file *file);
68extern int cifs_closedir(struct inode *inode, struct file *file);
69extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
70 size_t read_size, loff_t * poffset);
71extern ssize_t cifs_user_write(struct file *file, const char __user *write_data,
72 size_t write_size, loff_t * poffset);
73extern int cifs_lock(struct file *, int, struct file_lock *);
74extern int cifs_fsync(struct file *, struct dentry *, int);
75extern int cifs_flush(struct file *);
76extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
77extern struct file_operations cifs_dir_ops;
78extern int cifs_dir_open(struct inode *inode, struct file *file);
79extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
80extern int cifs_dir_notify(struct file *, unsigned long arg);
81
82/* Functions related to dir entries */
83extern struct dentry_operations cifs_dentry_ops;
84
85/* Functions related to symlinks */
86extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
87extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
88extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
89 int buflen);
90extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
91 const char *symname);
92extern int cifs_removexattr(struct dentry *, const char *);
93extern int cifs_setxattr(struct dentry *, const char *, const void *,
94 size_t, int);
95extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
96extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
97#define CIFS_VERSION "1.31"
98#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
new file mode 100644
index 000000000000..69aff1a7da9b
--- /dev/null
+++ b/fs/cifs/cifsglob.h
@@ -0,0 +1,439 @@
1/*
2 * fs/cifs/cifsglob.h
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2003
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 */
18#include <linux/in.h>
19#include <linux/in6.h>
20#include "cifs_fs_sb.h"
21/*
22 * The sizes of various internal tables and strings
23 */
24#define MAX_UID_INFO 16
25#define MAX_SES_INFO 2
26#define MAX_TCON_INFO 4
27
28#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
29#define MAX_SERVER_SIZE 15
30#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
31#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
32 termination then *2 for unicode versions */
33#define MAX_PASSWORD_SIZE 16
34
35#define CIFS_MIN_RCV_POOL 4
36
37/*
38 * MAX_REQ is the maximum number of requests that WE will send
39 * on one socket concurently. It also matches the most common
40 * value of max multiplex returned by servers. We may
41 * eventually want to use the negotiated value (in case
42 * future servers can handle more) when we are more confident that
43 * we will not have problems oveloading the socket with pending
44 * write data.
45 */
46#define CIFS_MAX_REQ 50
47
48#define SERVER_NAME_LENGTH 15
49#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
50
51/* used to define string lengths for reversing unicode strings */
52/* (256+1)*2 = 514 */
53/* (max path length + 1 for null) * 2 for unicode */
54#define MAX_NAME 514
55
56#include "cifspdu.h"
57
58#ifndef FALSE
59#define FALSE 0
60#endif
61
62#ifndef TRUE
63#define TRUE 1
64#endif
65
66#ifndef XATTR_DOS_ATTRIB
67#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
68#endif
69
70/*
71 * This information is kept on every Server we know about.
72 *
73 * Some things to note:
74 *
75 */
76#define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1)
77
78/*
79 * CIFS vfs client Status information (based on what we know.)
80 */
81
82 /* associated with each tcp and smb session */
83enum statusEnum {
84 CifsNew = 0,
85 CifsGood,
86 CifsExiting,
87 CifsNeedReconnect
88};
89
90enum securityEnum {
91 NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
92 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
93 RawNTLMSSP, /* NTLMSSP without SPNEGO */
94 NTLMSSP, /* NTLMSSP via SPNEGO */
95 Kerberos /* Kerberos via SPNEGO */
96};
97
98enum protocolEnum {
99 IPV4 = 0,
100 IPV6,
101 SCTP
102 /* Netbios frames protocol not supported at this time */
103};
104
105/*
106 *****************************************************************
107 * Except the CIFS PDUs themselves all the
108 * globally interesting structs should go here
109 *****************************************************************
110 */
111
112struct TCP_Server_Info {
113 char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20'in 16th */
114 char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; /* Unicode version of server_Name */
115 struct socket *ssocket;
116 union {
117 struct sockaddr_in sockAddr;
118 struct sockaddr_in6 sockAddr6;
119 } addr;
120 wait_queue_head_t response_q;
121 wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
122 struct list_head pending_mid_q;
123 void *Server_NlsInfo; /* BB - placeholder for future NLS info */
124 unsigned short server_codepage; /* codepage for the server */
125 unsigned long ip_address; /* IP addr for the server if known */
126 enum protocolEnum protocolType;
127 char versionMajor;
128 char versionMinor;
129 unsigned svlocal:1; /* local server or remote */
130 atomic_t socketUseCount; /* number of open cifs sessions on socket */
131 atomic_t inFlight; /* number of requests on the wire to server */
132 enum statusEnum tcpStatus; /* what we think the status is */
133 struct semaphore tcpSem;
134 struct task_struct *tsk;
135 char server_GUID[16];
136 char secMode;
137 enum securityEnum secType;
138 unsigned int maxReq; /* Clients should submit no more */
139 /* than maxReq distinct unanswered SMBs to the server when using */
140 /* multiplexed reads or writes */
141 unsigned int maxBuf; /* maxBuf specifies the maximum */
142 /* message size the server can send or receive for non-raw SMBs */
143 unsigned int maxRw; /* maxRw specifies the maximum */
144 /* message size the server can send or receive for */
145 /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
146 char sessid[4]; /* unique token id for this session */
147 /* (returned on Negotiate */
148 int capabilities; /* allow selective disabling of caps by smb sess */
149 __u16 timeZone;
150 char cryptKey[CIFS_CRYPTO_KEY_SIZE];
151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */
152};
153
154/*
155 * The following is our shortcut to user information. We surface the uid,
156 * and name. We always get the password on the fly in case it
157 * has changed. We also hang a list of sessions owned by this user off here.
158 */
159struct cifsUidInfo {
160 struct list_head userList;
161 struct list_head sessionList; /* SMB sessions for this user */
162 uid_t linux_uid;
163 char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
164 /* BB may need ptr or callback for PAM or WinBind info */
165};
166
167/*
168 * Session structure. One of these for each uid session with a particular host
169 */
170struct cifsSesInfo {
171 struct list_head cifsSessionList;
172 struct semaphore sesSem;
173 struct cifsUidInfo *uidInfo; /* pointer to user info */
174 struct TCP_Server_Info *server; /* pointer to server info */
175 atomic_t inUse; /* # of mounts (tree connections) on this ses */
176 enum statusEnum status;
177 __u32 sequence_number; /* needed for CIFS PDU signature */
178 __u16 ipc_tid; /* special tid for connection to IPC share */
179 __u16 flags;
180 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
181 char *serverOS; /* name of operating system underlying the server */
182 char *serverNOS; /* name of network operating system that the server is running */
183 char *serverDomain; /* security realm of server */
184 int Suid; /* remote smb uid */
185 uid_t linux_uid; /* local Linux uid */
186 int capabilities;
187 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
188 char userName[MAX_USERNAME_SIZE + 1];
189 char domainName[MAX_USERNAME_SIZE + 1];
190 char * password;
191};
192/* session flags */
193#define CIFS_SES_NT4 1
194
195/*
196 * there is one of these for each connection to a resource on a particular
197 * session
198 */
199struct cifsTconInfo {
200 struct list_head cifsConnectionList;
201 struct list_head openFileList;
202 struct semaphore tconSem;
203 struct cifsSesInfo *ses; /* pointer to session associated with */
204 char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
205 char *nativeFileSystem;
206 __u16 tid; /* The 2 byte tree id */
207 __u16 Flags; /* optional support bits */
208 enum statusEnum tidStatus;
209 atomic_t useCount; /* how many mounts (explicit or implicit) to this share */
210#ifdef CONFIG_CIFS_STATS
211 atomic_t num_smbs_sent;
212 atomic_t num_writes;
213 atomic_t num_reads;
214 atomic_t num_oplock_brks;
215 atomic_t num_opens;
216 atomic_t num_deletes;
217 atomic_t num_mkdirs;
218 atomic_t num_rmdirs;
219 atomic_t num_renames;
220 atomic_t num_t2renames;
221 __u64 bytes_read;
222 __u64 bytes_written;
223 spinlock_t stat_lock;
224#endif
225 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
226 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if file system name truncated */
227 FILE_SYSTEM_UNIX_INFO fsUnixInfo;
228 unsigned retry:1;
229 /* BB add field for back pointer to sb struct? */
230};
231
232/*
233 * This info hangs off the cifsFileInfo structure. This is used to track
234 * byte stream locks on the file
235 */
236struct cifsLockInfo {
237 struct cifsLockInfo *next;
238 int start;
239 int length;
240 int type;
241};
242
243/*
244 * One of these for each open instance of a file
245 */
246struct cifs_search_info {
247 loff_t index_of_last_entry;
248 __u16 entries_in_buffer;
249 __u16 info_level;
250 __u32 resume_key;
251 char * ntwrk_buf_start;
252 char * srch_entries_start;
253 char * presume_name;
254 unsigned int resume_name_len;
255 unsigned endOfSearch:1;
256 unsigned emptyDir:1;
257 unsigned unicode:1;
258};
259
260struct cifsFileInfo {
261 struct list_head tlist; /* pointer to next fid owned by tcon */
262 struct list_head flist; /* next fid (file instance) for this inode */
263 unsigned int uid; /* allows finding which FileInfo structure */
264 __u32 pid; /* process id who opened file */
265 __u16 netfid; /* file id from remote */
266 /* BB add lock scope info here if needed */ ;
267 /* lock scope id (0 if none) */
268 struct file * pfile; /* needed for writepage */
269 struct inode * pInode; /* needed for oplock break */
270 unsigned closePend:1; /* file is marked to close */
271 unsigned invalidHandle:1; /* file closed via session abend */
272 struct semaphore fh_sem; /* prevents reopen race after dead ses*/
273 char * search_resume_name; /* BB removeme BB */
274 unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */
275 struct cifs_search_info srch_inf;
276};
277
278/*
279 * One of these for each file inode
280 */
281
282struct cifsInodeInfo {
283 struct list_head lockList;
284 /* BB add in lists for dirty pages - i.e. write caching info for oplock */
285 struct list_head openFileList;
286 int write_behind_rc;
287 __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
288 atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
289 unsigned long time; /* jiffies of last update/check of inode */
290 unsigned clientCanCacheRead:1; /* read oplock */
291 unsigned clientCanCacheAll:1; /* read and writebehind oplock */
292 unsigned oplockPending:1;
293 struct inode vfs_inode;
294};
295
296static inline struct cifsInodeInfo *
297CIFS_I(struct inode *inode)
298{
299 return container_of(inode, struct cifsInodeInfo, vfs_inode);
300}
301
302static inline struct cifs_sb_info *
303CIFS_SB(struct super_block *sb)
304{
305 return sb->s_fs_info;
306}
307
308
309/* one of these for every pending CIFS request to the server */
310struct mid_q_entry {
311 struct list_head qhead; /* mids waiting on reply from this server */
312 __u16 mid; /* multiplex id */
313 __u16 pid; /* process id */
314 __u32 sequence_number; /* for CIFS signing */
315 __u16 command; /* smb command code */
316 struct timeval when_sent; /* time when smb sent */
317 struct cifsSesInfo *ses; /* smb was sent to this server */
318 struct task_struct *tsk; /* task waiting for response */
319 struct smb_hdr *resp_buf; /* response buffer */
320 int midState; /* wish this were enum but can not pass to wait_event */
321};
322
323struct oplock_q_entry {
324 struct list_head qhead;
325 struct inode * pinode;
326 struct cifsTconInfo * tcon;
327 __u16 netfid;
328};
329
330#define MID_FREE 0
331#define MID_REQUEST_ALLOCATED 1
332#define MID_REQUEST_SUBMITTED 2
333#define MID_RESPONSE_RECEIVED 4
334#define MID_RETRY_NEEDED 8 /* session closed while this request out */
335#define MID_NO_RESP_NEEDED 0x10
336#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */
337
338/*
339 *****************************************************************
340 * All constants go here
341 *****************************************************************
342 */
343
344#define UID_HASH (16)
345
346/*
347 * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
348 * following to be declared.
349 */
350
351/****************************************************************************
352 * Locking notes. All updates to global variables and lists should be
353 * protected by spinlocks or semaphores.
354 *
355 * Spinlocks
356 * ---------
357 * GlobalMid_Lock protects:
358 * list operations on pending_mid_q and oplockQ
359 * updates to XID counters, multiplex id and SMB sequence numbers
360 * GlobalSMBSesLock protects:
361 * list operations on tcp and SMB session lists and tCon lists
362 * f_owner.lock protects certain per file struct operations
363 * mapping->page_lock protects certain per page operations
364 *
365 * Semaphores
366 * ----------
367 * sesSem operations on smb session
368 * tconSem operations on tree connection
369 * fh_sem file handle reconnection operations
370 *
371 ****************************************************************************/
372
373#ifdef DECLARE_GLOBALS_HERE
374#define GLOBAL_EXTERN
375#else
376#define GLOBAL_EXTERN extern
377#endif
378
379/*
380 * The list of servers that did not respond with NT LM 0.12.
381 * This list helps improve performance and eliminate the messages indicating
382 * that we had a communications error talking to the server in this list.
383 */
384GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */
385
386/*
387 * The following is a hash table of all the users we know about.
388 */
389GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
390
391GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
392GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
393GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
394GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
395
396GLOBAL_EXTERN struct list_head GlobalOplock_Q;
397
398/*
399 * Global transaction id (XID) information
400 */
401GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */
402GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
403GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */
404GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above and list operations */
405 /* on midQ entries */
406GLOBAL_EXTERN char Local_System_Name[15];
407
408/*
409 * Global counters, updated atomically
410 */
411GLOBAL_EXTERN atomic_t sesInfoAllocCount;
412GLOBAL_EXTERN atomic_t tconInfoAllocCount;
413GLOBAL_EXTERN atomic_t tcpSesAllocCount;
414GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
415GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
416
417/* Various Debug counters to remove someday (BB) */
418GLOBAL_EXTERN atomic_t bufAllocCount;
419GLOBAL_EXTERN atomic_t smBufAllocCount;
420GLOBAL_EXTERN atomic_t midCount;
421
422/* Misc globals */
423GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
424 to be established on existing mount if we
425 have the uid/password or Kerberos credential
426 or equivalent for current user */
427GLOBAL_EXTERN unsigned int oplockEnabled;
428GLOBAL_EXTERN unsigned int experimEnabled;
429GLOBAL_EXTERN unsigned int lookupCacheEnabled;
430GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
431 with more secure ntlmssp2 challenge/resp */
432GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
433GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
434GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
435GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
436GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
437GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
438GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
439
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
new file mode 100644
index 000000000000..bcd4a6136f08
--- /dev/null
+++ b/fs/cifs/cifspdu.h
@@ -0,0 +1,1987 @@
1/*
2 * fs/cifs/cifspdu.h
3 *
4 * Copyright (c) International Business Machines Corp., 2002
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#ifndef _CIFSPDU_H
23#define _CIFSPDU_H
24
25#include <net/sock.h>
26
27#define CIFS_PROT 0
28#define BAD_PROT CIFS_PROT+1
29
30/* SMB command codes */
31/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
32 (ie which include no useful data other than the SMB error code itself).
33 Knowing this helps avoid response buffer allocations and copy in some cases */
34#define SMB_COM_CREATE_DIRECTORY 0x00 /* trivial response */
35#define SMB_COM_DELETE_DIRECTORY 0x01 /* trivial response */
36#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
37#define SMB_COM_DELETE 0x06 /* trivial response */
38#define SMB_COM_RENAME 0x07 /* trivial response */
39#define SMB_COM_SETATTR 0x09 /* trivial response */
40#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
41#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
42#define SMB_COM_READ_ANDX 0x2E
43#define SMB_COM_WRITE_ANDX 0x2F
44#define SMB_COM_TRANSACTION2 0x32
45#define SMB_COM_TRANSACTION2_SECONDARY 0x33
46#define SMB_COM_FIND_CLOSE2 0x34 /* trivial response */
47#define SMB_COM_TREE_DISCONNECT 0x71 /* trivial response */
48#define SMB_COM_NEGOTIATE 0x72
49#define SMB_COM_SESSION_SETUP_ANDX 0x73
50#define SMB_COM_LOGOFF_ANDX 0x74 /* trivial response */
51#define SMB_COM_TREE_CONNECT_ANDX 0x75
52#define SMB_COM_NT_TRANSACT 0xA0
53#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
54#define SMB_COM_NT_CREATE_ANDX 0xA2
55#define SMB_COM_NT_RENAME 0xA5 /* trivial response */
56
57/* Transact2 subcommand codes */
58#define TRANS2_OPEN 0x00
59#define TRANS2_FIND_FIRST 0x01
60#define TRANS2_FIND_NEXT 0x02
61#define TRANS2_QUERY_FS_INFORMATION 0x03
62#define TRANS2_QUERY_PATH_INFORMATION 0x05
63#define TRANS2_SET_PATH_INFORMATION 0x06
64#define TRANS2_QUERY_FILE_INFORMATION 0x07
65#define TRANS2_SET_FILE_INFORMATION 0x08
66#define TRANS2_GET_DFS_REFERRAL 0x10
67#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
68
69/* NT Transact subcommand codes */
70#define NT_TRANSACT_CREATE 0x01
71#define NT_TRANSACT_IOCTL 0x02
72#define NT_TRANSACT_SET_SECURITY_DESC 0x03
73#define NT_TRANSACT_NOTIFY_CHANGE 0x04
74#define NT_TRANSACT_RENAME 0x05
75#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
76#define NT_TRANSACT_GET_USER_QUOTA 0x07
77#define NT_TRANSACT_SET_USER_QUOTA 0x08
78
79#define MAX_CIFS_HDR_SIZE 256 /* chained NTCreateXReadX will probably be biggest */
80
81/* internal cifs vfs structures */
82/*****************************************************************
83 * All constants go here
84 *****************************************************************
85 */
86
87/*
88 * Starting value for maximum SMB size negotiation
89 */
90#define CIFS_MAX_MSGSIZE (4*4096)
91
92/*
93 * Size of encrypted user password in bytes
94 */
95#define CIFS_ENCPWD_SIZE (16)
96
97/*
98 * Size of the crypto key returned on the negotiate SMB in bytes
99 */
100#define CIFS_CRYPTO_KEY_SIZE (8)
101
102/*
103 * Size of the session key (crypto key encrypted with the password
104 */
105#define CIFS_SESSION_KEY_SIZE (24)
106
107/*
108 * Maximum user name length
109 */
110#define CIFS_UNLEN (20)
111
112/*
113 * Flags on SMB open
114 */
115#define SMBOPEN_WRITE_THROUGH 0x4000
116#define SMBOPEN_DENY_ALL 0x0010
117#define SMBOPEN_DENY_WRITE 0x0020
118#define SMBOPEN_DENY_READ 0x0030
119#define SMBOPEN_DENY_NONE 0x0040
120#define SMBOPEN_READ 0x0000
121#define SMBOPEN_WRITE 0x0001
122#define SMBOPEN_READWRITE 0x0002
123#define SMBOPEN_EXECUTE 0x0003
124
125#define SMBOPEN_OCREATE 0x0010
126#define SMBOPEN_OTRUNC 0x0002
127#define SMBOPEN_OAPPEND 0x0001
128
129/*
130 * SMB flag definitions
131 */
132#define SMBFLG_EXTD_LOCK 0x01 /* server supports lock-read write-unlock primitives */
133#define SMBFLG_RCV_POSTED 0x02 /* obsolete */
134#define SMBFLG_RSVD 0x04
135#define SMBFLG_CASELESS 0x08 /* all pathnames treated as caseless (off implies case sensitive file handling requested) */
136#define SMBFLG_CANONICAL_PATH_FORMAT 0x10 /* obsolete */
137#define SMBFLG_OLD_OPLOCK 0x20 /* obsolete */
138#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40 /* obsolete */
139#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
140
141/*
142 * SMB flag2 definitions
143 */
144#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1) /* can send long (non-8.3) path names in response */
145#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
146#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
147#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
148#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
149#define SMBFLG2_DFS cpu_to_le16(0x1000)
150#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
151#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
152#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
153
154/*
155 * These are the file access permission bits defined in CIFS for the
156 * NTCreateAndX as well as the level 0x107
157 * TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
158 * responds with the AccessFlags.
159 * The AccessFlags specifies the access permissions a caller has to the
160 * file and can have any suitable combination of the following values:
161 */
162
163#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
164#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
165#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
166#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
167 /* with the file can be read */
168#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
169 /* with the file can be written */
170#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
171 /* the file using system paging I/O */
172#define FILE_DELETE_CHILD 0x00000040
173#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
174 /* file can be read */
175#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
176 /* file can be written */
177#define DELETE 0x00010000 /* The file can be deleted */
178#define READ_CONTROL 0x00020000 /* The access control list and */
179 /* ownership associated with the */
180 /* file can be read */
181#define WRITE_DAC 0x00040000 /* The access control list and */
182 /* ownership associated with the */
183 /* file can be written. */
184#define WRITE_OWNER 0x00080000 /* Ownership information associated */
185 /* with the file can be written */
186#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
187 /* synchronize with the completion */
188 /* of an input/output request */
189#define GENERIC_ALL 0x10000000
190#define GENERIC_EXECUTE 0x20000000
191#define GENERIC_WRITE 0x40000000
192#define GENERIC_READ 0x80000000
193 /* In summary - Relevant file */
194 /* access flags from CIFS are */
195 /* file_read_data, file_write_data */
196 /* file_execute, file_read_attributes */
197 /* write_dac, and delete. */
198
199/*
200 * Invalid readdir handle
201 */
202#define CIFS_NO_HANDLE 0xFFFF
203
204/* IPC$ in ASCII */
205#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
206
207/* IPC$ in Unicode */
208#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
209
210/* Unicode Null terminate 2 bytes of 0 */
211#define UNICODE_NULL "\x00\x00"
212#define ASCII_NULL 0x00
213
214/*
215 * Server type values (returned on EnumServer API
216 */
217#define CIFS_SV_TYPE_DC 0x00000008
218#define CIFS_SV_TYPE_BACKDC 0x00000010
219
220/*
221 * Alias type flags (From EnumAlias API call
222 */
223#define CIFS_ALIAS_TYPE_FILE 0x0001
224#define CIFS_SHARE_TYPE_FILE 0x0000
225
226/*
227 * File Attribute flags
228 */
229#define ATTR_READONLY 0x0001
230#define ATTR_HIDDEN 0x0002
231#define ATTR_SYSTEM 0x0004
232#define ATTR_VOLUME 0x0008
233#define ATTR_DIRECTORY 0x0010
234#define ATTR_ARCHIVE 0x0020
235#define ATTR_DEVICE 0x0040
236#define ATTR_NORMAL 0x0080
237#define ATTR_TEMPORARY 0x0100
238#define ATTR_SPARSE 0x0200
239#define ATTR_REPARSE 0x0400
240#define ATTR_COMPRESSED 0x0800
241#define ATTR_OFFLINE 0x1000 /* ie file not immediately available - offline storage */
242#define ATTR_NOT_CONTENT_INDEXED 0x2000
243#define ATTR_ENCRYPTED 0x4000
244#define ATTR_POSIX_SEMANTICS 0x01000000
245#define ATTR_BACKUP_SEMANTICS 0x02000000
246#define ATTR_DELETE_ON_CLOSE 0x04000000
247#define ATTR_SEQUENTIAL_SCAN 0x08000000
248#define ATTR_RANDOM_ACCESS 0x10000000
249#define ATTR_NO_BUFFERING 0x20000000
250#define ATTR_WRITE_THROUGH 0x80000000
251
252/* ShareAccess flags */
253#define FILE_NO_SHARE 0x00000000
254#define FILE_SHARE_READ 0x00000001
255#define FILE_SHARE_WRITE 0x00000002
256#define FILE_SHARE_DELETE 0x00000004
257#define FILE_SHARE_ALL 0x00000007
258
259/* CreateDisposition flags */
260#define FILE_SUPERSEDE 0x00000000
261#define FILE_OPEN 0x00000001
262#define FILE_CREATE 0x00000002
263#define FILE_OPEN_IF 0x00000003
264#define FILE_OVERWRITE 0x00000004
265#define FILE_OVERWRITE_IF 0x00000005
266
267/* CreateOptions */
268#define CREATE_NOT_FILE 0x00000001 /* if set must not be file */
269#define CREATE_WRITE_THROUGH 0x00000002
270#define CREATE_NOT_DIR 0x00000040 /* if set must not be directory */
271#define CREATE_RANDOM_ACCESS 0x00000800
272#define CREATE_DELETE_ON_CLOSE 0x00001000
273#define OPEN_REPARSE_POINT 0x00200000
274
275/* ImpersonationLevel flags */
276#define SECURITY_ANONYMOUS 0
277#define SECURITY_IDENTIFICATION 1
278#define SECURITY_IMPERSONATION 2
279#define SECURITY_DELEGATION 3
280
281/* SecurityFlags */
282#define SECURITY_CONTEXT_TRACKING 0x01
283#define SECURITY_EFFECTIVE_ONLY 0x02
284
285/*
286 * Default PID value, used in all SMBs where the PID is not important
287 */
288#define CIFS_DFT_PID 0x1234
289
290/*
291 * We use the same routine for Copy and Move SMBs. This flag is used to
292 * distinguish
293 */
294#define CIFS_COPY_OP 1
295#define CIFS_RENAME_OP 2
296
297#define GETU16(var) (*((__u16 *)var)) /* BB check for endian issues */
298#define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */
299
300#pragma pack(1)
301
302struct smb_hdr {
303 __u32 smb_buf_length; /* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */
304 __u8 Protocol[4];
305 __u8 Command;
306 union {
307 struct {
308 __u8 ErrorClass;
309 __u8 Reserved;
310 __le16 Error;
311 } DosError;
312 __le32 CifsError;
313 } Status;
314 __u8 Flags;
315 __le16 Flags2; /* note: le */
316 __le16 PidHigh;
317 union {
318 struct {
319 __le32 SequenceNumber; /* le */
320 __u32 Reserved; /* zero */
321 } Sequence;
322 __u8 SecuritySignature[8]; /* le */
323 } Signature;
324 __u8 pad[2];
325 __u16 Tid;
326 __le16 Pid;
327 __u16 Uid;
328 __u16 Mid;
329 __u8 WordCount;
330};
331/* given a pointer to an smb_hdr retrieve the value of byte count */
332#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
333
334/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
335#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
336
337/*
338 * Computer Name Length
339 */
340#define CNLEN 15
341
342/*
343 * Share Name Length @S8A
344 * Note: This length is limited by the SMB used to get @S8A
345 * the Share info. NetShareEnum only returns 13 @S8A
346 * chars, including the null termination. @S8A
347 */
348#define SNLEN 12 /*@S8A */
349
350/*
351 * Comment Length
352 */
353#define MAXCOMMENTLEN 40
354
355/*
356 * The OS/2 maximum path name
357 */
358#define MAX_PATHCONF 256
359
360/*
361 * SMB frame definitions (following must be packed structs)
362 * See the SNIA CIFS Specification for details.
363 *
364 * The Naming convention is the lower case version of the
365 * smb command code name for the struct and this is typedef to the
366 * uppercase version of the same name with the prefix SMB_ removed
367 * for brevity. Although typedefs are not commonly used for
368 * structure definitions in the Linux kernel, their use in the
369 * CIFS standards document, which this code is based on, may
370 * make this one of the cases where typedefs for structures make
371 * sense to improve readability for readers of the standards doc.
372 * Typedefs can always be removed later if they are too distracting
373 * and they are only used for the CIFSs PDUs themselves, not
374 * internal cifs vfs structures
375 *
376 */
377
378typedef struct negotiate_req {
379 struct smb_hdr hdr; /* wct = 0 */
380 __le16 ByteCount;
381 unsigned char DialectsArray[1];
382} NEGOTIATE_REQ;
383
384typedef struct negotiate_rsp {
385 struct smb_hdr hdr; /* wct = 17 */
386 __le16 DialectIndex;
387 __u8 SecurityMode;
388 __le16 MaxMpxCount;
389 __le16 MaxNumberVcs;
390 __le32 MaxBufferSize;
391 __le32 MaxRawSize;
392 __le32 SessionKey;
393 __le32 Capabilities; /* see below */
394 __le32 SystemTimeLow;
395 __le32 SystemTimeHigh;
396 __le16 ServerTimeZone;
397 __u8 EncryptionKeyLength;
398 __u16 ByteCount;
399 union {
400 unsigned char EncryptionKey[1]; /* if cap extended security is off */
401 /* followed by Domain name - if extended security is off */
402 /* followed by 16 bytes of server GUID */
403 /* followed by security blob if cap_extended_security negotiated */
404 struct {
405 unsigned char GUID[16];
406 unsigned char SecurityBlob[1];
407 } extended_response;
408 } u;
409} NEGOTIATE_RSP;
410
411/* SecurityMode bits */
412#define SECMODE_USER 0x01 /* off indicates share level security */
413#define SECMODE_PW_ENCRYPT 0x02
414#define SECMODE_SIGN_ENABLED 0x04 /* SMB security signatures enabled */
415#define SECMODE_SIGN_REQUIRED 0x08 /* SMB security signatures required */
416
417/* Negotiate response Capabilities */
418#define CAP_RAW_MODE 0x00000001
419#define CAP_MPX_MODE 0x00000002
420#define CAP_UNICODE 0x00000004
421#define CAP_LARGE_FILES 0x00000008
422#define CAP_NT_SMBS 0x00000010 /* implies CAP_NT_FIND */
423#define CAP_RPC_REMOTE_APIS 0x00000020
424#define CAP_STATUS32 0x00000040
425#define CAP_LEVEL_II_OPLOCKS 0x00000080
426#define CAP_LOCK_AND_READ 0x00000100
427#define CAP_NT_FIND 0x00000200
428#define CAP_DFS 0x00001000
429#define CAP_INFOLEVEL_PASSTHRU 0x00002000
430#define CAP_LARGE_READ_X 0x00004000
431#define CAP_LARGE_WRITE_X 0x00008000
432#define CAP_UNIX 0x00800000
433#define CAP_RESERVED 0x02000000
434#define CAP_BULK_TRANSFER 0x20000000
435#define CAP_COMPRESSED_DATA 0x40000000
436#define CAP_EXTENDED_SECURITY 0x80000000
437
438typedef union smb_com_session_setup_andx {
439 struct { /* request format */
440 struct smb_hdr hdr; /* wct = 12 */
441 __u8 AndXCommand;
442 __u8 AndXReserved;
443 __le16 AndXOffset;
444 __le16 MaxBufferSize;
445 __le16 MaxMpxCount;
446 __le16 VcNumber;
447 __u32 SessionKey;
448 __le16 SecurityBlobLength;
449 __u32 Reserved;
450 __le32 Capabilities; /* see below */
451 __le16 ByteCount;
452 unsigned char SecurityBlob[1]; /* followed by */
453 /* STRING NativeOS */
454 /* STRING NativeLanMan */
455 } req; /* NTLM request format (with extended security */
456
457 struct { /* request format */
458 struct smb_hdr hdr; /* wct = 13 */
459 __u8 AndXCommand;
460 __u8 AndXReserved;
461 __le16 AndXOffset;
462 __le16 MaxBufferSize;
463 __le16 MaxMpxCount;
464 __le16 VcNumber;
465 __u32 SessionKey;
466 __le16 CaseInsensitivePasswordLength; /* ASCII password length */
467 __le16 CaseSensitivePasswordLength; /* Unicode password length */
468 __u32 Reserved; /* see below */
469 __le32 Capabilities;
470 __le16 ByteCount;
471 unsigned char CaseInsensitivePassword[1]; /* followed by: */
472 /* unsigned char * CaseSensitivePassword; */
473 /* STRING AccountName */
474 /* STRING PrimaryDomain */
475 /* STRING NativeOS */
476 /* STRING NativeLanMan */
477 } req_no_secext; /* NTLM request format (without extended security */
478
479 struct { /* default (NTLM) response format */
480 struct smb_hdr hdr; /* wct = 4 */
481 __u8 AndXCommand;
482 __u8 AndXReserved;
483 __le16 AndXOffset;
484 __le16 Action; /* see below */
485 __le16 SecurityBlobLength;
486 __u16 ByteCount;
487 unsigned char SecurityBlob[1]; /* followed by */
488/* unsigned char * NativeOS; */
489/* unsigned char * NativeLanMan; */
490/* unsigned char * PrimaryDomain; */
491 } resp; /* NTLM response format (with or without extended security */
492
493 struct { /* request format */
494 struct smb_hdr hdr; /* wct = 10 */
495 __u8 AndXCommand;
496 __u8 AndXReserved;
497 __le16 AndXOffset;
498 __le16 MaxBufferSize;
499 __le16 MaxMpxCount;
500 __le16 VcNumber;
501 __u32 SessionKey;
502 __le16 PassswordLength;
503 __u32 Reserved;
504 __le16 ByteCount;
505 unsigned char AccountPassword[1]; /* followed by */
506 /* STRING AccountName */
507 /* STRING PrimaryDomain */
508 /* STRING NativeOS */
509 /* STRING NativeLanMan */
510 } old_req; /* pre-NTLM (LANMAN2.1) request format */
511
512 struct { /* default (NTLM) response format */
513 struct smb_hdr hdr; /* wct = 3 */
514 __u8 AndXCommand;
515 __u8 AndXReserved;
516 __le16 AndXOffset;
517 __le16 Action; /* see below */
518 __u16 ByteCount;
519 unsigned char NativeOS[1]; /* followed by */
520/* unsigned char * NativeLanMan; */
521/* unsigned char * PrimaryDomain; */
522 } old_resp; /* pre-NTLM (LANMAN2.1) response format */
523} SESSION_SETUP_ANDX;
524
525#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
526
527/* Capabilities bits (for NTLM SessSetup request) */
528#define CAP_UNICODE 0x00000004
529#define CAP_LARGE_FILES 0x00000008
530#define CAP_NT_SMBS 0x00000010
531#define CAP_STATUS32 0x00000040
532#define CAP_LEVEL_II_OPLOCKS 0x00000080
533#define CAP_NT_FIND 0x00000200 /* reserved should be zero (presumably because NT_SMBs implies the same thing) */
534#define CAP_BULK_TRANSFER 0x20000000
535#define CAP_EXTENDED_SECURITY 0x80000000
536
537/* Action bits */
538#define GUEST_LOGIN 1
539
540typedef struct smb_com_tconx_req {
541 struct smb_hdr hdr; /* wct = 4 */
542 __u8 AndXCommand;
543 __u8 AndXReserved;
544 __le16 AndXOffset;
545 __le16 Flags; /* see below */
546 __le16 PasswordLength;
547 __le16 ByteCount;
548 unsigned char Password[1]; /* followed by */
549/* STRING Path *//* \\server\share name */
550 /* STRING Service */
551} TCONX_REQ;
552
553typedef struct smb_com_tconx_rsp {
554 struct smb_hdr hdr; /* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
555 __u8 AndXCommand;
556 __u8 AndXReserved;
557 __le16 AndXOffset;
558 __le16 OptionalSupport; /* see below */
559 __u16 ByteCount;
560 unsigned char Service[1]; /* always ASCII, not Unicode */
561 /* STRING NativeFileSystem */
562} TCONX_RSP;
563
564/* tree connect Flags */
565#define DISCONNECT_TID 0x0001
566#define TCON_EXTENDED_SECINFO 0x0008
567/* OptionalSupport bits */
568#define SMB_SUPPORT_SEARCH_BITS 0x0001 /* must have bits (exclusive searches suppt. */
569#define SMB_SHARE_IS_IN_DFS 0x0002
570
571typedef struct smb_com_logoff_andx_req {
572 struct smb_hdr hdr; /* wct = 2 */
573 __u8 AndXCommand;
574 __u8 AndXReserved;
575 __u16 AndXOffset;
576 __u16 ByteCount;
577} LOGOFF_ANDX_REQ;
578
579typedef struct smb_com_logoff_andx_rsp {
580 struct smb_hdr hdr; /* wct = 2 */
581 __u8 AndXCommand;
582 __u8 AndXReserved;
583 __u16 AndXOffset;
584 __u16 ByteCount;
585} LOGOFF_ANDX_RSP;
586
587typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
588 struct {
589 struct smb_hdr hdr; /* wct = 0 */
590 __u16 ByteCount; /* bcc = 0 */
591 } req;
592 struct {
593 struct smb_hdr hdr; /* wct = 0 */
594 __u16 ByteCount; /* bcc = 0 */
595 } resp;
596} TREE_DISCONNECT;
597
598typedef struct smb_com_close_req {
599 struct smb_hdr hdr; /* wct = 3 */
600 __u16 FileID;
601 __u32 LastWriteTime; /* should be zero */
602 __u16 ByteCount; /* 0 */
603} CLOSE_REQ;
604
605typedef struct smb_com_close_rsp {
606 struct smb_hdr hdr; /* wct = 0 */
607 __u16 ByteCount; /* bct = 0 */
608} CLOSE_RSP;
609
610typedef struct smb_com_findclose_req {
611 struct smb_hdr hdr; /* wct = 1 */
612 __u16 FileID;
613 __u16 ByteCount; /* 0 */
614} FINDCLOSE_REQ;
615
616/* OpenFlags */
617#define REQ_OPLOCK 0x00000002
618#define REQ_BATCHOPLOCK 0x00000004
619#define REQ_OPENDIRONLY 0x00000008
620
621typedef struct smb_com_open_req { /* also handles create */
622 struct smb_hdr hdr; /* wct = 24 */
623 __u8 AndXCommand;
624 __u8 AndXReserved;
625 __le16 AndXOffset;
626 __u8 Reserved; /* Must Be Zero */
627 __le16 NameLength;
628 __le32 OpenFlags;
629 __le32 RootDirectoryFid;
630 __le32 DesiredAccess;
631 __le64 AllocationSize;
632 __le32 FileAttributes;
633 __le32 ShareAccess;
634 __le32 CreateDisposition;
635 __le32 CreateOptions;
636 __le32 ImpersonationLevel;
637 __u8 SecurityFlags;
638 __le16 ByteCount;
639 char fileName[1];
640} OPEN_REQ;
641
642/* open response: oplock levels */
643#define OPLOCK_NONE 0
644#define OPLOCK_EXCLUSIVE 1
645#define OPLOCK_BATCH 2
646#define OPLOCK_READ 3 /* level 2 oplock */
647
648/* open response for CreateAction shifted left */
649#define CIFS_CREATE_ACTION 0x20000 /* file created */
650
651typedef struct smb_com_open_rsp {
652 struct smb_hdr hdr; /* wct = 34 BB */
653 __u8 AndXCommand;
654 __u8 AndXReserved;
655 __le16 AndXOffset;
656 __u8 OplockLevel;
657 __u16 Fid;
658 __le32 CreateAction;
659 __le64 CreationTime;
660 __le64 LastAccessTime;
661 __le64 LastWriteTime;
662 __le64 ChangeTime;
663 __le32 FileAttributes;
664 __le64 AllocationSize;
665 __le64 EndOfFile;
666 __le16 FileType;
667 __le16 DeviceState;
668 __u8 DirectoryFlag;
669 __u16 ByteCount; /* bct = 0 */
670} OPEN_RSP;
671
672typedef struct smb_com_write_req {
673 struct smb_hdr hdr; /* wct = 14 */
674 __u8 AndXCommand;
675 __u8 AndXReserved;
676 __le16 AndXOffset;
677 __u16 Fid;
678 __le32 OffsetLow;
679 __u32 Reserved;
680 __le16 WriteMode;
681 __le16 Remaining;
682 __le16 DataLengthHigh;
683 __le16 DataLengthLow;
684 __le16 DataOffset;
685 __le32 OffsetHigh;
686 __le16 ByteCount;
687 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
688 char Data[0];
689} WRITE_REQ;
690
691typedef struct smb_com_write_rsp {
692 struct smb_hdr hdr; /* wct = 6 */
693 __u8 AndXCommand;
694 __u8 AndXReserved;
695 __le16 AndXOffset;
696 __le16 Count;
697 __le16 Remaining;
698 __le16 CountHigh;
699 __u16 Reserved;
700 __u16 ByteCount;
701} WRITE_RSP;
702
703typedef struct smb_com_read_req {
704 struct smb_hdr hdr; /* wct = 12 */
705 __u8 AndXCommand;
706 __u8 AndXReserved;
707 __le16 AndXOffset;
708 __u16 Fid;
709 __le32 OffsetLow;
710 __le16 MaxCount;
711 __le16 MinCount; /* obsolete */
712 __le32 MaxCountHigh;
713 __le16 Remaining;
714 __le32 OffsetHigh;
715 __le16 ByteCount;
716} READ_REQ;
717
718typedef struct smb_com_read_rsp {
719 struct smb_hdr hdr; /* wct = 12 */
720 __u8 AndXCommand;
721 __u8 AndXReserved;
722 __le16 AndXOffset;
723 __le16 Remaining;
724 __le16 DataCompactionMode;
725 __le16 Reserved;
726 __le16 DataLength;
727 __le16 DataOffset;
728 __le16 DataLengthHigh;
729 __u64 Reserved2;
730 __u16 ByteCount;
731 __u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
732 char Data[1];
733} READ_RSP;
734
735typedef struct locking_andx_range {
736 __le16 Pid;
737 __le16 Pad;
738 __le32 OffsetHigh;
739 __le32 OffsetLow;
740 __le32 LengthHigh;
741 __le32 LengthLow;
742} LOCKING_ANDX_RANGE;
743
744#define LOCKING_ANDX_SHARED_LOCK 0x01
745#define LOCKING_ANDX_OPLOCK_RELEASE 0x02
746#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
747#define LOCKING_ANDX_CANCEL_LOCK 0x08
748#define LOCKING_ANDX_LARGE_FILES 0x10 /* always on for us */
749
750typedef struct smb_com_lock_req {
751 struct smb_hdr hdr; /* wct = 8 */
752 __u8 AndXCommand;
753 __u8 AndXReserved;
754 __le16 AndXOffset;
755 __u16 Fid;
756 __u8 LockType;
757 __u8 OplockLevel;
758 __le32 Timeout;
759 __le16 NumberOfUnlocks;
760 __le16 NumberOfLocks;
761 __le16 ByteCount;
762 LOCKING_ANDX_RANGE Locks[1];
763} LOCK_REQ;
764
765typedef struct smb_com_lock_rsp {
766 struct smb_hdr hdr; /* wct = 2 */
767 __u8 AndXCommand;
768 __u8 AndXReserved;
769 __le16 AndXOffset;
770 __u16 ByteCount;
771} LOCK_RSP;
772
773typedef struct smb_com_rename_req {
774 struct smb_hdr hdr; /* wct = 1 */
775 __le16 SearchAttributes; /* target file attributes */
776 __le16 ByteCount;
777 __u8 BufferFormat; /* 4 = ASCII or Unicode */
778 unsigned char OldFileName[1];
779 /* followed by __u8 BufferFormat2 */
780 /* followed by NewFileName */
781} RENAME_REQ;
782
783 /* copy request flags */
784#define COPY_MUST_BE_FILE 0x0001
785#define COPY_MUST_BE_DIR 0x0002
786#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
787#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
788#define COPY_VERIFY_WRITES 0x0010
789#define COPY_TREE 0x0020
790
791typedef struct smb_com_copy_req {
792 struct smb_hdr hdr; /* wct = 3 */
793 __u16 Tid2;
794 __le16 OpenFunction;
795 __le16 Flags;
796 __le16 ByteCount;
797 __u8 BufferFormat; /* 4 = ASCII or Unicode */
798 unsigned char OldFileName[1];
799 /* followed by __u8 BufferFormat2 */
800 /* followed by NewFileName string */
801} COPY_REQ;
802
803typedef struct smb_com_copy_rsp {
804 struct smb_hdr hdr; /* wct = 1 */
805 __le16 CopyCount; /* number of files copied */
806 __u16 ByteCount; /* may be zero */
807 __u8 BufferFormat; /* 0x04 - only present if errored file follows */
808 unsigned char ErrorFileName[1]; /* only present if error in copy */
809} COPY_RSP;
810
811#define CREATE_HARD_LINK 0x103
812#define MOVEFILE_COPY_ALLOWED 0x0002
813#define MOVEFILE_REPLACE_EXISTING 0x0001
814
815typedef struct smb_com_nt_rename_req { /* A5 - also used for create hardlink */
816 struct smb_hdr hdr; /* wct = 4 */
817 __le16 SearchAttributes; /* target file attributes */
818 __le16 Flags; /* spec says Information Level */
819 __le32 ClusterCount;
820 __le16 ByteCount;
821 __u8 BufferFormat; /* 4 = ASCII or Unicode */
822 unsigned char OldFileName[1];
823 /* followed by __u8 BufferFormat2 */
824 /* followed by NewFileName */
825} NT_RENAME_REQ;
826
827typedef struct smb_com_rename_rsp {
828 struct smb_hdr hdr; /* wct = 0 */
829 __u16 ByteCount; /* bct = 0 */
830} RENAME_RSP;
831
832typedef struct smb_com_delete_file_req {
833 struct smb_hdr hdr; /* wct = 1 */
834 __le16 SearchAttributes;
835 __le16 ByteCount;
836 __u8 BufferFormat; /* 4 = ASCII */
837 unsigned char fileName[1];
838} DELETE_FILE_REQ;
839
840typedef struct smb_com_delete_file_rsp {
841 struct smb_hdr hdr; /* wct = 0 */
842 __u16 ByteCount; /* bct = 0 */
843} DELETE_FILE_RSP;
844
845typedef struct smb_com_delete_directory_req {
846 struct smb_hdr hdr; /* wct = 0 */
847 __le16 ByteCount;
848 __u8 BufferFormat; /* 4 = ASCII */
849 unsigned char DirName[1];
850} DELETE_DIRECTORY_REQ;
851
852typedef struct smb_com_delete_directory_rsp {
853 struct smb_hdr hdr; /* wct = 0 */
854 __u16 ByteCount; /* bct = 0 */
855} DELETE_DIRECTORY_RSP;
856
857typedef struct smb_com_create_directory_req {
858 struct smb_hdr hdr; /* wct = 0 */
859 __le16 ByteCount;
860 __u8 BufferFormat; /* 4 = ASCII */
861 unsigned char DirName[1];
862} CREATE_DIRECTORY_REQ;
863
864typedef struct smb_com_create_directory_rsp {
865 struct smb_hdr hdr; /* wct = 0 */
866 __u16 ByteCount; /* bct = 0 */
867} CREATE_DIRECTORY_RSP;
868
869typedef struct smb_com_setattr_req {
870 struct smb_hdr hdr; /* wct = 8 */
871 __le16 attr;
872 __le16 time_low;
873 __le16 time_high;
874 __le16 reserved[5]; /* must be zero */
875 __u16 ByteCount;
876 __u8 BufferFormat; /* 4 = ASCII */
877 unsigned char fileName[1];
878} SETATTR_REQ;
879
880typedef struct smb_com_setattr_rsp {
881 struct smb_hdr hdr; /* wct = 0 */
882 __u16 ByteCount; /* bct = 0 */
883} SETATTR_RSP;
884
885/* empty wct response to setattr */
886
887/***************************************************/
888/* NT Transact structure defintions follow */
889/* Currently only ioctl and notify are implemented */
890/***************************************************/
891typedef struct smb_com_transaction_ioctl_req {
892 struct smb_hdr hdr; /* wct = 23 */
893 __u8 MaxSetupCount;
894 __u16 Reserved;
895 __le32 TotalParameterCount;
896 __le32 TotalDataCount;
897 __le32 MaxParameterCount;
898 __le32 MaxDataCount;
899 __le32 ParameterCount;
900 __le32 ParameterOffset;
901 __le32 DataCount;
902 __le32 DataOffset;
903 __u8 SetupCount; /* four setup words follow subcommand */
904 /* SNIA spec incorrectly included spurious pad here */
905 __le16 SubCommand;/* 2 = IOCTL/FSCTL */
906 __le32 FunctionCode;
907 __u16 Fid;
908 __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
909 __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
910 __le16 ByteCount;
911 __u8 Pad[3];
912 __u8 Data[1];
913} TRANSACT_IOCTL_REQ;
914
915typedef struct smb_com_transaction_ioctl_rsp {
916 struct smb_hdr hdr; /* wct = 19 */
917 __u8 Reserved[3];
918 __le32 TotalParameterCount;
919 __le32 TotalDataCount;
920 __le32 ParameterCount;
921 __le32 ParameterOffset;
922 __le32 ParameterDisplacement;
923 __le32 DataCount;
924 __le32 DataOffset;
925 __le32 DataDisplacement;
926 __u8 SetupCount; /* 1 */
927 __le16 ReturnedDataLen;
928 __u16 ByteCount;
929 __u8 Pad[3];
930} TRANSACT_IOCTL_RSP;
931
932typedef struct smb_com_transaction_change_notify_req {
933 struct smb_hdr hdr; /* wct = 23 */
934 __u8 MaxSetupCount;
935 __u16 Reserved;
936 __le32 TotalParameterCount;
937 __le32 TotalDataCount;
938 __le32 MaxParameterCount;
939 __le32 MaxDataCount;
940 __le32 ParameterCount;
941 __le32 ParameterOffset;
942 __le32 DataCount;
943 __le32 DataOffset;
944 __u8 SetupCount; /* four setup words follow subcommand */
945 /* SNIA spec incorrectly included spurious pad here */
946 __le16 SubCommand;/* 4 = Change Notify */
947 __le32 CompletionFilter; /* operation to monitor */
948 __u16 Fid;
949 __u8 WatchTree; /* 1 = Monitor subdirectories */
950 __u8 Reserved2;
951 __le16 ByteCount;
952/* __u8 Pad[3];*/
953/* __u8 Data[1];*/
954} TRANSACT_CHANGE_NOTIFY_REQ;
955
956typedef struct smb_com_transaction_change_notify_rsp {
957 struct smb_hdr hdr; /* wct = 18 */
958 __u8 Reserved[3];
959 __le32 TotalParameterCount;
960 __le32 TotalDataCount;
961 __le32 ParameterCount;
962 __le32 ParameterOffset;
963 __le32 ParameterDisplacement;
964 __le32 DataCount;
965 __le32 DataOffset;
966 __le32 DataDisplacement;
967 __u8 SetupCount; /* 0 */
968 __u16 ByteCount;
969 /* __u8 Pad[3]; */
970} TRANSACT_CHANGE_NOTIFY_RSP;
971/* Completion Filter flags for Notify */
972#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
973#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
974#define FILE_NOTIFY_CHANGE_NAME 0x00000003
975#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
976#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
977#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
978#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
979#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
980#define FILE_NOTIFY_CHANGE_EA 0x00000080
981#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
982#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
983#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
984#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
985
986#define FILE_ACTION_ADDED 0x00000001
987#define FILE_ACTION_REMOVED 0x00000002
988#define FILE_ACTION_MODIFIED 0x00000003
989#define FILE_ACTION_RENAMED_OLD_NAME 0x00000004
990#define FILE_ACTION_RENAMED_NEW_NAME 0x00000005
991#define FILE_ACTION_ADDED_STREAM 0x00000006
992#define FILE_ACTION_REMOVED_STREAM 0x00000007
993#define FILE_ACTION_MODIFIED_STREAM 0x00000008
994
995/* response contains array of the following structures */
996struct file_notify_information {
997 __le32 NextEntryOffset;
998 __le32 Action;
999 __le32 FileNameLength;
1000 __u8 FileName[0];
1001};
1002
1003struct reparse_data {
1004 __u32 ReparseTag;
1005 __u16 ReparseDataLength;
1006 __u16 Reserved;
1007 __u16 AltNameOffset;
1008 __u16 AltNameLen;
1009 __u16 TargetNameOffset;
1010 __u16 TargetNameLen;
1011 char LinkNamesBuf[1];
1012};
1013
1014struct cifs_quota_data {
1015 __u32 rsrvd1; /* 0 */
1016 __u32 sid_size;
1017 __u64 rsrvd2; /* 0 */
1018 __u64 space_used;
1019 __u64 soft_limit;
1020 __u64 hard_limit;
1021 char sid[1]; /* variable size? */
1022};
1023
1024/* quota sub commands */
1025#define QUOTA_LIST_CONTINUE 0
1026#define QUOTA_LIST_START 0x100
1027#define QUOTA_FOR_SID 0x101
1028
1029struct trans2_req {
1030 /* struct smb_hdr hdr precedes. Set wct = 14+ */
1031 __le16 TotalParameterCount;
1032 __le16 TotalDataCount;
1033 __le16 MaxParameterCount;
1034 __le16 MaxDataCount;
1035 __u8 MaxSetupCount;
1036 __u8 Reserved;
1037 __le16 Flags;
1038 __le32 Timeout;
1039 __u16 Reserved2;
1040 __le16 ParameterCount;
1041 __le16 ParameterOffset;
1042 __le16 DataCount;
1043 __le16 DataOffset;
1044 __u8 SetupCount;
1045 __u8 Reserved3;
1046 __le16 SubCommand; /* 1st setup word - SetupCount words follow */
1047 __le16 ByteCount;
1048};
1049
1050struct smb_t2_req {
1051 struct smb_hdr hdr;
1052 struct trans2_req t2_req;
1053};
1054
1055struct trans2_resp {
1056 /* struct smb_hdr hdr precedes. Note wct = 10 + setup count */
1057 __le16 TotalParameterCount;
1058 __le16 TotalDataCount;
1059 __u16 Reserved;
1060 __le16 ParameterCount;
1061 __le16 ParameterOffset;
1062 __le16 ParameterDisplacement;
1063 __le16 DataCount;
1064 __le16 DataOffset;
1065 __le16 DataDisplacement;
1066 __u8 SetupCount;
1067 __u8 Reserved1;
1068 /* SetupWords[SetupCount];
1069 __u16 ByteCount;
1070 __u16 Reserved2;*/
1071 /* data area follows */
1072};
1073
1074struct smb_t2_rsp {
1075 struct smb_hdr hdr;
1076 struct trans2_resp t2_rsp;
1077};
1078
1079/* PathInfo/FileInfo infolevels */
1080#define SMB_INFO_STANDARD 1
1081#define SMB_SET_FILE_EA 2
1082#define SMB_QUERY_FILE_EA_SIZE 2
1083#define SMB_INFO_QUERY_EAS_FROM_LIST 3
1084#define SMB_INFO_QUERY_ALL_EAS 4
1085#define SMB_INFO_IS_NAME_VALID 6
1086#define SMB_QUERY_FILE_BASIC_INFO 0x101
1087#define SMB_QUERY_FILE_STANDARD_INFO 0x102
1088#define SMB_QUERY_FILE_EA_INFO 0x103
1089#define SMB_QUERY_FILE_NAME_INFO 0x104
1090#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105
1091#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106
1092#define SMB_QUERY_FILE_ALL_INFO 0x107
1093#define SMB_QUERY_ALT_NAME_INFO 0x108
1094#define SMB_QUERY_FILE_STREAM_INFO 0x109
1095#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
1096#define SMB_QUERY_FILE_UNIX_BASIC 0x200
1097#define SMB_QUERY_FILE_UNIX_LINK 0x201
1098#define SMB_QUERY_POSIX_ACL 0x204
1099#define SMB_QUERY_XATTR 0x205
1100#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
1101#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
1102#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
1103#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
1104#define SMB_QUERY_FILE_POSITION_INFO 0x3f6
1105#define SMB_QUERY_FILE_MODE_INFO 0x3f8
1106#define SMB_QUERY_FILE_ALGN_INFO 0x3f9
1107
1108
1109#define SMB_SET_FILE_BASIC_INFO 0x101
1110#define SMB_SET_FILE_DISPOSITION_INFO 0x102
1111#define SMB_SET_FILE_ALLOCATION_INFO 0x103
1112#define SMB_SET_FILE_END_OF_FILE_INFO 0x104
1113#define SMB_SET_FILE_UNIX_BASIC 0x200
1114#define SMB_SET_FILE_UNIX_LINK 0x201
1115#define SMB_SET_FILE_UNIX_HLINK 0x203
1116#define SMB_SET_POSIX_ACL 0x204
1117#define SMB_SET_XATTR 0x205
1118#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
1119#define SMB_SET_FILE_BASIC_INFO2 0x3ec
1120#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
1121#define SMB_FILE_ALL_INFO2 0x3fa
1122#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
1123#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
1124#define SMB_FILE_MOVE_CLUSTER_INFO 0x407
1125#define SMB_FILE_QUOTA_INFO 0x408
1126#define SMB_FILE_REPARSEPOINT_INFO 0x409
1127#define SMB_FILE_MAXIMUM_INFO 0x40d
1128
1129/* Find File infolevels */
1130#define SMB_FIND_FILE_DIRECTORY_INFO 0x101
1131#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
1132#define SMB_FIND_FILE_NAMES_INFO 0x103
1133#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
1134#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105
1135#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106
1136#define SMB_FIND_FILE_UNIX 0x202
1137
1138typedef struct smb_com_transaction2_qpi_req {
1139 struct smb_hdr hdr; /* wct = 14+ */
1140 __le16 TotalParameterCount;
1141 __le16 TotalDataCount;
1142 __le16 MaxParameterCount;
1143 __le16 MaxDataCount;
1144 __u8 MaxSetupCount;
1145 __u8 Reserved;
1146 __le16 Flags;
1147 __le32 Timeout;
1148 __u16 Reserved2;
1149 __le16 ParameterCount;
1150 __le16 ParameterOffset;
1151 __le16 DataCount;
1152 __le16 DataOffset;
1153 __u8 SetupCount;
1154 __u8 Reserved3;
1155 __le16 SubCommand; /* one setup word */
1156 __le16 ByteCount;
1157 __u8 Pad;
1158 __le16 InformationLevel;
1159 __u32 Reserved4;
1160 char FileName[1];
1161} TRANSACTION2_QPI_REQ;
1162
1163typedef struct smb_com_transaction2_qpi_rsp {
1164 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1165 struct trans2_resp t2;
1166 __u16 ByteCount;
1167 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
1168} TRANSACTION2_QPI_RSP;
1169
1170typedef struct smb_com_transaction2_spi_req {
1171 struct smb_hdr hdr; /* wct = 15 */
1172 __le16 TotalParameterCount;
1173 __le16 TotalDataCount;
1174 __le16 MaxParameterCount;
1175 __le16 MaxDataCount;
1176 __u8 MaxSetupCount;
1177 __u8 Reserved;
1178 __le16 Flags;
1179 __le32 Timeout;
1180 __u16 Reserved2;
1181 __le16 ParameterCount;
1182 __le16 ParameterOffset;
1183 __le16 DataCount;
1184 __le16 DataOffset;
1185 __u8 SetupCount;
1186 __u8 Reserved3;
1187 __le16 SubCommand; /* one setup word */
1188 __le16 ByteCount;
1189 __u8 Pad;
1190 __u16 Pad1;
1191 __le16 InformationLevel;
1192 __u32 Reserved4;
1193 char FileName[1];
1194} TRANSACTION2_SPI_REQ;
1195
1196typedef struct smb_com_transaction2_spi_rsp {
1197 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1198 struct trans2_resp t2;
1199 __u16 ByteCount;
1200 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
1201} TRANSACTION2_SPI_RSP;
1202
1203struct set_file_rename {
1204 __le32 overwrite; /* 1 = overwrite dest */
1205 __u32 root_fid; /* zero */
1206 __le32 target_name_len;
1207 char target_name[0]; /* Must be unicode */
1208};
1209
1210struct smb_com_transaction2_sfi_req {
1211 struct smb_hdr hdr; /* wct = 15 */
1212 __le16 TotalParameterCount;
1213 __le16 TotalDataCount;
1214 __le16 MaxParameterCount;
1215 __le16 MaxDataCount;
1216 __u8 MaxSetupCount;
1217 __u8 Reserved;
1218 __le16 Flags;
1219 __le32 Timeout;
1220 __u16 Reserved2;
1221 __le16 ParameterCount;
1222 __le16 ParameterOffset;
1223 __le16 DataCount;
1224 __le16 DataOffset;
1225 __u8 SetupCount;
1226 __u8 Reserved3;
1227 __le16 SubCommand; /* one setup word */
1228 __le16 ByteCount;
1229 __u8 Pad;
1230 __u16 Pad1;
1231 __u16 Fid;
1232 __le16 InformationLevel;
1233 __u16 Reserved4;
1234};
1235
1236struct smb_com_transaction2_sfi_rsp {
1237 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1238 struct trans2_resp t2;
1239 __u16 ByteCount;
1240 __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
1241};
1242
1243
1244/*
1245 * Flags on T2 FINDFIRST and FINDNEXT
1246 */
1247#define CIFS_SEARCH_CLOSE_ALWAYS 0x0001
1248#define CIFS_SEARCH_CLOSE_AT_END 0x0002
1249#define CIFS_SEARCH_RETURN_RESUME 0x0004
1250#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
1251#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
1252
1253/*
1254 * Size of the resume key on FINDFIRST and FINDNEXT calls
1255 */
1256#define CIFS_SMB_RESUME_KEY_SIZE 4
1257
1258typedef struct smb_com_transaction2_ffirst_req {
1259 struct smb_hdr hdr; /* wct = 15 */
1260 __le16 TotalParameterCount;
1261 __le16 TotalDataCount;
1262 __le16 MaxParameterCount;
1263 __le16 MaxDataCount;
1264 __u8 MaxSetupCount;
1265 __u8 Reserved;
1266 __le16 Flags;
1267 __le32 Timeout;
1268 __u16 Reserved2;
1269 __le16 ParameterCount;
1270 __le16 ParameterOffset;
1271 __le16 DataCount;
1272 __le16 DataOffset;
1273 __u8 SetupCount; /* one */
1274 __u8 Reserved3;
1275 __le16 SubCommand; /* TRANS2_FIND_FIRST */
1276 __le16 ByteCount;
1277 __u8 Pad;
1278 __le16 SearchAttributes;
1279 __le16 SearchCount;
1280 __le16 SearchFlags;
1281 __le16 InformationLevel;
1282 __le32 SearchStorageType;
1283 char FileName[1];
1284} TRANSACTION2_FFIRST_REQ;
1285
1286typedef struct smb_com_transaction2_ffirst_rsp {
1287 struct smb_hdr hdr; /* wct = 10 */
1288 struct trans2_resp t2;
1289 __u16 ByteCount;
1290} TRANSACTION2_FFIRST_RSP;
1291
1292typedef struct smb_com_transaction2_ffirst_rsp_parms {
1293 __u16 SearchHandle;
1294 __le16 SearchCount;
1295 __le16 EndofSearch;
1296 __le16 EAErrorOffset;
1297 __le16 LastNameOffset;
1298} T2_FFIRST_RSP_PARMS;
1299
1300typedef struct smb_com_transaction2_fnext_req {
1301 struct smb_hdr hdr; /* wct = 15 */
1302 __le16 TotalParameterCount;
1303 __le16 TotalDataCount;
1304 __le16 MaxParameterCount;
1305 __le16 MaxDataCount;
1306 __u8 MaxSetupCount;
1307 __u8 Reserved;
1308 __le16 Flags;
1309 __le32 Timeout;
1310 __u16 Reserved2;
1311 __le16 ParameterCount;
1312 __le16 ParameterOffset;
1313 __le16 DataCount;
1314 __le16 DataOffset;
1315 __u8 SetupCount; /* one */
1316 __u8 Reserved3;
1317 __le16 SubCommand; /* TRANS2_FIND_NEXT */
1318 __le16 ByteCount;
1319 __u8 Pad;
1320 __u16 SearchHandle;
1321 __le16 SearchCount;
1322 __le16 InformationLevel;
1323 __u32 ResumeKey;
1324 __le16 SearchFlags;
1325 char ResumeFileName[1];
1326} TRANSACTION2_FNEXT_REQ;
1327
1328typedef struct smb_com_transaction2_fnext_rsp {
1329 struct smb_hdr hdr; /* wct = 10 */
1330 struct trans2_resp t2;
1331 __u16 ByteCount;
1332} TRANSACTION2_FNEXT_RSP;
1333
1334typedef struct smb_com_transaction2_fnext_rsp_parms {
1335 __le16 SearchCount;
1336 __le16 EndofSearch;
1337 __le16 EAErrorOffset;
1338 __le16 LastNameOffset;
1339} T2_FNEXT_RSP_PARMS;
1340
1341/* QFSInfo Levels */
1342#define SMB_INFO_ALLOCATION 1
1343#define SMB_INFO_VOLUME 2
1344#define SMB_QUERY_FS_VOLUME_INFO 0x102
1345#define SMB_QUERY_FS_SIZE_INFO 0x103
1346#define SMB_QUERY_FS_DEVICE_INFO 0x104
1347#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
1348#define SMB_QUERY_CIFS_UNIX_INFO 0x200
1349#define SMB_QUERY_POSIX_FS_INFO 0x201
1350#define SMB_QUERY_LABEL_INFO 0x3ea
1351#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
1352#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
1353#define SMB_QUERY_OBJECTID_INFO 0x3f0
1354
1355typedef struct smb_com_transaction2_qfsi_req {
1356 struct smb_hdr hdr; /* wct = 14+ */
1357 __le16 TotalParameterCount;
1358 __le16 TotalDataCount;
1359 __le16 MaxParameterCount;
1360 __le16 MaxDataCount;
1361 __u8 MaxSetupCount;
1362 __u8 Reserved;
1363 __le16 Flags;
1364 __le32 Timeout;
1365 __u16 Reserved2;
1366 __le16 ParameterCount;
1367 __le16 ParameterOffset;
1368 __le16 DataCount;
1369 __le16 DataOffset;
1370 __u8 SetupCount;
1371 __u8 Reserved3;
1372 __le16 SubCommand; /* one setup word */
1373 __le16 ByteCount;
1374 __u8 Pad;
1375 __le16 InformationLevel;
1376} TRANSACTION2_QFSI_REQ;
1377
1378typedef struct smb_com_transaction_qfsi_rsp {
1379 struct smb_hdr hdr; /* wct = 10 + SetupCount */
1380 struct trans2_resp t2;
1381 __u16 ByteCount;
1382 __u8 Pad; /* may be three bytes *//* followed by data area */
1383} TRANSACTION2_QFSI_RSP;
1384
1385typedef struct smb_com_transaction2_get_dfs_refer_req {
1386 struct smb_hdr hdr; /* wct = 15 */
1387 __le16 TotalParameterCount;
1388 __le16 TotalDataCount;
1389 __le16 MaxParameterCount;
1390 __le16 MaxDataCount;
1391 __u8 MaxSetupCount;
1392 __u8 Reserved;
1393 __le16 Flags;
1394 __le32 Timeout;
1395 __u16 Reserved2;
1396 __le16 ParameterCount;
1397 __le16 ParameterOffset;
1398 __le16 DataCount;
1399 __le16 DataOffset;
1400 __u8 SetupCount;
1401 __u8 Reserved3;
1402 __le16 SubCommand; /* one setup word */
1403 __le16 ByteCount;
1404 __u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
1405 __le16 MaxReferralLevel;
1406 char RequestFileName[1];
1407} TRANSACTION2_GET_DFS_REFER_REQ;
1408
1409typedef struct dfs_referral_level_3 {
1410 __le16 VersionNumber;
1411 __le16 ReferralSize;
1412 __le16 ServerType; /* 0x0001 = CIFS server */
1413 __le16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
1414 __le16 TimeToLive;
1415 __le16 Proximity;
1416 __le16 DfsPathOffset;
1417 __le16 DfsAlternatePathOffset;
1418 __le16 NetworkAddressOffset;
1419} REFERRAL3;
1420
1421typedef struct smb_com_transaction_get_dfs_refer_rsp {
1422 struct smb_hdr hdr; /* wct = 10 */
1423 struct trans2_resp t2;
1424 __u16 ByteCount;
1425 __u8 Pad;
1426 __le16 PathConsumed;
1427 __le16 NumberOfReferrals;
1428 __le16 DFSFlags;
1429 __u16 Pad2;
1430 REFERRAL3 referrals[1]; /* array of level 3 dfs_referral structures */
1431 /* followed by the strings pointed to by the referral structures */
1432} TRANSACTION2_GET_DFS_REFER_RSP;
1433
1434/* DFS Flags */
1435#define DFSREF_REFERRAL_SERVER 0x0001
1436#define DFSREF_STORAGE_SERVER 0x0002
1437
1438/* IOCTL information */
1439/* List of ioctl function codes that look to be of interest to remote clients like this. */
1440/* Need to do some experimentation to make sure they all work remotely. */
1441/* Some of the following such as the encryption/compression ones would be */
1442/* invoked from tools via a specialized hook into the VFS rather than via the */
1443/* standard vfs entry points */
1444#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
1445#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
1446#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
1447#define FSCTL_LOCK_VOLUME 0x00090018
1448#define FSCTL_UNLOCK_VOLUME 0x0009001C
1449#define FSCTL_GET_COMPRESSION 0x0009003C
1450#define FSCTL_SET_COMPRESSION 0x0009C040
1451#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C
1452#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
1453#define FSCTL_SET_REPARSE_POINT 0x000900A4
1454#define FSCTL_GET_REPARSE_POINT 0x000900A8
1455#define FSCTL_DELETE_REPARSE_POINT 0x000900AC
1456#define FSCTL_SET_SPARSE 0x000900C4
1457#define FSCTL_SET_ZERO_DATA 0x000900C8
1458#define FSCTL_SET_ENCRYPTION 0x000900D7
1459#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB
1460#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF
1461#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3
1462#define FSCTL_SIS_COPYFILE 0x00090100
1463#define FSCTL_SIS_LINK_FILES 0x0009C104
1464
1465#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
1466#define IO_REPARSE_TAG_HSM 0xC0000004
1467#define IO_REPARSE_TAG_SIS 0x80000007
1468
1469/*
1470 ************************************************************************
1471 * All structs for everything above the SMB PDUs themselves
1472 * (such as the T2 level specific data) go here
1473 ************************************************************************
1474 */
1475
1476/*
1477 * Information on a server
1478 */
1479
1480struct serverInfo {
1481 char name[16];
1482 unsigned char versionMajor;
1483 unsigned char versionMinor;
1484 unsigned long type;
1485 unsigned int commentOffset;
1486};
1487
1488/*
1489 * The following structure is the format of the data returned on a NetShareEnum
1490 * with level "90" (x5A)
1491 */
1492
1493struct shareInfo {
1494 char shareName[13];
1495 char pad;
1496 unsigned short type;
1497 unsigned int commentOffset;
1498};
1499
1500struct aliasInfo {
1501 char aliasName[9];
1502 char pad;
1503 unsigned int commentOffset;
1504 unsigned char type[2];
1505};
1506
1507struct aliasInfo92 {
1508 int aliasNameOffset;
1509 int serverNameOffset;
1510 int shareNameOffset;
1511};
1512
1513typedef struct {
1514 __le64 TotalAllocationUnits;
1515 __le64 FreeAllocationUnits;
1516 __le32 SectorsPerAllocationUnit;
1517 __le32 BytesPerSector;
1518} FILE_SYSTEM_INFO; /* size info, level 0x103 */
1519
1520typedef struct {
1521 __le16 MajorVersionNumber;
1522 __le16 MinorVersionNumber;
1523 __le64 Capability;
1524} FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
1525/* Linux/Unix extensions capability flags */
1526#define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */
1527#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
1528#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/
1529
1530typedef struct {
1531 /* For undefined recommended transfer size return -1 in that field */
1532 __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
1533 __le32 BlockSize;
1534 /* The next three fields are in terms of the block size.
1535 (above). If block size is unknown, 4096 would be a
1536 reasonable block size for a server to report.
1537 Note that returning the blocks/blocksavail removes need
1538 to make a second call (to QFSInfo level 0x103 to get this info.
1539 UserBlockAvail is typically less than or equal to BlocksAvail,
1540 if no distinction is made return the same value in each */
1541 __le64 TotalBlocks;
1542 __le64 BlocksAvail; /* bfree */
1543 __le64 UserBlocksAvail; /* bavail */
1544 /* For undefined Node fields or FSID return -1 */
1545 __le64 TotalFileNodes;
1546 __le64 FreeFileNodes;
1547 __le64 FileSysIdentifier; /* fsid */
1548 /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
1549 /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
1550} FILE_SYSTEM_POSIX_INFO;
1551
1552/* DeviceType Flags */
1553#define FILE_DEVICE_CD_ROM 0x00000002
1554#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
1555#define FILE_DEVICE_DFS 0x00000006
1556#define FILE_DEVICE_DISK 0x00000007
1557#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
1558#define FILE_DEVICE_FILE_SYSTEM 0x00000009
1559#define FILE_DEVICE_NAMED_PIPE 0x00000011
1560#define FILE_DEVICE_NETWORK 0x00000012
1561#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
1562#define FILE_DEVICE_NULL 0x00000015
1563#define FILE_DEVICE_PARALLEL_PORT 0x00000016
1564#define FILE_DEVICE_PRINTER 0x00000018
1565#define FILE_DEVICE_SERIAL_PORT 0x0000001b
1566#define FILE_DEVICE_STREAMS 0x0000001e
1567#define FILE_DEVICE_TAPE 0x0000001f
1568#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
1569#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
1570#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
1571
1572typedef struct {
1573 __le32 DeviceType;
1574 __le32 DeviceCharacteristics;
1575} FILE_SYSTEM_DEVICE_INFO; /* device info, level 0x104 */
1576
1577typedef struct {
1578 __le32 Attributes;
1579 __le32 MaxPathNameComponentLength;
1580 __le32 FileSystemNameLen;
1581 char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
1582} FILE_SYSTEM_ATTRIBUTE_INFO;
1583
1584/******************************************************************************/
1585/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
1586/******************************************************************************/
1587typedef struct { /* data block encoding of response to level 263 QPathInfo */
1588 __le64 CreationTime;
1589 __le64 LastAccessTime;
1590 __le64 LastWriteTime;
1591 __le64 ChangeTime;
1592 __le32 Attributes;
1593 __u32 Pad1;
1594 __le64 AllocationSize;
1595 __le64 EndOfFile; /* size ie offset to first free byte in file */
1596 __le32 NumberOfLinks; /* hard links */
1597 __u8 DeletePending;
1598 __u8 Directory;
1599 __u16 Pad2;
1600 __u64 IndexNumber;
1601 __le32 EASize;
1602 __le32 AccessFlags;
1603 __u64 IndexNumber1;
1604 __le64 CurrentByteOffset;
1605 __le32 Mode;
1606 __le32 AlignmentRequirement;
1607 __le32 FileNameLength;
1608 char FileName[1];
1609} FILE_ALL_INFO; /* level 0x107 QPathInfo */
1610
1611/* defines for enumerating possible values of the Unix type field below */
1612#define UNIX_FILE 0
1613#define UNIX_DIR 1
1614#define UNIX_SYMLINK 2
1615#define UNIX_CHARDEV 3
1616#define UNIX_BLOCKDEV 4
1617#define UNIX_FIFO 5
1618#define UNIX_SOCKET 6
1619typedef struct {
1620 __le64 EndOfFile;
1621 __le64 NumOfBytes;
1622 __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
1623 __le64 LastAccessTime;
1624 __le64 LastModificationTime;
1625 __le64 Uid;
1626 __le64 Gid;
1627 __le32 Type;
1628 __le64 DevMajor;
1629 __le64 DevMinor;
1630 __u64 UniqueId;
1631 __le64 Permissions;
1632 __le64 Nlinks;
1633} FILE_UNIX_BASIC_INFO; /* level 0x200 QPathInfo */
1634
1635typedef struct {
1636 char LinkDest[1];
1637} FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
1638
1639/* The following three structures are needed only for
1640 setting time to NT4 and some older servers via
1641 the primitive DOS time format */
1642typedef struct {
1643 __u16 Day:5;
1644 __u16 Month:4;
1645 __u16 Year:7;
1646} SMB_DATE;
1647
1648typedef struct {
1649 __u16 TwoSeconds:5;
1650 __u16 Minutes:6;
1651 __u16 Hours:5;
1652} SMB_TIME;
1653
1654typedef struct {
1655 __le16 CreationDate; /* SMB Date see above */
1656 __le16 CreationTime; /* SMB Time */
1657 __le16 LastAccessDate;
1658 __le16 LastAccessTime;
1659 __le16 LastWriteDate;
1660 __le16 LastWriteTime;
1661 __le32 DataSize; /* File Size (EOF) */
1662 __le32 AllocationSize;
1663 __le16 Attributes; /* verify not u32 */
1664 __le32 EASize;
1665} FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
1666
1667typedef struct {
1668 __le64 CreationTime;
1669 __le64 LastAccessTime;
1670 __le64 LastWriteTime;
1671 __le64 ChangeTime;
1672 __le32 Attributes;
1673 __u32 Pad;
1674} FILE_BASIC_INFO; /* size info, level 0x101 */
1675
1676struct file_allocation_info {
1677 __le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
1678}; /* size used on disk, level 0x103 for set, 0x105 for query */
1679
1680struct file_end_of_file_info {
1681 __le64 FileSize; /* offset to end of file */
1682}; /* size info, level 0x104 for set, 0x106 for query */
1683
1684struct file_alt_name_info {
1685 __u8 alt_name[1];
1686}; /* level 0x0108 */
1687
1688struct file_stream_info {
1689 __le32 number_of_streams; /* BB check sizes and verify location */
1690 /* followed by info on streams themselves
1691 u64 size;
1692 u64 allocation_size
1693 stream info */
1694}; /* level 0x109 */
1695
1696struct file_compression_info {
1697 __le64 compressed_size;
1698 __le16 format;
1699 __u8 unit_shift;
1700 __u8 ch_shift;
1701 __u8 cl_shift;
1702 __u8 pad[3];
1703}; /* level 0x10b */
1704
1705/* POSIX ACL set/query path info structures */
1706#define CIFS_ACL_VERSION 1
1707struct cifs_posix_ace { /* access control entry (ACE) */
1708 __u8 cifs_e_tag;
1709 __u8 cifs_e_perm;
1710 __le64 cifs_uid; /* or gid */
1711};
1712
1713struct cifs_posix_acl { /* access conrol list (ACL) */
1714 __le16 version;
1715 __le16 access_entry_count; /* access ACL - count of entries */
1716 __le16 default_entry_count; /* default ACL - count of entries */
1717 struct cifs_posix_ace ace_array[0];
1718 /* followed by
1719 struct cifs_posix_ace default_ace_arraay[] */
1720}; /* level 0x204 */
1721
1722/* types of access control entries already defined in posix_acl.h */
1723/* #define CIFS_POSIX_ACL_USER_OBJ 0x01
1724#define CIFS_POSIX_ACL_USER 0x02
1725#define CIFS_POSIX_ACL_GROUP_OBJ 0x04
1726#define CIFS_POSIX_ACL_GROUP 0x08
1727#define CIFS_POSIX_ACL_MASK 0x10
1728#define CIFS_POSIX_ACL_OTHER 0x20 */
1729
1730/* types of perms */
1731/* #define CIFS_POSIX_ACL_EXECUTE 0x01
1732#define CIFS_POSIX_ACL_WRITE 0x02
1733#define CIFS_POSIX_ACL_READ 0x04 */
1734
1735/* end of POSIX ACL definitions */
1736
1737struct file_internal_info {
1738 __u64 UniqueId; /* inode number */
1739}; /* level 0x3ee */
1740struct file_mode_info {
1741 __le32 Mode;
1742}; /* level 0x3f8 */
1743
1744struct file_attrib_tag {
1745 __le32 Attribute;
1746 __le32 ReparseTag;
1747}; /* level 0x40b */
1748
1749
1750/********************************************************/
1751/* FindFirst/FindNext transact2 data buffer formats */
1752/********************************************************/
1753
1754typedef struct {
1755 __le32 NextEntryOffset;
1756 __u32 ResumeKey; /* as with FileIndex - no need to convert */
1757 __le64 EndOfFile;
1758 __le64 NumOfBytes;
1759 __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
1760 __le64 LastAccessTime;
1761 __le64 LastModificationTime;
1762 __le64 Uid;
1763 __le64 Gid;
1764 __le32 Type;
1765 __le64 DevMajor;
1766 __le64 DevMinor;
1767 __u64 UniqueId;
1768 __le64 Permissions;
1769 __le64 Nlinks;
1770 char FileName[1];
1771} FILE_UNIX_INFO; /* level 0x202 */
1772
1773typedef struct {
1774 __le32 NextEntryOffset;
1775 __u32 FileIndex;
1776 __le64 CreationTime;
1777 __le64 LastAccessTime;
1778 __le64 LastWriteTime;
1779 __le64 ChangeTime;
1780 __le64 EndOfFile;
1781 __le64 AllocationSize;
1782 __le32 ExtFileAttributes;
1783 __le32 FileNameLength;
1784 char FileName[1];
1785} FILE_DIRECTORY_INFO; /* level 0x101 FF response data area */
1786
1787typedef struct {
1788 __le32 NextEntryOffset;
1789 __u32 FileIndex;
1790 __le64 CreationTime;
1791 __le64 LastAccessTime;
1792 __le64 LastWriteTime;
1793 __le64 ChangeTime;
1794 __le64 EndOfFile;
1795 __le64 AllocationSize;
1796 __le32 ExtFileAttributes;
1797 __le32 FileNameLength;
1798 __le32 EaSize; /* length of the xattrs */
1799 char FileName[1];
1800} FILE_FULL_DIRECTORY_INFO; /* level 0x102 FF response data area */
1801
1802typedef struct {
1803 __le32 NextEntryOffset;
1804 __u32 FileIndex;
1805 __le64 CreationTime;
1806 __le64 LastAccessTime;
1807 __le64 LastWriteTime;
1808 __le64 ChangeTime;
1809 __le64 EndOfFile;
1810 __le64 AllocationSize;
1811 __le32 ExtFileAttributes;
1812 __le32 FileNameLength;
1813 __le32 EaSize; /* EA size */
1814 __le32 Reserved;
1815 __u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
1816 char FileName[1];
1817} SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF response data area */
1818
1819typedef struct {
1820 __le32 NextEntryOffset;
1821 __u32 FileIndex;
1822 __le64 CreationTime;
1823 __le64 LastAccessTime;
1824 __le64 LastWriteTime;
1825 __le64 ChangeTime;
1826 __le64 EndOfFile;
1827 __le64 AllocationSize;
1828 __le32 ExtFileAttributes;
1829 __le32 FileNameLength;
1830 __le32 EaSize; /* length of the xattrs */
1831 __u8 ShortNameLength;
1832 __u8 Reserved;
1833 __u8 ShortName[12];
1834 char FileName[1];
1835} FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */
1836
1837
1838struct gea {
1839 unsigned char name_len;
1840 char name[1];
1841};
1842
1843struct gealist {
1844 unsigned long list_len;
1845 struct gea list[1];
1846};
1847
1848struct fea {
1849 unsigned char EA_flags;
1850 __u8 name_len;
1851 __le16 value_len;
1852 char name[1];
1853 /* optionally followed by value */
1854};
1855/* flags for _FEA.fEA */
1856#define FEA_NEEDEA 0x80 /* need EA bit */
1857
1858struct fealist {
1859 __le32 list_len;
1860 struct fea list[1];
1861};
1862
1863/* used to hold an arbitrary blob of data */
1864struct data_blob {
1865 __u8 *data;
1866 size_t length;
1867 void (*free) (struct data_blob * data_blob);
1868};
1869
1870
1871#ifdef CONFIG_CIFS_POSIX
1872/*
1873 For better POSIX semantics from Linux client, (even better
1874 than the existing CIFS Unix Extensions) we need updated PDUs for:
1875
1876 1) PosixCreateX - to set and return the mode, inode#, device info and
1877 perhaps add a CreateDevice - to create Pipes and other special .inodes
1878 Also note POSIX open flags
1879 2) Close - to return the last write time to do cache across close more safely
1880 3) PosixQFSInfo - to return statfs info
1881 4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
1882 5) Mkdir - set mode
1883
1884 And under consideration:
1885 6) FindClose2 (return nanosecond timestamp ??)
1886 7) Use nanosecond timestamps throughout all time fields if
1887 corresponding attribute flag is set
1888 8) sendfile - handle based copy
1889 9) Direct i/o
1890 10) "POSIX ACL" support
1891 11) Misc fcntls?
1892
1893 what about fixing 64 bit alignment
1894
1895 There are also various legacy SMB/CIFS requests used as is
1896
1897 From existing Lanman and NTLM dialects:
1898 --------------------------------------
1899 NEGOTIATE
1900 SESSION_SETUP_ANDX (BB which?)
1901 TREE_CONNECT_ANDX (BB which wct?)
1902 TREE_DISCONNECT (BB add volume timestamp on response)
1903 LOGOFF_ANDX
1904 DELETE (note delete open file behavior)
1905 DELETE_DIRECTORY
1906 READ_AND_X
1907 WRITE_AND_X
1908 LOCKING_AND_X (note posix lock semantics)
1909 RENAME (note rename across dirs and open file rename posix behaviors)
1910 NT_RENAME (for hardlinks) Is this good enough for all features?
1911 FIND_CLOSE2
1912 TRANSACTION2 (18 cases)
1913 SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
1914 (BB verify that never need to set allocation size)
1915 SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
1916
1917 COPY (note support for copy across directories) - FUTURE, OPTIONAL
1918 setting/getting OS/2 EAs - FUTURE (BB can this handle
1919 setting Linux xattrs perfectly) - OPTIONAL
1920 dnotify - FUTURE, OPTIONAL
1921 quota - FUTURE, OPTIONAL
1922
1923 Note that various requests implemented for NT interop such as
1924 NT_TRANSACT (IOCTL) QueryReparseInfo
1925 are unneeded to servers compliant with the CIFS POSIX extensions
1926
1927 From CIFS Unix Extensions:
1928 -------------------------
1929 T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
1930 T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
1931 T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
1932 T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
1933 Actually need QUERY_FILE_UNIX_INFO since has inode num
1934 BB what about a) blksize/blkbits/blocks
1935 b) i_version
1936 c) i_rdev
1937 d) notify mask?
1938 e) generation
1939 f) size_seqcount
1940 T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
1941 TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
1942 T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
1943
1944
1945 */
1946
1947/* xsymlink is a symlink format that can be used
1948 to save symlink info in a regular file when
1949 mounted to operating systems that do not
1950 support the cifs Unix extensions or EAs (for xattr
1951 based symlinks). For such a file to be recognized
1952 as containing symlink data:
1953
1954 1) file size must be 1067,
1955 2) signature must begin file data,
1956 3) length field must be set to ASCII representation
1957 of a number which is less than or equal to 1024,
1958 4) md5 must match that of the path data */
1959
1960struct xsymlink {
1961 /* 1067 bytes */
1962 char signature[4]; /* XSym */ /* not null terminated */
1963 char cr0; /* \n */
1964/* ASCII representation of length (4 bytes decimal) terminated by \n not null */
1965 char length[4];
1966 char cr1; /* \n */
1967/* md5 of valid subset of path ie path[0] through path[length-1] */
1968 __u8 md5[32];
1969 char cr2; /* \n */
1970/* if room left, then end with \n then 0x20s by convention but not required */
1971 char path[1024];
1972};
1973
1974typedef struct {
1975 /* BB do we need another field for flags? BB */
1976 __u32 xattr_name_len;
1977 __u32 xattr_value_len;
1978 char xattr_name[0];
1979 /* followed by xattr_value[xattr_value_len], no pad */
1980} FILE_XATTR_INFO; /* extended attribute, info level 205 */
1981
1982
1983#endif
1984
1985#pragma pack() /* resume default structure packing */
1986
1987#endif /* _CIFSPDU_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
new file mode 100644
index 000000000000..787eef4d86d3
--- /dev/null
+++ b/fs/cifs/cifsproto.h
@@ -0,0 +1,269 @@
1/*
2 * fs/cifs/cifsproto.h
3 *
4 * Copyright (c) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#ifndef _CIFSPROTO_H
22#define _CIFSPROTO_H
23#include <linux/nls.h>
24
25struct statfs;
26
27/*
28 *****************************************************************
29 * All Prototypes
30 *****************************************************************
31 */
32
33extern struct smb_hdr *cifs_buf_get(void);
34extern void cifs_buf_release(void *);
35extern struct smb_hdr *cifs_small_buf_get(void);
36extern void cifs_small_buf_release(void *);
37extern int smb_send(struct socket *, struct smb_hdr *,
38 unsigned int /* length */ , struct sockaddr *);
39extern unsigned int _GetXid(void);
40extern void _FreeXid(unsigned int);
41#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
42#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
43extern char *build_path_from_dentry(struct dentry *);
44extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
45extern void renew_parental_timestamps(struct dentry *direntry);
46extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
47 struct smb_hdr * /* input */ ,
48 struct smb_hdr * /* out */ ,
49 int * /* bytes returned */ , const int long_op);
50extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
51extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
52extern int is_valid_oplock_break(struct smb_hdr *smb);
53extern int is_size_safe_to_change(struct cifsInodeInfo *);
54extern unsigned int smbCalcSize(struct smb_hdr *ptr);
55extern int decode_negTokenInit(unsigned char *security_blob, int length,
56 enum securityEnum *secType);
57extern int cifs_inet_pton(int, char * source, void *dst);
58extern int map_smb_to_linux_error(struct smb_hdr *smb);
59extern void header_assemble(struct smb_hdr *, char /* command */ ,
60 const struct cifsTconInfo *, int
61 /* length of fixed section (word count) in two byte units */
62 );
63extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
64extern void DeleteOplockQEntry(struct oplock_q_entry *);
65extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
66extern u64 cifs_UnixTimeToNT(struct timespec);
67extern int cifs_get_inode_info(struct inode **pinode,
68 const unsigned char *search_path,
69 FILE_ALL_INFO * pfile_info,
70 struct super_block *sb, int xid);
71extern int cifs_get_inode_info_unix(struct inode **pinode,
72 const unsigned char *search_path,
73 struct super_block *sb,int xid);
74
75extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
76 const char *);
77extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
78void cifs_proc_init(void);
79void cifs_proc_clean(void);
80
81extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
82 struct nls_table * nls_info);
83extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
84
85extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
86 const char *tree, struct cifsTconInfo *tcon,
87 const struct nls_table *);
88
89extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
90 const char *searchName, const struct nls_table *nls_codepage,
91 __u16 *searchHandle, struct cifs_search_info * psrch_inf);
92
93extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
94 __u16 searchHandle, struct cifs_search_info * psrch_inf);
95
96extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
97 const __u16 search_handle);
98
99extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
100 const unsigned char *searchName,
101 FILE_ALL_INFO * findData,
102 const struct nls_table *nls_codepage);
103
104extern int CIFSSMBUnixQPathInfo(const int xid,
105 struct cifsTconInfo *tcon,
106 const unsigned char *searchName,
107 FILE_UNIX_BASIC_INFO * pFindData,
108 const struct nls_table *nls_codepage);
109
110extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
111 const unsigned char *searchName,
112 unsigned char **targetUNCs,
113 unsigned int *number_of_UNC_in_array,
114 const struct nls_table *nls_codepage);
115
116extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
117 const char *old_path,
118 const struct nls_table *nls_codepage);
119extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
120 const char *old_path, const struct nls_table *nls_codepage,
121 unsigned int *pnum_referrals, unsigned char ** preferrals);
122extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
123 struct kstatfs *FSData,
124 const struct nls_table *nls_codepage);
125extern int CIFSSMBQFSAttributeInfo(const int xid,
126 struct cifsTconInfo *tcon,
127 const struct nls_table *nls_codepage);
128extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
129 const struct nls_table *nls_codepage);
130extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
131 const struct nls_table *nls_codepage);
132extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
133 struct kstatfs *FSData, const struct nls_table *nls_codepage);
134
135extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
136 const char *fileName, const FILE_BASIC_INFO * data,
137 const struct nls_table *nls_codepage);
138extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
139 const FILE_BASIC_INFO * data, __u16 fid);
140#if 0
141extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
142 char *fileName, __u16 dos_attributes,
143 const struct nls_table *nls_codepage);
144#endif /* possibly unneeded function */
145extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
146 const char *fileName, __u64 size,int setAllocationSizeFlag,
147 const struct nls_table *nls_codepage);
148extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
149 __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
150extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
151 char *full_path, __u64 mode, __u64 uid,
152 __u64 gid, dev_t dev, const struct nls_table *nls_codepage);
153
154extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
155 const char *newName,
156 const struct nls_table *nls_codepage);
157extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
158 const char *name, const struct nls_table *nls_codepage);
159
160extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
161 const char *name,
162 const struct nls_table *nls_codepage);
163extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
164 const char *fromName, const char *toName,
165 const struct nls_table *nls_codepage);
166extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
167 int netfid, char * target_name, const struct nls_table *nls_codepage);
168extern int CIFSCreateHardLink(const int xid,
169 struct cifsTconInfo *tcon,
170 const char *fromName, const char *toName,
171 const struct nls_table *nls_codepage);
172extern int CIFSUnixCreateHardLink(const int xid,
173 struct cifsTconInfo *tcon,
174 const char *fromName, const char *toName,
175 const struct nls_table *nls_codepage);
176extern int CIFSUnixCreateSymLink(const int xid,
177 struct cifsTconInfo *tcon,
178 const char *fromName, const char *toName,
179 const struct nls_table *nls_codepage);
180extern int CIFSSMBUnixQuerySymLink(const int xid,
181 struct cifsTconInfo *tcon,
182 const unsigned char *searchName,
183 char *syminfo, const int buflen,
184 const struct nls_table *nls_codepage);
185extern int CIFSSMBQueryReparseLinkInfo(const int xid,
186 struct cifsTconInfo *tcon,
187 const unsigned char *searchName,
188 char *symlinkinfo, const int buflen, __u16 fid,
189 const struct nls_table *nls_codepage);
190
191extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
192 const char *fileName, const int disposition,
193 const int access_flags, const int omode,
194 __u16 * netfid, int *pOplock, FILE_ALL_INFO *,
195 const struct nls_table *nls_codepage);
196extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
197 const int smb_file_id);
198
199extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
200 const int netfid, unsigned int count,
201 const __u64 lseek, unsigned int *nbytes, char **buf);
202extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
203 const int netfid, const unsigned int count,
204 const __u64 lseek, unsigned int *nbytes,
205 const char *buf, const char __user *ubuf,
206 const int long_op);
207#ifdef CONFIG_CIFS_EXPERIMENTAL
208extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
209 const int netfid, const unsigned int count,
210 const __u64 offset, unsigned int *nbytes,
211 const char __user *buf,const int long_op);
212extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
213 const unsigned char *searchName, __u64 * inode_number,
214 const struct nls_table *nls_codepage);
215#endif /* CONFIG_CIFS_EXPERIMENTAL */
216
217extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
218 const __u16 netfid, const __u64 len,
219 const __u64 offset, const __u32 numUnlock,
220 const __u32 numLock, const __u8 lockType,
221 const int waitFlag);
222
223extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
224extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
225
226extern struct cifsSesInfo *sesInfoAlloc(void);
227extern void sesInfoFree(struct cifsSesInfo *);
228extern struct cifsTconInfo *tconInfoAlloc(void);
229extern void tconInfoFree(struct cifsTconInfo *);
230
231extern int cifs_reconnect(struct TCP_Server_Info *server);
232
233extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
234extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
235 __u32 expected_sequence_number);
236extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
237extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
238extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
239extern int CIFSSMBCopy(int xid,
240 struct cifsTconInfo *source_tcon,
241 const char *fromName,
242 const __u16 target_tid,
243 const char *toName, const int flags,
244 const struct nls_table *nls_codepage);
245extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
246 const int notify_subdirs,const __u16 netfid,__u32 filter,
247 const struct nls_table *nls_codepage);
248extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
249 const unsigned char *searchName, char * EAData,
250 size_t bufsize, const struct nls_table *nls_codepage);
251extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
252 const unsigned char * searchName,const unsigned char * ea_name,
253 unsigned char * ea_value, size_t buf_size,
254 const struct nls_table *nls_codepage);
255extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
256 const char *fileName, const char * ea_name,
257 const void * ea_value, const __u16 ea_value_len,
258 const struct nls_table *nls_codepage);
259extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
260 const unsigned char *searchName,
261 char *acl_inf, const int buflen,const int acl_type,
262 const struct nls_table *nls_codepage);
263extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
264 const unsigned char *fileName,
265 const char *local_acl, const int buflen, const int acl_type,
266 const struct nls_table *nls_codepage);
267int cifs_ioctl (struct inode * inode, struct file * filep,
268 unsigned int command, unsigned long arg);
269#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
new file mode 100644
index 000000000000..df6a619a6821
--- /dev/null
+++ b/fs/cifs/cifssmb.c
@@ -0,0 +1,4186 @@
1/*
2 * fs/cifs/cifssmb.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for constructing the SMB PDUs themselves
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
29
30#include <linux/fs.h>
31#include <linux/kernel.h>
32#include <linux/vfs.h>
33#include <linux/posix_acl_xattr.h>
34#include <asm/uaccess.h>
35#include "cifspdu.h"
36#include "cifsglob.h"
37#include "cifsproto.h"
38#include "cifs_unicode.h"
39#include "cifs_debug.h"
40
41#ifdef CONFIG_CIFS_POSIX
42static struct {
43 int index;
44 char *name;
45} protocols[] = {
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
48 {BAD_PROT, "\2"}
49};
50#else
51static struct {
52 int index;
53 char *name;
54} protocols[] = {
55 {CIFS_PROT, "\2NT LM 0.12"},
56 {BAD_PROT, "\2"}
57};
58#endif
59
60
61/* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
64{
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
68
69/* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
73 if(open_file) {
74 open_file->invalidHandle = TRUE;
75 }
76 }
77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
79}
80
81/* If the return code is zero, this function must fill in request_buf pointer */
82static int
83small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
84 void **request_buf /* returned */)
85{
86 int rc = 0;
87
88 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
89 check for tcp and smb session status done differently
90 for those three - in the calling routine */
91 if(tcon) {
92 if((tcon->ses) && (tcon->ses->server)){
93 struct nls_table *nls_codepage;
94 /* Give Demultiplex thread up to 10 seconds to
95 reconnect, should be greater than cifs socket
96 timeout which is 7 seconds */
97 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
98 wait_event_interruptible_timeout(tcon->ses->server->response_q,
99 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
100 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
101 /* on "soft" mounts we wait once */
102 if((tcon->retry == FALSE) ||
103 (tcon->ses->status == CifsExiting)) {
104 cFYI(1,("gave up waiting on reconnect in smb_init"));
105 return -EHOSTDOWN;
106 } /* else "hard" mount - keep retrying until
107 process is killed or server comes back up */
108 } else /* TCP session is reestablished now */
109 break;
110
111 }
112
113 nls_codepage = load_nls_default();
114 /* need to prevent multiple threads trying to
115 simultaneously reconnect the same SMB session */
116 down(&tcon->ses->sesSem);
117 if(tcon->ses->status == CifsNeedReconnect)
118 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
119 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
120 mark_open_files_invalid(tcon);
121 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
122 nls_codepage);
123 up(&tcon->ses->sesSem);
124 if(rc == 0)
125 atomic_inc(&tconInfoReconnectCount);
126
127 cFYI(1, ("reconnect tcon rc = %d", rc));
128 /* Removed call to reopen open files here -
129 it is safer (and faster) to reopen files
130 one at a time as needed in read and write */
131
132 /* Check if handle based operation so we
133 know whether we can continue or not without
134 returning to caller to reset file handle */
135 switch(smb_command) {
136 case SMB_COM_READ_ANDX:
137 case SMB_COM_WRITE_ANDX:
138 case SMB_COM_CLOSE:
139 case SMB_COM_FIND_CLOSE2:
140 case SMB_COM_LOCKING_ANDX: {
141 unload_nls(nls_codepage);
142 return -EAGAIN;
143 }
144 }
145 } else {
146 up(&tcon->ses->sesSem);
147 }
148 unload_nls(nls_codepage);
149
150 } else {
151 return -EIO;
152 }
153 }
154 if(rc)
155 return rc;
156
157 *request_buf = cifs_small_buf_get();
158 if (*request_buf == NULL) {
159 /* BB should we add a retry in here if not a writepage? */
160 return -ENOMEM;
161 }
162
163 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
164
165#ifdef CONFIG_CIFS_STATS
166 if(tcon != NULL) {
167 atomic_inc(&tcon->num_smbs_sent);
168 }
169#endif /* CONFIG_CIFS_STATS */
170 return rc;
171}
172
173/* If the return code is zero, this function must fill in request_buf pointer */
174static int
175smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
176 void **request_buf /* returned */ ,
177 void **response_buf /* returned */ )
178{
179 int rc = 0;
180
181 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
182 check for tcp and smb session status done differently
183 for those three - in the calling routine */
184 if(tcon) {
185 if((tcon->ses) && (tcon->ses->server)){
186 struct nls_table *nls_codepage;
187 /* Give Demultiplex thread up to 10 seconds to
188 reconnect, should be greater than cifs socket
189 timeout which is 7 seconds */
190 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
191 wait_event_interruptible_timeout(tcon->ses->server->response_q,
192 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
193 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
194 /* on "soft" mounts we wait once */
195 if((tcon->retry == FALSE) ||
196 (tcon->ses->status == CifsExiting)) {
197 cFYI(1,("gave up waiting on reconnect in smb_init"));
198 return -EHOSTDOWN;
199 } /* else "hard" mount - keep retrying until
200 process is killed or server comes back up */
201 } else /* TCP session is reestablished now */
202 break;
203
204 }
205
206 nls_codepage = load_nls_default();
207 /* need to prevent multiple threads trying to
208 simultaneously reconnect the same SMB session */
209 down(&tcon->ses->sesSem);
210 if(tcon->ses->status == CifsNeedReconnect)
211 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
212 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
213 mark_open_files_invalid(tcon);
214 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
215 nls_codepage);
216 up(&tcon->ses->sesSem);
217 if(rc == 0)
218 atomic_inc(&tconInfoReconnectCount);
219
220 cFYI(1, ("reconnect tcon rc = %d", rc));
221 /* Removed call to reopen open files here -
222 it is safer (and faster) to reopen files
223 one at a time as needed in read and write */
224
225 /* Check if handle based operation so we
226 know whether we can continue or not without
227 returning to caller to reset file handle */
228 switch(smb_command) {
229 case SMB_COM_READ_ANDX:
230 case SMB_COM_WRITE_ANDX:
231 case SMB_COM_CLOSE:
232 case SMB_COM_FIND_CLOSE2:
233 case SMB_COM_LOCKING_ANDX: {
234 unload_nls(nls_codepage);
235 return -EAGAIN;
236 }
237 }
238 } else {
239 up(&tcon->ses->sesSem);
240 }
241 unload_nls(nls_codepage);
242
243 } else {
244 return -EIO;
245 }
246 }
247 if(rc)
248 return rc;
249
250 *request_buf = cifs_buf_get();
251 if (*request_buf == NULL) {
252 /* BB should we add a retry in here if not a writepage? */
253 return -ENOMEM;
254 }
255 /* Although the original thought was we needed the response buf for */
256 /* potential retries of smb operations it turns out we can determine */
257 /* from the mid flags when the request buffer can be resent without */
258 /* having to use a second distinct buffer for the response */
259 *response_buf = *request_buf;
260
261 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
262 wct /*wct */ );
263
264#ifdef CONFIG_CIFS_STATS
265 if(tcon != NULL) {
266 atomic_inc(&tcon->num_smbs_sent);
267 }
268#endif /* CONFIG_CIFS_STATS */
269 return rc;
270}
271
272static int validate_t2(struct smb_t2_rsp * pSMB)
273{
274 int rc = -EINVAL;
275 int total_size;
276 char * pBCC;
277
278 /* check for plausible wct, bcc and t2 data and parm sizes */
279 /* check for parm and data offset going beyond end of smb */
280 if(pSMB->hdr.WordCount >= 10) {
281 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
282 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
283 /* check that bcc is at least as big as parms + data */
284 /* check that bcc is less than negotiated smb buffer */
285 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
286 if(total_size < 512) {
287 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
288 /* BCC le converted in SendReceive */
289 pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) +
290 (char *)pSMB;
291 if((total_size <= (*(u16 *)pBCC)) &&
292 (total_size <
293 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
294 return 0;
295 }
296
297 }
298 }
299 }
300 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
301 sizeof(struct smb_t2_rsp) + 16);
302 return rc;
303}
304int
305CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
306{
307 NEGOTIATE_REQ *pSMB;
308 NEGOTIATE_RSP *pSMBr;
309 int rc = 0;
310 int bytes_returned;
311 struct TCP_Server_Info * server;
312 u16 count;
313
314 if(ses->server)
315 server = ses->server;
316 else {
317 rc = -EIO;
318 return rc;
319 }
320 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
321 (void **) &pSMB, (void **) &pSMBr);
322 if (rc)
323 return rc;
324
325 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
326 if (extended_security)
327 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
328
329 count = strlen(protocols[0].name) + 1;
330 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
331 /* null guaranteed to be at end of source and target buffers anyway */
332
333 pSMB->hdr.smb_buf_length += count;
334 pSMB->ByteCount = cpu_to_le16(count);
335
336 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
337 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
338 if (rc == 0) {
339 server->secMode = pSMBr->SecurityMode;
340 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
341 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
342 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
343 /* probably no need to store and check maxvcs */
344 server->maxBuf =
345 min(le32_to_cpu(pSMBr->MaxBufferSize),
346 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
347 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
348 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
349 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
350 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
351 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
352 /* BB with UTC do we ever need to be using srvr timezone? */
353 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
354 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
355 CIFS_CRYPTO_KEY_SIZE);
356 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
357 && (pSMBr->EncryptionKeyLength == 0)) {
358 /* decode security blob */
359 } else
360 rc = -EIO;
361
362 /* BB might be helpful to save off the domain of server here */
363
364 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
365 (server->capabilities & CAP_EXTENDED_SECURITY)) {
366 count = pSMBr->ByteCount;
367 if (count < 16)
368 rc = -EIO;
369 else if (count == 16) {
370 server->secType = RawNTLMSSP;
371 if (server->socketUseCount.counter > 1) {
372 if (memcmp
373 (server->server_GUID,
374 pSMBr->u.extended_response.
375 GUID, 16) != 0) {
376 cFYI(1,
377 ("UID of server does not match previous connection to same ip address"));
378 memcpy(server->
379 server_GUID,
380 pSMBr->u.
381 extended_response.
382 GUID, 16);
383 }
384 } else
385 memcpy(server->server_GUID,
386 pSMBr->u.extended_response.
387 GUID, 16);
388 } else {
389 rc = decode_negTokenInit(pSMBr->u.
390 extended_response.
391 SecurityBlob,
392 count - 16,
393 &server->secType);
394 if(rc == 1) {
395 /* BB Need to fill struct for sessetup here */
396 rc = -EOPNOTSUPP;
397 } else {
398 rc = -EINVAL;
399 }
400 }
401 } else
402 server->capabilities &= ~CAP_EXTENDED_SECURITY;
403 if(sign_CIFS_PDUs == FALSE) {
404 if(server->secMode & SECMODE_SIGN_REQUIRED)
405 cERROR(1,
406 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
407 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
408 } else if(sign_CIFS_PDUs == 1) {
409 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
410 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
411 }
412
413 }
414 if (pSMB)
415 cifs_buf_release(pSMB);
416 return rc;
417}
418
419int
420CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
421{
422 struct smb_hdr *smb_buffer;
423 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
424 int rc = 0;
425 int length;
426
427 cFYI(1, ("In tree disconnect"));
428 /*
429 * If last user of the connection and
430 * connection alive - disconnect it
431 * If this is the last connection on the server session disconnect it
432 * (and inside session disconnect we should check if tcp socket needs
433 * to be freed and kernel thread woken up).
434 */
435 if (tcon)
436 down(&tcon->tconSem);
437 else
438 return -EIO;
439
440 atomic_dec(&tcon->useCount);
441 if (atomic_read(&tcon->useCount) > 0) {
442 up(&tcon->tconSem);
443 return -EBUSY;
444 }
445
446 /* No need to return error on this operation if tid invalidated and
447 closed on server already e.g. due to tcp session crashing */
448 if(tcon->tidStatus == CifsNeedReconnect) {
449 up(&tcon->tconSem);
450 return 0;
451 }
452
453 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
454 up(&tcon->tconSem);
455 return -EIO;
456 }
457 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
458 if (rc) {
459 up(&tcon->tconSem);
460 return rc;
461 } else {
462 smb_buffer_response = smb_buffer; /* BB removeme BB */
463 }
464 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
465 &length, 0);
466 if (rc)
467 cFYI(1, (" Tree disconnect failed %d", rc));
468
469 if (smb_buffer)
470 cifs_small_buf_release(smb_buffer);
471 up(&tcon->tconSem);
472
473 /* No need to return error on this operation if tid invalidated and
474 closed on server already e.g. due to tcp session crashing */
475 if (rc == -EAGAIN)
476 rc = 0;
477
478 return rc;
479}
480
481int
482CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
483{
484 struct smb_hdr *smb_buffer_response;
485 LOGOFF_ANDX_REQ *pSMB;
486 int rc = 0;
487 int length;
488
489 cFYI(1, ("In SMBLogoff for session disconnect"));
490 if (ses)
491 down(&ses->sesSem);
492 else
493 return -EIO;
494
495 atomic_dec(&ses->inUse);
496 if (atomic_read(&ses->inUse) > 0) {
497 up(&ses->sesSem);
498 return -EBUSY;
499 }
500 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
501 if (rc) {
502 up(&ses->sesSem);
503 return rc;
504 }
505
506 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
507
508 if(ses->server) {
509 if(ses->server->secMode &
510 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
511 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
512 }
513
514 pSMB->hdr.Uid = ses->Suid;
515
516 pSMB->AndXCommand = 0xFF;
517 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
518 smb_buffer_response, &length, 0);
519 if (ses->server) {
520 atomic_dec(&ses->server->socketUseCount);
521 if (atomic_read(&ses->server->socketUseCount) == 0) {
522 spin_lock(&GlobalMid_Lock);
523 ses->server->tcpStatus = CifsExiting;
524 spin_unlock(&GlobalMid_Lock);
525 rc = -ESHUTDOWN;
526 }
527 }
528 if (pSMB)
529 cifs_small_buf_release(pSMB);
530 up(&ses->sesSem);
531
532 /* if session dead then we do not need to do ulogoff,
533 since server closed smb session, no sense reporting
534 error */
535 if (rc == -EAGAIN)
536 rc = 0;
537 return rc;
538}
539
540int
541CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
542 const char *fileName, const struct nls_table *nls_codepage)
543{
544 DELETE_FILE_REQ *pSMB = NULL;
545 DELETE_FILE_RSP *pSMBr = NULL;
546 int rc = 0;
547 int bytes_returned;
548 int name_len;
549
550DelFileRetry:
551 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
552 (void **) &pSMBr);
553 if (rc)
554 return rc;
555
556 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
557 name_len =
558 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
559 /* find define for this maxpathcomponent */
560 , nls_codepage);
561 name_len++; /* trailing null */
562 name_len *= 2;
563 } else { /* BB improve the check for buffer overruns BB */
564 name_len = strnlen(fileName, PATH_MAX);
565 name_len++; /* trailing null */
566 strncpy(pSMB->fileName, fileName, name_len);
567 }
568 pSMB->SearchAttributes =
569 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
570 pSMB->BufferFormat = 0x04;
571 pSMB->hdr.smb_buf_length += name_len + 1;
572 pSMB->ByteCount = cpu_to_le16(name_len + 1);
573 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
574 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
575 if (rc) {
576 cFYI(1, ("Error in RMFile = %d", rc));
577 }
578#ifdef CONFIG_CIFS_STATS
579 else {
580 atomic_inc(&tcon->num_deletes);
581 }
582#endif
583
584 cifs_buf_release(pSMB);
585 if (rc == -EAGAIN)
586 goto DelFileRetry;
587
588 return rc;
589}
590
591int
592CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
593 const char *dirName, const struct nls_table *nls_codepage)
594{
595 DELETE_DIRECTORY_REQ *pSMB = NULL;
596 DELETE_DIRECTORY_RSP *pSMBr = NULL;
597 int rc = 0;
598 int bytes_returned;
599 int name_len;
600
601 cFYI(1, ("In CIFSSMBRmDir"));
602RmDirRetry:
603 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
604 (void **) &pSMBr);
605 if (rc)
606 return rc;
607
608 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
609 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
610 /* find define for this maxpathcomponent */
611 , nls_codepage);
612 name_len++; /* trailing null */
613 name_len *= 2;
614 } else { /* BB improve the check for buffer overruns BB */
615 name_len = strnlen(dirName, PATH_MAX);
616 name_len++; /* trailing null */
617 strncpy(pSMB->DirName, dirName, name_len);
618 }
619
620 pSMB->BufferFormat = 0x04;
621 pSMB->hdr.smb_buf_length += name_len + 1;
622 pSMB->ByteCount = cpu_to_le16(name_len + 1);
623 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
624 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
625 if (rc) {
626 cFYI(1, ("Error in RMDir = %d", rc));
627 }
628#ifdef CONFIG_CIFS_STATS
629 else {
630 atomic_inc(&tcon->num_rmdirs);
631 }
632#endif
633
634 cifs_buf_release(pSMB);
635 if (rc == -EAGAIN)
636 goto RmDirRetry;
637 return rc;
638}
639
640int
641CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
642 const char *name, const struct nls_table *nls_codepage)
643{
644 int rc = 0;
645 CREATE_DIRECTORY_REQ *pSMB = NULL;
646 CREATE_DIRECTORY_RSP *pSMBr = NULL;
647 int bytes_returned;
648 int name_len;
649
650 cFYI(1, ("In CIFSSMBMkDir"));
651MkDirRetry:
652 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
653 (void **) &pSMBr);
654 if (rc)
655 return rc;
656
657 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
658 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
659 /* find define for this maxpathcomponent */
660 , nls_codepage);
661 name_len++; /* trailing null */
662 name_len *= 2;
663 } else { /* BB improve the check for buffer overruns BB */
664 name_len = strnlen(name, PATH_MAX);
665 name_len++; /* trailing null */
666 strncpy(pSMB->DirName, name, name_len);
667 }
668
669 pSMB->BufferFormat = 0x04;
670 pSMB->hdr.smb_buf_length += name_len + 1;
671 pSMB->ByteCount = cpu_to_le16(name_len + 1);
672 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
673 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
674 if (rc) {
675 cFYI(1, ("Error in Mkdir = %d", rc));
676 }
677#ifdef CONFIG_CIFS_STATS
678 else {
679 atomic_inc(&tcon->num_mkdirs);
680 }
681#endif
682 cifs_buf_release(pSMB);
683 if (rc == -EAGAIN)
684 goto MkDirRetry;
685 return rc;
686}
687
688int
689CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
690 const char *fileName, const int openDisposition,
691 const int access_flags, const int create_options, __u16 * netfid,
692 int *pOplock, FILE_ALL_INFO * pfile_info,
693 const struct nls_table *nls_codepage)
694{
695 int rc = -EACCES;
696 OPEN_REQ *pSMB = NULL;
697 OPEN_RSP *pSMBr = NULL;
698 int bytes_returned;
699 int name_len;
700 __u16 count;
701
702openRetry:
703 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
704 (void **) &pSMBr);
705 if (rc)
706 return rc;
707
708 pSMB->AndXCommand = 0xFF; /* none */
709
710 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
711 count = 1; /* account for one byte pad to word boundary */
712 name_len =
713 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
714 fileName, PATH_MAX
715 /* find define for this maxpathcomponent */
716 , nls_codepage);
717 name_len++; /* trailing null */
718 name_len *= 2;
719 pSMB->NameLength = cpu_to_le16(name_len);
720 } else { /* BB improve the check for buffer overruns BB */
721 count = 0; /* no pad */
722 name_len = strnlen(fileName, PATH_MAX);
723 name_len++; /* trailing null */
724 pSMB->NameLength = cpu_to_le16(name_len);
725 strncpy(pSMB->fileName, fileName, name_len);
726 }
727 if (*pOplock & REQ_OPLOCK)
728 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
729 else if (*pOplock & REQ_BATCHOPLOCK) {
730 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
731 }
732 pSMB->DesiredAccess = cpu_to_le32(access_flags);
733 pSMB->AllocationSize = 0;
734 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
735 /* XP does not handle ATTR_POSIX_SEMANTICS */
736 /* but it helps speed up case sensitive checks for other
737 servers such as Samba */
738 if (tcon->ses->capabilities & CAP_UNIX)
739 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
740
741 /* if ((omode & S_IWUGO) == 0)
742 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
743 /* Above line causes problems due to vfs splitting create into two
744 pieces - need to set mode after file created not while it is
745 being created */
746 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
747 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
748 pSMB->CreateOptions = cpu_to_le32(create_options);
749 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
750 pSMB->SecurityFlags =
751 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
752
753 count += name_len;
754 pSMB->hdr.smb_buf_length += count;
755
756 pSMB->ByteCount = cpu_to_le16(count);
757 /* long_op set to 1 to allow for oplock break timeouts */
758 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
759 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
760 if (rc) {
761 cFYI(1, ("Error in Open = %d", rc));
762 } else {
763 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
764 *netfid = pSMBr->Fid; /* cifs fid stays in le */
765 /* Let caller know file was created so we can set the mode. */
766 /* Do we care about the CreateAction in any other cases? */
767 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
768 *pOplock |= CIFS_CREATE_ACTION;
769 if(pfile_info) {
770 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
771 36 /* CreationTime to Attributes */);
772 /* the file_info buf is endian converted by caller */
773 pfile_info->AllocationSize = pSMBr->AllocationSize;
774 pfile_info->EndOfFile = pSMBr->EndOfFile;
775 pfile_info->NumberOfLinks = cpu_to_le32(1);
776 }
777
778#ifdef CONFIG_CIFS_STATS
779 atomic_inc(&tcon->num_opens);
780#endif
781 }
782 cifs_buf_release(pSMB);
783 if (rc == -EAGAIN)
784 goto openRetry;
785 return rc;
786}
787
788/* If no buffer passed in, then caller wants to do the copy
789 as in the case of readpages so the SMB buffer must be
790 freed by the caller */
791
792int
793CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
794 const int netfid, const unsigned int count,
795 const __u64 lseek, unsigned int *nbytes, char **buf)
796{
797 int rc = -EACCES;
798 READ_REQ *pSMB = NULL;
799 READ_RSP *pSMBr = NULL;
800 char *pReadData = NULL;
801 int bytes_returned;
802
803 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
804
805 *nbytes = 0;
806 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
807 (void **) &pSMBr);
808 if (rc)
809 return rc;
810
811 /* tcon and ses pointer are checked in smb_init */
812 if (tcon->ses->server == NULL)
813 return -ECONNABORTED;
814
815 pSMB->AndXCommand = 0xFF; /* none */
816 pSMB->Fid = netfid;
817 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
818 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
819 pSMB->Remaining = 0;
820 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
821 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
822 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
823
824 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
825 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
826 if (rc) {
827 cERROR(1, ("Send error in read = %d", rc));
828 } else {
829 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
830 data_length = data_length << 16;
831 data_length += le16_to_cpu(pSMBr->DataLength);
832 *nbytes = data_length;
833
834 /*check that DataLength would not go beyond end of SMB */
835 if ((data_length > CIFSMaxBufSize)
836 || (data_length > count)) {
837 cFYI(1,("bad length %d for count %d",data_length,count));
838 rc = -EIO;
839 *nbytes = 0;
840 } else {
841 pReadData =
842 (char *) (&pSMBr->hdr.Protocol) +
843 le16_to_cpu(pSMBr->DataOffset);
844/* if(rc = copy_to_user(buf, pReadData, data_length)) {
845 cERROR(1,("Faulting on read rc = %d",rc));
846 rc = -EFAULT;
847 }*/ /* can not use copy_to_user when using page cache*/
848 if(*buf)
849 memcpy(*buf,pReadData,data_length);
850 }
851 }
852 if(*buf)
853 cifs_buf_release(pSMB);
854 else
855 *buf = (char *)pSMB;
856
857 /* Note: On -EAGAIN error only caller can retry on handle based calls
858 since file handle passed in no longer valid */
859 return rc;
860}
861
862int
863CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
864 const int netfid, const unsigned int count,
865 const __u64 offset, unsigned int *nbytes, const char *buf,
866 const char __user * ubuf, const int long_op)
867{
868 int rc = -EACCES;
869 WRITE_REQ *pSMB = NULL;
870 WRITE_RSP *pSMBr = NULL;
871 int bytes_returned;
872 __u32 bytes_sent;
873 __u16 byte_count;
874
875 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
876 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
877 (void **) &pSMBr);
878 if (rc)
879 return rc;
880 /* tcon and ses pointer are checked in smb_init */
881 if (tcon->ses->server == NULL)
882 return -ECONNABORTED;
883
884 pSMB->AndXCommand = 0xFF; /* none */
885 pSMB->Fid = netfid;
886 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
887 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
888 pSMB->Reserved = 0xFFFFFFFF;
889 pSMB->WriteMode = 0;
890 pSMB->Remaining = 0;
891
892 /* Can increase buffer size if buffer is big enough in some cases - ie we
893 can send more if LARGE_WRITE_X capability returned by the server and if
894 our buffer is big enough or if we convert to iovecs on socket writes
895 and eliminate the copy to the CIFS buffer */
896 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
897 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
898 } else {
899 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
900 & ~0xFF;
901 }
902
903 if (bytes_sent > count)
904 bytes_sent = count;
905 pSMB->DataOffset =
906 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
907 if(buf)
908 memcpy(pSMB->Data,buf,bytes_sent);
909 else if(ubuf) {
910 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
911 cifs_buf_release(pSMB);
912 return -EFAULT;
913 }
914 } else {
915 /* No buffer */
916 cifs_buf_release(pSMB);
917 return -EINVAL;
918 }
919
920 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
921 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
922 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
923 pSMB->hdr.smb_buf_length += bytes_sent+1;
924 pSMB->ByteCount = cpu_to_le16(byte_count);
925
926 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
927 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
928 if (rc) {
929 cFYI(1, ("Send error in write = %d", rc));
930 *nbytes = 0;
931 } else {
932 *nbytes = le16_to_cpu(pSMBr->CountHigh);
933 *nbytes = (*nbytes) << 16;
934 *nbytes += le16_to_cpu(pSMBr->Count);
935 }
936
937 cifs_buf_release(pSMB);
938
939 /* Note: On -EAGAIN error only caller can retry on handle based calls
940 since file handle passed in no longer valid */
941
942 return rc;
943}
944
945#ifdef CONFIG_CIFS_EXPERIMENTAL
946int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
947 const int netfid, const unsigned int count,
948 const __u64 offset, unsigned int *nbytes, const char __user *buf,
949 const int long_op)
950{
951 int rc = -EACCES;
952 WRITE_REQ *pSMB = NULL;
953 WRITE_RSP *pSMBr = NULL;
954 /*int bytes_returned;*/
955 unsigned bytes_sent;
956 __u16 byte_count;
957
958 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
959
960 if (rc)
961 return rc;
962
963 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
964
965 /* tcon and ses pointer are checked in smb_init */
966 if (tcon->ses->server == NULL)
967 return -ECONNABORTED;
968
969 pSMB->AndXCommand = 0xFF; /* none */
970 pSMB->Fid = netfid;
971 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
972 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
973 pSMB->Reserved = 0xFFFFFFFF;
974 pSMB->WriteMode = 0;
975 pSMB->Remaining = 0;
976 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
977 if (bytes_sent > count)
978 bytes_sent = count;
979 pSMB->DataLengthHigh = 0;
980 pSMB->DataOffset =
981 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
982
983 byte_count = bytes_sent + 1 /* pad */ ;
984 pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
985 pSMB->DataLengthHigh = 0;
986 pSMB->hdr.smb_buf_length += byte_count;
987 pSMB->ByteCount = cpu_to_le16(byte_count);
988
989/* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
990 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
991 if (rc) {
992 cFYI(1, ("Send error in write2 (large write) = %d", rc));
993 *nbytes = 0;
994 } else
995 *nbytes = le16_to_cpu(pSMBr->Count);
996
997 cifs_small_buf_release(pSMB);
998
999 /* Note: On -EAGAIN error only caller can retry on handle based calls
1000 since file handle passed in no longer valid */
1001
1002 return rc;
1003}
1004#endif /* CIFS_EXPERIMENTAL */
1005
1006int
1007CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1008 const __u16 smb_file_id, const __u64 len,
1009 const __u64 offset, const __u32 numUnlock,
1010 const __u32 numLock, const __u8 lockType, const int waitFlag)
1011{
1012 int rc = 0;
1013 LOCK_REQ *pSMB = NULL;
1014 LOCK_RSP *pSMBr = NULL;
1015 int bytes_returned;
1016 int timeout = 0;
1017 __u16 count;
1018
1019 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1020 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
1021 (void **) &pSMBr);
1022 if (rc)
1023 return rc;
1024
1025 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1026 timeout = -1; /* no response expected */
1027 pSMB->Timeout = 0;
1028 } else if (waitFlag == TRUE) {
1029 timeout = 3; /* blocking operation, no timeout */
1030 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1031 } else {
1032 pSMB->Timeout = 0;
1033 }
1034
1035 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1036 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1037 pSMB->LockType = lockType;
1038 pSMB->AndXCommand = 0xFF; /* none */
1039 pSMB->Fid = smb_file_id; /* netfid stays le */
1040
1041 if((numLock != 0) || (numUnlock != 0)) {
1042 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1043 /* BB where to store pid high? */
1044 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1045 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1046 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1047 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1048 count = sizeof(LOCKING_ANDX_RANGE);
1049 } else {
1050 /* oplock break */
1051 count = 0;
1052 }
1053 pSMB->hdr.smb_buf_length += count;
1054 pSMB->ByteCount = cpu_to_le16(count);
1055
1056 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1057 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1058
1059 if (rc) {
1060 cFYI(1, ("Send error in Lock = %d", rc));
1061 }
1062 cifs_buf_release(pSMB);
1063
1064 /* Note: On -EAGAIN error only caller can retry on handle based calls
1065 since file handle passed in no longer valid */
1066 return rc;
1067}
1068
1069int
1070CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1071{
1072 int rc = 0;
1073 CLOSE_REQ *pSMB = NULL;
1074 CLOSE_RSP *pSMBr = NULL;
1075 int bytes_returned;
1076 cFYI(1, ("In CIFSSMBClose"));
1077
1078/* do not retry on dead session on close */
1079 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1080 if(rc == -EAGAIN)
1081 return 0;
1082 if (rc)
1083 return rc;
1084
1085 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1086
1087 pSMB->FileID = (__u16) smb_file_id;
1088 pSMB->LastWriteTime = 0;
1089 pSMB->ByteCount = 0;
1090 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1091 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1092 if (rc) {
1093 if(rc!=-EINTR) {
1094 /* EINTR is expected when user ctl-c to kill app */
1095 cERROR(1, ("Send error in Close = %d", rc));
1096 }
1097 }
1098
1099 cifs_small_buf_release(pSMB);
1100
1101 /* Since session is dead, file will be closed on server already */
1102 if(rc == -EAGAIN)
1103 rc = 0;
1104
1105 return rc;
1106}
1107
1108int
1109CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1110 const char *fromName, const char *toName,
1111 const struct nls_table *nls_codepage)
1112{
1113 int rc = 0;
1114 RENAME_REQ *pSMB = NULL;
1115 RENAME_RSP *pSMBr = NULL;
1116 int bytes_returned;
1117 int name_len, name_len2;
1118 __u16 count;
1119
1120 cFYI(1, ("In CIFSSMBRename"));
1121renameRetry:
1122 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1123 (void **) &pSMBr);
1124 if (rc)
1125 return rc;
1126
1127 pSMB->BufferFormat = 0x04;
1128 pSMB->SearchAttributes =
1129 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1130 ATTR_DIRECTORY);
1131
1132 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1133 name_len =
1134 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
1135 /* find define for this maxpathcomponent */
1136 , nls_codepage);
1137 name_len++; /* trailing null */
1138 name_len *= 2;
1139 pSMB->OldFileName[name_len] = 0x04; /* pad */
1140 /* protocol requires ASCII signature byte on Unicode string */
1141 pSMB->OldFileName[name_len + 1] = 0x00;
1142 name_len2 =
1143 cifs_strtoUCS((wchar_t *) & pSMB->
1144 OldFileName[name_len + 2], toName, PATH_MAX,
1145 nls_codepage);
1146 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1147 name_len2 *= 2; /* convert to bytes */
1148 } else { /* BB improve the check for buffer overruns BB */
1149 name_len = strnlen(fromName, PATH_MAX);
1150 name_len++; /* trailing null */
1151 strncpy(pSMB->OldFileName, fromName, name_len);
1152 name_len2 = strnlen(toName, PATH_MAX);
1153 name_len2++; /* trailing null */
1154 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1155 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1156 name_len2++; /* trailing null */
1157 name_len2++; /* signature byte */
1158 }
1159
1160 count = 1 /* 1st signature byte */ + name_len + name_len2;
1161 pSMB->hdr.smb_buf_length += count;
1162 pSMB->ByteCount = cpu_to_le16(count);
1163
1164 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1165 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1166 if (rc) {
1167 cFYI(1, ("Send error in rename = %d", rc));
1168 }
1169
1170#ifdef CONFIG_CIFS_STATS
1171 else {
1172 atomic_inc(&tcon->num_renames);
1173 }
1174#endif
1175
1176 cifs_buf_release(pSMB);
1177
1178 if (rc == -EAGAIN)
1179 goto renameRetry;
1180
1181 return rc;
1182}
1183
1184int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1185 int netfid, char * target_name, const struct nls_table * nls_codepage)
1186{
1187 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1188 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1189 struct set_file_rename * rename_info;
1190 char *data_offset;
1191 char dummy_string[30];
1192 int rc = 0;
1193 int bytes_returned = 0;
1194 int len_of_str;
1195 __u16 params, param_offset, offset, count, byte_count;
1196
1197 cFYI(1, ("Rename to File by handle"));
1198 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1199 (void **) &pSMBr);
1200 if (rc)
1201 return rc;
1202
1203 params = 6;
1204 pSMB->MaxSetupCount = 0;
1205 pSMB->Reserved = 0;
1206 pSMB->Flags = 0;
1207 pSMB->Timeout = 0;
1208 pSMB->Reserved2 = 0;
1209 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1210 offset = param_offset + params;
1211
1212 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1213 rename_info = (struct set_file_rename *) data_offset;
1214 pSMB->MaxParameterCount = cpu_to_le16(2);
1215 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1216 pSMB->SetupCount = 1;
1217 pSMB->Reserved3 = 0;
1218 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1219 byte_count = 3 /* pad */ + params;
1220 pSMB->ParameterCount = cpu_to_le16(params);
1221 pSMB->TotalParameterCount = pSMB->ParameterCount;
1222 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1223 pSMB->DataOffset = cpu_to_le16(offset);
1224 /* construct random name ".cifs_tmp<inodenum><mid>" */
1225 rename_info->overwrite = cpu_to_le32(1);
1226 rename_info->root_fid = 0;
1227 /* unicode only call */
1228 if(target_name == NULL) {
1229 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1230 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
1231 } else {
1232 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
1233 }
1234 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1235 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1236 byte_count += count;
1237 pSMB->DataCount = cpu_to_le16(count);
1238 pSMB->TotalDataCount = pSMB->DataCount;
1239 pSMB->Fid = netfid;
1240 pSMB->InformationLevel =
1241 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1242 pSMB->Reserved4 = 0;
1243 pSMB->hdr.smb_buf_length += byte_count;
1244 pSMB->ByteCount = cpu_to_le16(byte_count);
1245 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1246 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1247 if (rc) {
1248 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1249 }
1250#ifdef CONFIG_CIFS_STATS
1251 else {
1252 atomic_inc(&pTcon->num_t2renames);
1253 }
1254#endif
1255 cifs_buf_release(pSMB);
1256
1257 /* Note: On -EAGAIN error only caller can retry on handle based calls
1258 since file handle passed in no longer valid */
1259
1260 return rc;
1261}
1262
1263int
1264CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1265 const __u16 target_tid, const char *toName, const int flags,
1266 const struct nls_table *nls_codepage)
1267{
1268 int rc = 0;
1269 COPY_REQ *pSMB = NULL;
1270 COPY_RSP *pSMBr = NULL;
1271 int bytes_returned;
1272 int name_len, name_len2;
1273 __u16 count;
1274
1275 cFYI(1, ("In CIFSSMBCopy"));
1276copyRetry:
1277 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1278 (void **) &pSMBr);
1279 if (rc)
1280 return rc;
1281
1282 pSMB->BufferFormat = 0x04;
1283 pSMB->Tid2 = target_tid;
1284
1285 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1286
1287 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1288 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
1289 fromName,
1290 PATH_MAX /* find define for this maxpathcomponent */,
1291 nls_codepage);
1292 name_len++; /* trailing null */
1293 name_len *= 2;
1294 pSMB->OldFileName[name_len] = 0x04; /* pad */
1295 /* protocol requires ASCII signature byte on Unicode string */
1296 pSMB->OldFileName[name_len + 1] = 0x00;
1297 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1298 OldFileName[name_len + 2], toName, PATH_MAX,
1299 nls_codepage);
1300 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1301 name_len2 *= 2; /* convert to bytes */
1302 } else { /* BB improve the check for buffer overruns BB */
1303 name_len = strnlen(fromName, PATH_MAX);
1304 name_len++; /* trailing null */
1305 strncpy(pSMB->OldFileName, fromName, name_len);
1306 name_len2 = strnlen(toName, PATH_MAX);
1307 name_len2++; /* trailing null */
1308 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1309 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1310 name_len2++; /* trailing null */
1311 name_len2++; /* signature byte */
1312 }
1313
1314 count = 1 /* 1st signature byte */ + name_len + name_len2;
1315 pSMB->hdr.smb_buf_length += count;
1316 pSMB->ByteCount = cpu_to_le16(count);
1317
1318 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1319 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1320 if (rc) {
1321 cFYI(1, ("Send error in copy = %d with %d files copied",
1322 rc, le16_to_cpu(pSMBr->CopyCount)));
1323 }
1324 if (pSMB)
1325 cifs_buf_release(pSMB);
1326
1327 if (rc == -EAGAIN)
1328 goto copyRetry;
1329
1330 return rc;
1331}
1332
1333int
1334CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1335 const char *fromName, const char *toName,
1336 const struct nls_table *nls_codepage)
1337{
1338 TRANSACTION2_SPI_REQ *pSMB = NULL;
1339 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1340 char *data_offset;
1341 int name_len;
1342 int name_len_target;
1343 int rc = 0;
1344 int bytes_returned = 0;
1345 __u16 params, param_offset, offset, byte_count;
1346
1347 cFYI(1, ("In Symlink Unix style"));
1348createSymLinkRetry:
1349 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1350 (void **) &pSMBr);
1351 if (rc)
1352 return rc;
1353
1354 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1355 name_len =
1356 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1357 /* find define for this maxpathcomponent */
1358 , nls_codepage);
1359 name_len++; /* trailing null */
1360 name_len *= 2;
1361
1362 } else { /* BB improve the check for buffer overruns BB */
1363 name_len = strnlen(fromName, PATH_MAX);
1364 name_len++; /* trailing null */
1365 strncpy(pSMB->FileName, fromName, name_len);
1366 }
1367 params = 6 + name_len;
1368 pSMB->MaxSetupCount = 0;
1369 pSMB->Reserved = 0;
1370 pSMB->Flags = 0;
1371 pSMB->Timeout = 0;
1372 pSMB->Reserved2 = 0;
1373 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1374 InformationLevel) - 4;
1375 offset = param_offset + params;
1376
1377 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1378 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1379 name_len_target =
1380 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1381 /* find define for this maxpathcomponent */
1382 , nls_codepage);
1383 name_len_target++; /* trailing null */
1384 name_len_target *= 2;
1385 } else { /* BB improve the check for buffer overruns BB */
1386 name_len_target = strnlen(toName, PATH_MAX);
1387 name_len_target++; /* trailing null */
1388 strncpy(data_offset, toName, name_len_target);
1389 }
1390
1391 pSMB->MaxParameterCount = cpu_to_le16(2);
1392 /* BB find exact max on data count below from sess */
1393 pSMB->MaxDataCount = cpu_to_le16(1000);
1394 pSMB->SetupCount = 1;
1395 pSMB->Reserved3 = 0;
1396 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1397 byte_count = 3 /* pad */ + params + name_len_target;
1398 pSMB->DataCount = cpu_to_le16(name_len_target);
1399 pSMB->ParameterCount = cpu_to_le16(params);
1400 pSMB->TotalDataCount = pSMB->DataCount;
1401 pSMB->TotalParameterCount = pSMB->ParameterCount;
1402 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1403 pSMB->DataOffset = cpu_to_le16(offset);
1404 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1405 pSMB->Reserved4 = 0;
1406 pSMB->hdr.smb_buf_length += byte_count;
1407 pSMB->ByteCount = cpu_to_le16(byte_count);
1408 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1409 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1410 if (rc) {
1411 cFYI(1,
1412 ("Send error in SetPathInfo (create symlink) = %d",
1413 rc));
1414 }
1415
1416 if (pSMB)
1417 cifs_buf_release(pSMB);
1418
1419 if (rc == -EAGAIN)
1420 goto createSymLinkRetry;
1421
1422 return rc;
1423}
1424
1425int
1426CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1427 const char *fromName, const char *toName,
1428 const struct nls_table *nls_codepage)
1429{
1430 TRANSACTION2_SPI_REQ *pSMB = NULL;
1431 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1432 char *data_offset;
1433 int name_len;
1434 int name_len_target;
1435 int rc = 0;
1436 int bytes_returned = 0;
1437 __u16 params, param_offset, offset, byte_count;
1438
1439 cFYI(1, ("In Create Hard link Unix style"));
1440createHardLinkRetry:
1441 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1442 (void **) &pSMBr);
1443 if (rc)
1444 return rc;
1445
1446 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1447 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
1448 /* find define for this maxpathcomponent */
1449 , nls_codepage);
1450 name_len++; /* trailing null */
1451 name_len *= 2;
1452
1453 } else { /* BB improve the check for buffer overruns BB */
1454 name_len = strnlen(toName, PATH_MAX);
1455 name_len++; /* trailing null */
1456 strncpy(pSMB->FileName, toName, name_len);
1457 }
1458 params = 6 + name_len;
1459 pSMB->MaxSetupCount = 0;
1460 pSMB->Reserved = 0;
1461 pSMB->Flags = 0;
1462 pSMB->Timeout = 0;
1463 pSMB->Reserved2 = 0;
1464 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1465 InformationLevel) - 4;
1466 offset = param_offset + params;
1467
1468 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1469 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1470 name_len_target =
1471 cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
1472 /* find define for this maxpathcomponent */
1473 , nls_codepage);
1474 name_len_target++; /* trailing null */
1475 name_len_target *= 2;
1476 } else { /* BB improve the check for buffer overruns BB */
1477 name_len_target = strnlen(fromName, PATH_MAX);
1478 name_len_target++; /* trailing null */
1479 strncpy(data_offset, fromName, name_len_target);
1480 }
1481
1482 pSMB->MaxParameterCount = cpu_to_le16(2);
1483 /* BB find exact max on data count below from sess*/
1484 pSMB->MaxDataCount = cpu_to_le16(1000);
1485 pSMB->SetupCount = 1;
1486 pSMB->Reserved3 = 0;
1487 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1488 byte_count = 3 /* pad */ + params + name_len_target;
1489 pSMB->ParameterCount = cpu_to_le16(params);
1490 pSMB->TotalParameterCount = pSMB->ParameterCount;
1491 pSMB->DataCount = cpu_to_le16(name_len_target);
1492 pSMB->TotalDataCount = pSMB->DataCount;
1493 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1494 pSMB->DataOffset = cpu_to_le16(offset);
1495 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1496 pSMB->Reserved4 = 0;
1497 pSMB->hdr.smb_buf_length += byte_count;
1498 pSMB->ByteCount = cpu_to_le16(byte_count);
1499 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1500 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1501 if (rc) {
1502 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1503 }
1504
1505 cifs_buf_release(pSMB);
1506 if (rc == -EAGAIN)
1507 goto createHardLinkRetry;
1508
1509 return rc;
1510}
1511
1512int
1513CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1514 const char *fromName, const char *toName,
1515 const struct nls_table *nls_codepage)
1516{
1517 int rc = 0;
1518 NT_RENAME_REQ *pSMB = NULL;
1519 RENAME_RSP *pSMBr = NULL;
1520 int bytes_returned;
1521 int name_len, name_len2;
1522 __u16 count;
1523
1524 cFYI(1, ("In CIFSCreateHardLink"));
1525winCreateHardLinkRetry:
1526
1527 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1528 (void **) &pSMBr);
1529 if (rc)
1530 return rc;
1531
1532 pSMB->SearchAttributes =
1533 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1534 ATTR_DIRECTORY);
1535 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1536 pSMB->ClusterCount = 0;
1537
1538 pSMB->BufferFormat = 0x04;
1539
1540 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1541 name_len =
1542 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
1543 /* find define for this maxpathcomponent */
1544 , nls_codepage);
1545 name_len++; /* trailing null */
1546 name_len *= 2;
1547 pSMB->OldFileName[name_len] = 0; /* pad */
1548 pSMB->OldFileName[name_len + 1] = 0x04;
1549 name_len2 =
1550 cifs_strtoUCS((wchar_t *) & pSMB->
1551 OldFileName[name_len + 2], toName, PATH_MAX,
1552 nls_codepage);
1553 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1554 name_len2 *= 2; /* convert to bytes */
1555 } else { /* BB improve the check for buffer overruns BB */
1556 name_len = strnlen(fromName, PATH_MAX);
1557 name_len++; /* trailing null */
1558 strncpy(pSMB->OldFileName, fromName, name_len);
1559 name_len2 = strnlen(toName, PATH_MAX);
1560 name_len2++; /* trailing null */
1561 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1562 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1563 name_len2++; /* trailing null */
1564 name_len2++; /* signature byte */
1565 }
1566
1567 count = 1 /* string type byte */ + name_len + name_len2;
1568 pSMB->hdr.smb_buf_length += count;
1569 pSMB->ByteCount = cpu_to_le16(count);
1570
1571 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1572 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1573 if (rc) {
1574 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1575 }
1576 cifs_buf_release(pSMB);
1577 if (rc == -EAGAIN)
1578 goto winCreateHardLinkRetry;
1579
1580 return rc;
1581}
1582
1583int
1584CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1585 const unsigned char *searchName,
1586 char *symlinkinfo, const int buflen,
1587 const struct nls_table *nls_codepage)
1588{
1589/* SMB_QUERY_FILE_UNIX_LINK */
1590 TRANSACTION2_QPI_REQ *pSMB = NULL;
1591 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1592 int rc = 0;
1593 int bytes_returned;
1594 int name_len;
1595 __u16 params, byte_count;
1596
1597 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1598
1599querySymLinkRetry:
1600 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1601 (void **) &pSMBr);
1602 if (rc)
1603 return rc;
1604
1605 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1606 name_len =
1607 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1608 /* find define for this maxpathcomponent */
1609 , nls_codepage);
1610 name_len++; /* trailing null */
1611 name_len *= 2;
1612 } else { /* BB improve the check for buffer overruns BB */
1613 name_len = strnlen(searchName, PATH_MAX);
1614 name_len++; /* trailing null */
1615 strncpy(pSMB->FileName, searchName, name_len);
1616 }
1617
1618 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1619 pSMB->TotalDataCount = 0;
1620 pSMB->MaxParameterCount = cpu_to_le16(2);
1621 /* BB find exact max data count below from sess structure BB */
1622 pSMB->MaxDataCount = cpu_to_le16(4000);
1623 pSMB->MaxSetupCount = 0;
1624 pSMB->Reserved = 0;
1625 pSMB->Flags = 0;
1626 pSMB->Timeout = 0;
1627 pSMB->Reserved2 = 0;
1628 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1629 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1630 pSMB->DataCount = 0;
1631 pSMB->DataOffset = 0;
1632 pSMB->SetupCount = 1;
1633 pSMB->Reserved3 = 0;
1634 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1635 byte_count = params + 1 /* pad */ ;
1636 pSMB->TotalParameterCount = cpu_to_le16(params);
1637 pSMB->ParameterCount = pSMB->TotalParameterCount;
1638 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1639 pSMB->Reserved4 = 0;
1640 pSMB->hdr.smb_buf_length += byte_count;
1641 pSMB->ByteCount = cpu_to_le16(byte_count);
1642
1643 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1644 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1645 if (rc) {
1646 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1647 } else {
1648 /* decode response */
1649
1650 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1651 if (rc || (pSMBr->ByteCount < 2))
1652 /* BB also check enough total bytes returned */
1653 rc = -EIO; /* bad smb */
1654 else {
1655 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1656 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1657
1658 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1659 name_len = UniStrnlen((wchar_t *) ((char *)
1660 &pSMBr->hdr.Protocol +data_offset),
1661 min_t(const int, buflen,count) / 2);
1662 cifs_strfromUCS_le(symlinkinfo,
1663 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1664 data_offset),
1665 name_len, nls_codepage);
1666 } else {
1667 strncpy(symlinkinfo,
1668 (char *) &pSMBr->hdr.Protocol +
1669 data_offset,
1670 min_t(const int, buflen, count));
1671 }
1672 symlinkinfo[buflen] = 0;
1673 /* just in case so calling code does not go off the end of buffer */
1674 }
1675 }
1676 cifs_buf_release(pSMB);
1677 if (rc == -EAGAIN)
1678 goto querySymLinkRetry;
1679 return rc;
1680}
1681
1682int
1683CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1684 const unsigned char *searchName,
1685 char *symlinkinfo, const int buflen,__u16 fid,
1686 const struct nls_table *nls_codepage)
1687{
1688 int rc = 0;
1689 int bytes_returned;
1690 int name_len;
1691 struct smb_com_transaction_ioctl_req * pSMB;
1692 struct smb_com_transaction_ioctl_rsp * pSMBr;
1693
1694 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1695 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1696 (void **) &pSMBr);
1697 if (rc)
1698 return rc;
1699
1700 pSMB->TotalParameterCount = 0 ;
1701 pSMB->TotalDataCount = 0;
1702 pSMB->MaxParameterCount = cpu_to_le32(2);
1703 /* BB find exact data count max from sess structure BB */
1704 pSMB->MaxDataCount = cpu_to_le32(4000);
1705 pSMB->MaxSetupCount = 4;
1706 pSMB->Reserved = 0;
1707 pSMB->ParameterOffset = 0;
1708 pSMB->DataCount = 0;
1709 pSMB->DataOffset = 0;
1710 pSMB->SetupCount = 4;
1711 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1712 pSMB->ParameterCount = pSMB->TotalParameterCount;
1713 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1714 pSMB->IsFsctl = 1; /* FSCTL */
1715 pSMB->IsRootFlag = 0;
1716 pSMB->Fid = fid; /* file handle always le */
1717 pSMB->ByteCount = 0;
1718
1719 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1720 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1721 if (rc) {
1722 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1723 } else { /* decode response */
1724 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1725 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1726 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1727 /* BB also check enough total bytes returned */
1728 rc = -EIO; /* bad smb */
1729 else {
1730 if(data_count && (data_count < 2048)) {
1731 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1732
1733 struct reparse_data * reparse_buf = (struct reparse_data *)
1734 ((char *)&pSMBr->hdr.Protocol + data_offset);
1735 if((char*)reparse_buf >= end_of_smb) {
1736 rc = -EIO;
1737 goto qreparse_out;
1738 }
1739 if((reparse_buf->LinkNamesBuf +
1740 reparse_buf->TargetNameOffset +
1741 reparse_buf->TargetNameLen) >
1742 end_of_smb) {
1743 cFYI(1,("reparse buf extended beyond SMB"));
1744 rc = -EIO;
1745 goto qreparse_out;
1746 }
1747
1748 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1749 name_len = UniStrnlen((wchar_t *)
1750 (reparse_buf->LinkNamesBuf +
1751 reparse_buf->TargetNameOffset),
1752 min(buflen/2, reparse_buf->TargetNameLen / 2));
1753 cifs_strfromUCS_le(symlinkinfo,
1754 (wchar_t *) (reparse_buf->LinkNamesBuf +
1755 reparse_buf->TargetNameOffset),
1756 name_len, nls_codepage);
1757 } else { /* ASCII names */
1758 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1759 reparse_buf->TargetNameOffset,
1760 min_t(const int, buflen, reparse_buf->TargetNameLen));
1761 }
1762 } else {
1763 rc = -EIO;
1764 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1765 }
1766 symlinkinfo[buflen] = 0; /* just in case so the caller
1767 does not go off the end of the buffer */
1768 cFYI(1,("readlink result - %s ",symlinkinfo));
1769 }
1770 }
1771qreparse_out:
1772 if (pSMB)
1773 cifs_buf_release(pSMB);
1774
1775 /* Note: On -EAGAIN error only caller can retry on handle based calls
1776 since file handle passed in no longer valid */
1777
1778 return rc;
1779}
1780
1781#ifdef CONFIG_CIFS_POSIX
1782
1783/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1784static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1785{
1786 /* u8 cifs fields do not need le conversion */
1787 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1788 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1789 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1790 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1791
1792 return;
1793}
1794
1795/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1796static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
1797{
1798 int size = 0;
1799 int i;
1800 __u16 count;
1801 struct cifs_posix_ace * pACE;
1802 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1803 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1804
1805 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1806 return -EOPNOTSUPP;
1807
1808 if(acl_type & ACL_TYPE_ACCESS) {
1809 count = le16_to_cpu(cifs_acl->access_entry_count);
1810 pACE = &cifs_acl->ace_array[0];
1811 size = sizeof(struct cifs_posix_acl);
1812 size += sizeof(struct cifs_posix_ace) * count;
1813 /* check if we would go beyond end of SMB */
1814 if(size_of_data_area < size) {
1815 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1816 return -EINVAL;
1817 }
1818 } else if(acl_type & ACL_TYPE_DEFAULT) {
1819 count = le16_to_cpu(cifs_acl->access_entry_count);
1820 size = sizeof(struct cifs_posix_acl);
1821 size += sizeof(struct cifs_posix_ace) * count;
1822/* skip past access ACEs to get to default ACEs */
1823 pACE = &cifs_acl->ace_array[count];
1824 count = le16_to_cpu(cifs_acl->default_entry_count);
1825 size += sizeof(struct cifs_posix_ace) * count;
1826 /* check if we would go beyond end of SMB */
1827 if(size_of_data_area < size)
1828 return -EINVAL;
1829 } else {
1830 /* illegal type */
1831 return -EINVAL;
1832 }
1833
1834 size = posix_acl_xattr_size(count);
1835 if((buflen == 0) || (local_acl == NULL)) {
1836 /* used to query ACL EA size */
1837 } else if(size > buflen) {
1838 return -ERANGE;
1839 } else /* buffer big enough */ {
1840 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1841 for(i = 0;i < count ;i++) {
1842 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1843 pACE ++;
1844 }
1845 }
1846 return size;
1847}
1848
1849static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1850 const posix_acl_xattr_entry * local_ace)
1851{
1852 __u16 rc = 0; /* 0 = ACL converted ok */
1853
1854 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1855 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1856 /* BB is there a better way to handle the large uid? */
1857 if(local_ace->e_id == -1) {
1858 /* Probably no need to le convert -1 on any arch but can not hurt */
1859 cifs_ace->cifs_uid = cpu_to_le64(-1);
1860 } else
1861 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1862 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1863 return rc;
1864}
1865
1866/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1867static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1868 const int acl_type)
1869{
1870 __u16 rc = 0;
1871 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1872 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1873 int count;
1874 int i;
1875
1876 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1877 return 0;
1878
1879 count = posix_acl_xattr_count((size_t)buflen);
1880 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1881 count,buflen,local_acl->a_version));
1882 if(local_acl->a_version != 2) {
1883 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1884 return 0;
1885 }
1886 cifs_acl->version = cpu_to_le16(1);
1887 if(acl_type == ACL_TYPE_ACCESS)
1888 cifs_acl->access_entry_count = count;
1889 else if(acl_type == ACL_TYPE_DEFAULT)
1890 cifs_acl->default_entry_count = count;
1891 else {
1892 cFYI(1,("unknown ACL type %d",acl_type));
1893 return 0;
1894 }
1895 for(i=0;i<count;i++) {
1896 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1897 &local_acl->a_entries[i]);
1898 if(rc != 0) {
1899 /* ACE not converted */
1900 break;
1901 }
1902 }
1903 if(rc == 0) {
1904 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1905 rc += sizeof(struct cifs_posix_acl);
1906 /* BB add check to make sure ACL does not overflow SMB */
1907 }
1908 return rc;
1909}
1910
1911int
1912CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1913 const unsigned char *searchName,
1914 char *acl_inf, const int buflen, const int acl_type,
1915 const struct nls_table *nls_codepage)
1916{
1917/* SMB_QUERY_POSIX_ACL */
1918 TRANSACTION2_QPI_REQ *pSMB = NULL;
1919 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1920 int rc = 0;
1921 int bytes_returned;
1922 int name_len;
1923 __u16 params, byte_count;
1924
1925 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1926
1927queryAclRetry:
1928 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1929 (void **) &pSMBr);
1930 if (rc)
1931 return rc;
1932
1933 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1934 name_len =
1935 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1936 , nls_codepage);
1937 name_len++; /* trailing null */
1938 name_len *= 2;
1939 pSMB->FileName[name_len] = 0;
1940 pSMB->FileName[name_len+1] = 0;
1941 } else { /* BB improve the check for buffer overruns BB */
1942 name_len = strnlen(searchName, PATH_MAX);
1943 name_len++; /* trailing null */
1944 strncpy(pSMB->FileName, searchName, name_len);
1945 }
1946
1947 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1948 pSMB->TotalDataCount = 0;
1949 pSMB->MaxParameterCount = cpu_to_le16(2);
1950 /* BB find exact max data count below from sess structure BB */
1951 pSMB->MaxDataCount = cpu_to_le16(4000);
1952 pSMB->MaxSetupCount = 0;
1953 pSMB->Reserved = 0;
1954 pSMB->Flags = 0;
1955 pSMB->Timeout = 0;
1956 pSMB->Reserved2 = 0;
1957 pSMB->ParameterOffset = cpu_to_le16(
1958 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1959 pSMB->DataCount = 0;
1960 pSMB->DataOffset = 0;
1961 pSMB->SetupCount = 1;
1962 pSMB->Reserved3 = 0;
1963 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1964 byte_count = params + 1 /* pad */ ;
1965 pSMB->TotalParameterCount = cpu_to_le16(params);
1966 pSMB->ParameterCount = pSMB->TotalParameterCount;
1967 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
1968 pSMB->Reserved4 = 0;
1969 pSMB->hdr.smb_buf_length += byte_count;
1970 pSMB->ByteCount = cpu_to_le16(byte_count);
1971
1972 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1973 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1974 if (rc) {
1975 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
1976 } else {
1977 /* decode response */
1978
1979 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1980 if (rc || (pSMBr->ByteCount < 2))
1981 /* BB also check enough total bytes returned */
1982 rc = -EIO; /* bad smb */
1983 else {
1984 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1985 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1986 rc = cifs_copy_posix_acl(acl_inf,
1987 (char *)&pSMBr->hdr.Protocol+data_offset,
1988 buflen,acl_type,count);
1989 }
1990 }
1991 cifs_buf_release(pSMB);
1992 if (rc == -EAGAIN)
1993 goto queryAclRetry;
1994 return rc;
1995}
1996
1997int
1998CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
1999 const unsigned char *fileName,
2000 const char *local_acl, const int buflen, const int acl_type,
2001 const struct nls_table *nls_codepage)
2002{
2003 struct smb_com_transaction2_spi_req *pSMB = NULL;
2004 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2005 char *parm_data;
2006 int name_len;
2007 int rc = 0;
2008 int bytes_returned = 0;
2009 __u16 params, byte_count, data_count, param_offset, offset;
2010
2011 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2012setAclRetry:
2013 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2014 (void **) &pSMBr);
2015 if (rc)
2016 return rc;
2017 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2018 name_len =
2019 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
2020 , nls_codepage);
2021 name_len++; /* trailing null */
2022 name_len *= 2;
2023 } else { /* BB improve the check for buffer overruns BB */
2024 name_len = strnlen(fileName, PATH_MAX);
2025 name_len++; /* trailing null */
2026 strncpy(pSMB->FileName, fileName, name_len);
2027 }
2028 params = 6 + name_len;
2029 pSMB->MaxParameterCount = cpu_to_le16(2);
2030 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2031 pSMB->MaxSetupCount = 0;
2032 pSMB->Reserved = 0;
2033 pSMB->Flags = 0;
2034 pSMB->Timeout = 0;
2035 pSMB->Reserved2 = 0;
2036 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2037 InformationLevel) - 4;
2038 offset = param_offset + params;
2039 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2040 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2041
2042 /* convert to on the wire format for POSIX ACL */
2043 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2044
2045 if(data_count == 0) {
2046 rc = -EOPNOTSUPP;
2047 goto setACLerrorExit;
2048 }
2049 pSMB->DataOffset = cpu_to_le16(offset);
2050 pSMB->SetupCount = 1;
2051 pSMB->Reserved3 = 0;
2052 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2053 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2054 byte_count = 3 /* pad */ + params + data_count;
2055 pSMB->DataCount = cpu_to_le16(data_count);
2056 pSMB->TotalDataCount = pSMB->DataCount;
2057 pSMB->ParameterCount = cpu_to_le16(params);
2058 pSMB->TotalParameterCount = pSMB->ParameterCount;
2059 pSMB->Reserved4 = 0;
2060 pSMB->hdr.smb_buf_length += byte_count;
2061 pSMB->ByteCount = cpu_to_le16(byte_count);
2062 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2063 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2064 if (rc) {
2065 cFYI(1, ("Set POSIX ACL returned %d", rc));
2066 }
2067
2068setACLerrorExit:
2069 cifs_buf_release(pSMB);
2070 if (rc == -EAGAIN)
2071 goto setAclRetry;
2072 return rc;
2073}
2074
2075#endif
2076
2077int
2078CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2079 const unsigned char *searchName,
2080 FILE_ALL_INFO * pFindData,
2081 const struct nls_table *nls_codepage)
2082{
2083/* level 263 SMB_QUERY_FILE_ALL_INFO */
2084 TRANSACTION2_QPI_REQ *pSMB = NULL;
2085 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2086 int rc = 0;
2087 int bytes_returned;
2088 int name_len;
2089 __u16 params, byte_count;
2090
2091/* cFYI(1, ("In QPathInfo path %s", searchName)); */
2092QPathInfoRetry:
2093 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2094 (void **) &pSMBr);
2095 if (rc)
2096 return rc;
2097
2098 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2099 name_len =
2100 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2101 /* find define for this maxpathcomponent */
2102 , nls_codepage);
2103 name_len++; /* trailing null */
2104 name_len *= 2;
2105 } else { /* BB improve the check for buffer overruns BB */
2106 name_len = strnlen(searchName, PATH_MAX);
2107 name_len++; /* trailing null */
2108 strncpy(pSMB->FileName, searchName, name_len);
2109 }
2110
2111 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2112 pSMB->TotalDataCount = 0;
2113 pSMB->MaxParameterCount = cpu_to_le16(2);
2114 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2115 pSMB->MaxSetupCount = 0;
2116 pSMB->Reserved = 0;
2117 pSMB->Flags = 0;
2118 pSMB->Timeout = 0;
2119 pSMB->Reserved2 = 0;
2120 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2121 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2122 pSMB->DataCount = 0;
2123 pSMB->DataOffset = 0;
2124 pSMB->SetupCount = 1;
2125 pSMB->Reserved3 = 0;
2126 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2127 byte_count = params + 1 /* pad */ ;
2128 pSMB->TotalParameterCount = cpu_to_le16(params);
2129 pSMB->ParameterCount = pSMB->TotalParameterCount;
2130 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2131 pSMB->Reserved4 = 0;
2132 pSMB->hdr.smb_buf_length += byte_count;
2133 pSMB->ByteCount = cpu_to_le16(byte_count);
2134
2135 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2136 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2137 if (rc) {
2138 cFYI(1, ("Send error in QPathInfo = %d", rc));
2139 } else { /* decode response */
2140 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2141
2142 if (rc || (pSMBr->ByteCount < 40))
2143 rc = -EIO; /* bad smb */
2144 else if (pFindData){
2145 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2146 memcpy((char *) pFindData,
2147 (char *) &pSMBr->hdr.Protocol +
2148 data_offset, sizeof (FILE_ALL_INFO));
2149 } else
2150 rc = -ENOMEM;
2151 }
2152 cifs_buf_release(pSMB);
2153 if (rc == -EAGAIN)
2154 goto QPathInfoRetry;
2155
2156 return rc;
2157}
2158
2159int
2160CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2161 const unsigned char *searchName,
2162 FILE_UNIX_BASIC_INFO * pFindData,
2163 const struct nls_table *nls_codepage)
2164{
2165/* SMB_QUERY_FILE_UNIX_BASIC */
2166 TRANSACTION2_QPI_REQ *pSMB = NULL;
2167 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2168 int rc = 0;
2169 int bytes_returned = 0;
2170 int name_len;
2171 __u16 params, byte_count;
2172
2173 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2174UnixQPathInfoRetry:
2175 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2176 (void **) &pSMBr);
2177 if (rc)
2178 return rc;
2179
2180 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2181 name_len =
2182 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2183 /* find define for this maxpathcomponent */
2184 , nls_codepage);
2185 name_len++; /* trailing null */
2186 name_len *= 2;
2187 } else { /* BB improve the check for buffer overruns BB */
2188 name_len = strnlen(searchName, PATH_MAX);
2189 name_len++; /* trailing null */
2190 strncpy(pSMB->FileName, searchName, name_len);
2191 }
2192
2193 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2194 pSMB->TotalDataCount = 0;
2195 pSMB->MaxParameterCount = cpu_to_le16(2);
2196 /* BB find exact max SMB PDU from sess structure BB */
2197 pSMB->MaxDataCount = cpu_to_le16(4000);
2198 pSMB->MaxSetupCount = 0;
2199 pSMB->Reserved = 0;
2200 pSMB->Flags = 0;
2201 pSMB->Timeout = 0;
2202 pSMB->Reserved2 = 0;
2203 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2204 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2205 pSMB->DataCount = 0;
2206 pSMB->DataOffset = 0;
2207 pSMB->SetupCount = 1;
2208 pSMB->Reserved3 = 0;
2209 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2210 byte_count = params + 1 /* pad */ ;
2211 pSMB->TotalParameterCount = cpu_to_le16(params);
2212 pSMB->ParameterCount = pSMB->TotalParameterCount;
2213 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2214 pSMB->Reserved4 = 0;
2215 pSMB->hdr.smb_buf_length += byte_count;
2216 pSMB->ByteCount = cpu_to_le16(byte_count);
2217
2218 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2219 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2220 if (rc) {
2221 cFYI(1, ("Send error in QPathInfo = %d", rc));
2222 } else { /* decode response */
2223 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2224
2225 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2226 rc = -EIO; /* bad smb */
2227 } else {
2228 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2229 memcpy((char *) pFindData,
2230 (char *) &pSMBr->hdr.Protocol +
2231 data_offset,
2232 sizeof (FILE_UNIX_BASIC_INFO));
2233 }
2234 }
2235 cifs_buf_release(pSMB);
2236 if (rc == -EAGAIN)
2237 goto UnixQPathInfoRetry;
2238
2239 return rc;
2240}
2241
2242#if 0 /* function unused at present */
2243int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2244 const char *searchName, FILE_ALL_INFO * findData,
2245 const struct nls_table *nls_codepage)
2246{
2247/* level 257 SMB_ */
2248 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2249 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2250 int rc = 0;
2251 int bytes_returned;
2252 int name_len;
2253 __u16 params, byte_count;
2254
2255 cFYI(1, ("In FindUnique"));
2256findUniqueRetry:
2257 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2258 (void **) &pSMBr);
2259 if (rc)
2260 return rc;
2261
2262 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2263 name_len =
2264 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2265 /* find define for this maxpathcomponent */
2266 , nls_codepage);
2267 name_len++; /* trailing null */
2268 name_len *= 2;
2269 } else { /* BB improve the check for buffer overruns BB */
2270 name_len = strnlen(searchName, PATH_MAX);
2271 name_len++; /* trailing null */
2272 strncpy(pSMB->FileName, searchName, name_len);
2273 }
2274
2275 params = 12 + name_len /* includes null */ ;
2276 pSMB->TotalDataCount = 0; /* no EAs */
2277 pSMB->MaxParameterCount = cpu_to_le16(2);
2278 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2279 pSMB->MaxSetupCount = 0;
2280 pSMB->Reserved = 0;
2281 pSMB->Flags = 0;
2282 pSMB->Timeout = 0;
2283 pSMB->Reserved2 = 0;
2284 pSMB->ParameterOffset = cpu_to_le16(
2285 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2286 pSMB->DataCount = 0;
2287 pSMB->DataOffset = 0;
2288 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2289 pSMB->Reserved3 = 0;
2290 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2291 byte_count = params + 1 /* pad */ ;
2292 pSMB->TotalParameterCount = cpu_to_le16(params);
2293 pSMB->ParameterCount = pSMB->TotalParameterCount;
2294 pSMB->SearchAttributes =
2295 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2296 ATTR_DIRECTORY);
2297 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2298 pSMB->SearchFlags = cpu_to_le16(1);
2299 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2300 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2301 pSMB->hdr.smb_buf_length += byte_count;
2302 pSMB->ByteCount = cpu_to_le16(byte_count);
2303
2304 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2305 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2306
2307 if (rc) {
2308 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2309 } else { /* decode response */
2310
2311 /* BB fill in */
2312 }
2313
2314 cifs_buf_release(pSMB);
2315 if (rc == -EAGAIN)
2316 goto findUniqueRetry;
2317
2318 return rc;
2319}
2320#endif /* end unused (temporarily) function */
2321
2322/* xid, tcon, searchName and codepage are input parms, rest are returned */
2323int
2324CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2325 const char *searchName,
2326 const struct nls_table *nls_codepage,
2327 __u16 * pnetfid,
2328 struct cifs_search_info * psrch_inf)
2329{
2330/* level 257 SMB_ */
2331 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2332 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2333 T2_FFIRST_RSP_PARMS * parms;
2334 int rc = 0;
2335 int bytes_returned = 0;
2336 int name_len;
2337 __u16 params, byte_count;
2338
2339 cFYI(1, ("In FindFirst"));
2340
2341findFirstRetry:
2342 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2343 (void **) &pSMBr);
2344 if (rc)
2345 return rc;
2346
2347 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2348 name_len =
2349 cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
2350 PATH_MAX, nls_codepage);
2351 name_len++; /* trailing null */
2352 name_len *= 2;
2353 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2354 pSMB->FileName[name_len+1] = 0;
2355 } else { /* BB add check for overrun of SMB buf BB */
2356 name_len = strnlen(searchName, PATH_MAX);
2357 name_len++; /* trailing null */
2358/* BB fix here and in unicode clause above ie
2359 if(name_len > buffersize-header)
2360 free buffer exit; BB */
2361 strncpy(pSMB->FileName, searchName, name_len);
2362 pSMB->FileName[name_len] = 0; /* just in case */
2363 }
2364
2365 params = 12 + name_len /* includes null */ ;
2366 pSMB->TotalDataCount = 0; /* no EAs */
2367 pSMB->MaxParameterCount = cpu_to_le16(10);
2368 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2369 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2370 pSMB->MaxSetupCount = 0;
2371 pSMB->Reserved = 0;
2372 pSMB->Flags = 0;
2373 pSMB->Timeout = 0;
2374 pSMB->Reserved2 = 0;
2375 byte_count = params + 1 /* pad */ ;
2376 pSMB->TotalParameterCount = cpu_to_le16(params);
2377 pSMB->ParameterCount = pSMB->TotalParameterCount;
2378 pSMB->ParameterOffset = cpu_to_le16(
2379 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2380 pSMB->DataCount = 0;
2381 pSMB->DataOffset = 0;
2382 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2383 pSMB->Reserved3 = 0;
2384 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2385 pSMB->SearchAttributes =
2386 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2387 ATTR_DIRECTORY);
2388 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2389 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2390 CIFS_SEARCH_RETURN_RESUME);
2391 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2392
2393 /* BB what should we set StorageType to? Does it matter? BB */
2394 pSMB->SearchStorageType = 0;
2395 pSMB->hdr.smb_buf_length += byte_count;
2396 pSMB->ByteCount = cpu_to_le16(byte_count);
2397
2398 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2399 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2400
2401 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2402 /* BB Add code to handle unsupported level rc */
2403 cFYI(1, ("Error in FindFirst = %d", rc));
2404
2405 if (pSMB)
2406 cifs_buf_release(pSMB);
2407
2408 /* BB eventually could optimize out free and realloc of buf */
2409 /* for this case */
2410 if (rc == -EAGAIN)
2411 goto findFirstRetry;
2412 } else { /* decode response */
2413 /* BB remember to free buffer if error BB */
2414 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2415 if(rc == 0) {
2416 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2417 psrch_inf->unicode = TRUE;
2418 else
2419 psrch_inf->unicode = FALSE;
2420
2421 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2422 psrch_inf->srch_entries_start =
2423 (char *) &pSMBr->hdr.Protocol +
2424 le16_to_cpu(pSMBr->t2.DataOffset);
2425
2426 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2427 le16_to_cpu(pSMBr->t2.ParameterOffset));
2428
2429 if(parms->EndofSearch)
2430 psrch_inf->endOfSearch = TRUE;
2431 else
2432 psrch_inf->endOfSearch = FALSE;
2433
2434 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2435 psrch_inf->index_of_last_entry =
2436 psrch_inf->entries_in_buffer;
2437/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2438 *pnetfid = parms->SearchHandle;
2439 } else {
2440 cifs_buf_release(pSMB);
2441 }
2442 }
2443
2444 return rc;
2445}
2446
2447int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2448 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2449{
2450 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2451 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2452 T2_FNEXT_RSP_PARMS * parms;
2453 char *response_data;
2454 int rc = 0;
2455 int bytes_returned, name_len;
2456 __u16 params, byte_count;
2457
2458 cFYI(1, ("In FindNext"));
2459
2460 if(psrch_inf->endOfSearch == TRUE)
2461 return -ENOENT;
2462
2463 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2464 (void **) &pSMBr);
2465 if (rc)
2466 return rc;
2467
2468 params = 14; /* includes 2 bytes of null string, converted to LE below */
2469 byte_count = 0;
2470 pSMB->TotalDataCount = 0; /* no EAs */
2471 pSMB->MaxParameterCount = cpu_to_le16(8);
2472 pSMB->MaxDataCount =
2473 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2474 pSMB->MaxSetupCount = 0;
2475 pSMB->Reserved = 0;
2476 pSMB->Flags = 0;
2477 pSMB->Timeout = 0;
2478 pSMB->Reserved2 = 0;
2479 pSMB->ParameterOffset = cpu_to_le16(
2480 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2481 pSMB->DataCount = 0;
2482 pSMB->DataOffset = 0;
2483 pSMB->SetupCount = 1;
2484 pSMB->Reserved3 = 0;
2485 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2486 pSMB->SearchHandle = searchHandle; /* always kept as le */
2487 pSMB->SearchCount =
2488 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2489 /* test for Unix extensions */
2490/* if (tcon->ses->capabilities & CAP_UNIX) {
2491 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2492 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2493 } else {
2494 pSMB->InformationLevel =
2495 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2496 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2497 } */
2498 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2499 pSMB->ResumeKey = psrch_inf->resume_key;
2500 pSMB->SearchFlags =
2501 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2502
2503 name_len = psrch_inf->resume_name_len;
2504 params += name_len;
2505 if(name_len < PATH_MAX) {
2506 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2507 byte_count += name_len;
2508 } else {
2509 rc = -EINVAL;
2510 goto FNext2_err_exit;
2511 }
2512 byte_count = params + 1 /* pad */ ;
2513 pSMB->TotalParameterCount = cpu_to_le16(params);
2514 pSMB->ParameterCount = pSMB->TotalParameterCount;
2515 pSMB->hdr.smb_buf_length += byte_count;
2516 pSMB->ByteCount = cpu_to_le16(byte_count);
2517
2518 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2519 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2520
2521 if (rc) {
2522 if (rc == -EBADF) {
2523 psrch_inf->endOfSearch = TRUE;
2524 rc = 0; /* search probably was closed at end of search above */
2525 } else
2526 cFYI(1, ("FindNext returned = %d", rc));
2527 } else { /* decode response */
2528 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2529
2530 if(rc == 0) {
2531 /* BB fixme add lock for file (srch_info) struct here */
2532 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2533 psrch_inf->unicode = TRUE;
2534 else
2535 psrch_inf->unicode = FALSE;
2536 response_data = (char *) &pSMBr->hdr.Protocol +
2537 le16_to_cpu(pSMBr->t2.ParameterOffset);
2538 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2539 response_data = (char *)&pSMBr->hdr.Protocol +
2540 le16_to_cpu(pSMBr->t2.DataOffset);
2541 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2542 psrch_inf->srch_entries_start = response_data;
2543 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2544 if(parms->EndofSearch)
2545 psrch_inf->endOfSearch = TRUE;
2546 else
2547 psrch_inf->endOfSearch = FALSE;
2548
2549 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2550 psrch_inf->index_of_last_entry +=
2551 psrch_inf->entries_in_buffer;
2552/* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2553
2554 /* BB fixme add unlock here */
2555 }
2556
2557 }
2558
2559 /* BB On error, should we leave previous search buf (and count and
2560 last entry fields) intact or free the previous one? */
2561
2562 /* Note: On -EAGAIN error only caller can retry on handle based calls
2563 since file handle passed in no longer valid */
2564FNext2_err_exit:
2565 if (rc != 0)
2566 cifs_buf_release(pSMB);
2567
2568 return rc;
2569}
2570
2571int
2572CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2573{
2574 int rc = 0;
2575 FINDCLOSE_REQ *pSMB = NULL;
2576 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2577 int bytes_returned;
2578
2579 cFYI(1, ("In CIFSSMBFindClose"));
2580 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2581
2582 /* no sense returning error if session restarted
2583 as file handle has been closed */
2584 if(rc == -EAGAIN)
2585 return 0;
2586 if (rc)
2587 return rc;
2588
2589 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2590 pSMB->FileID = searchHandle;
2591 pSMB->ByteCount = 0;
2592 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2593 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2594 if (rc) {
2595 cERROR(1, ("Send error in FindClose = %d", rc));
2596 }
2597 cifs_small_buf_release(pSMB);
2598
2599 /* Since session is dead, search handle closed on server already */
2600 if (rc == -EAGAIN)
2601 rc = 0;
2602
2603 return rc;
2604}
2605
2606#ifdef CONFIG_CIFS_EXPERIMENTAL
2607int
2608CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2609 const unsigned char *searchName,
2610 __u64 * inode_number,
2611 const struct nls_table *nls_codepage)
2612{
2613 int rc = 0;
2614 TRANSACTION2_QPI_REQ *pSMB = NULL;
2615 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2616 int name_len, bytes_returned;
2617 __u16 params, byte_count;
2618
2619 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2620 if(tcon == NULL)
2621 return -ENODEV;
2622
2623GetInodeNumberRetry:
2624 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2625 (void **) &pSMBr);
2626 if (rc)
2627 return rc;
2628
2629
2630 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2631 name_len =
2632 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName,
2633 PATH_MAX,nls_codepage);
2634 name_len++; /* trailing null */
2635 name_len *= 2;
2636 } else { /* BB improve the check for buffer overruns BB */
2637 name_len = strnlen(searchName, PATH_MAX);
2638 name_len++; /* trailing null */
2639 strncpy(pSMB->FileName, searchName, name_len);
2640 }
2641
2642 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2643 pSMB->TotalDataCount = 0;
2644 pSMB->MaxParameterCount = cpu_to_le16(2);
2645 /* BB find exact max data count below from sess structure BB */
2646 pSMB->MaxDataCount = cpu_to_le16(4000);
2647 pSMB->MaxSetupCount = 0;
2648 pSMB->Reserved = 0;
2649 pSMB->Flags = 0;
2650 pSMB->Timeout = 0;
2651 pSMB->Reserved2 = 0;
2652 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2653 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2654 pSMB->DataCount = 0;
2655 pSMB->DataOffset = 0;
2656 pSMB->SetupCount = 1;
2657 pSMB->Reserved3 = 0;
2658 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2659 byte_count = params + 1 /* pad */ ;
2660 pSMB->TotalParameterCount = cpu_to_le16(params);
2661 pSMB->ParameterCount = pSMB->TotalParameterCount;
2662 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
2663 pSMB->Reserved4 = 0;
2664 pSMB->hdr.smb_buf_length += byte_count;
2665 pSMB->ByteCount = cpu_to_le16(byte_count);
2666
2667 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2668 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2669 if (rc) {
2670 cFYI(1, ("error %d in QueryInternalInfo", rc));
2671 } else {
2672 /* decode response */
2673 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2674 if (rc || (pSMBr->ByteCount < 2))
2675 /* BB also check enough total bytes returned */
2676 /* If rc should we check for EOPNOSUPP and
2677 disable the srvino flag? or in caller? */
2678 rc = -EIO; /* bad smb */
2679 else {
2680 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2681 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2682 struct file_internal_info * pfinfo;
2683 /* BB Do we need a cast or hash here ? */
2684 if(count < 8) {
2685 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2686 rc = -EIO;
2687 goto GetInodeNumOut;
2688 }
2689 pfinfo = (struct file_internal_info *)
2690 (data_offset + (char *) &pSMBr->hdr.Protocol);
2691 *inode_number = pfinfo->UniqueId;
2692 }
2693 }
2694GetInodeNumOut:
2695 cifs_buf_release(pSMB);
2696 if (rc == -EAGAIN)
2697 goto GetInodeNumberRetry;
2698 return rc;
2699}
2700#endif /* CIFS_EXPERIMENTAL */
2701
2702int
2703CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2704 const unsigned char *searchName,
2705 unsigned char **targetUNCs,
2706 unsigned int *number_of_UNC_in_array,
2707 const struct nls_table *nls_codepage)
2708{
2709/* TRANS2_GET_DFS_REFERRAL */
2710 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2711 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2712 struct dfs_referral_level_3 * referrals = NULL;
2713 int rc = 0;
2714 int bytes_returned;
2715 int name_len;
2716 unsigned int i;
2717 char * temp;
2718 __u16 params, byte_count;
2719 *number_of_UNC_in_array = 0;
2720 *targetUNCs = NULL;
2721
2722 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2723 if (ses == NULL)
2724 return -ENODEV;
2725getDFSRetry:
2726 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2727 (void **) &pSMBr);
2728 if (rc)
2729 return rc;
2730
2731 pSMB->hdr.Tid = ses->ipc_tid;
2732 pSMB->hdr.Uid = ses->Suid;
2733 if (ses->capabilities & CAP_STATUS32) {
2734 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2735 }
2736 if (ses->capabilities & CAP_DFS) {
2737 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2738 }
2739
2740 if (ses->capabilities & CAP_UNICODE) {
2741 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2742 name_len =
2743 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2744 searchName, PATH_MAX
2745 /* find define for this maxpathcomponent */
2746 , nls_codepage);
2747 name_len++; /* trailing null */
2748 name_len *= 2;
2749 } else { /* BB improve the check for buffer overruns BB */
2750 name_len = strnlen(searchName, PATH_MAX);
2751 name_len++; /* trailing null */
2752 strncpy(pSMB->RequestFileName, searchName, name_len);
2753 }
2754
2755 params = 2 /* level */ + name_len /*includes null */ ;
2756 pSMB->TotalDataCount = 0;
2757 pSMB->DataCount = 0;
2758 pSMB->DataOffset = 0;
2759 pSMB->MaxParameterCount = 0;
2760 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2761 pSMB->MaxSetupCount = 0;
2762 pSMB->Reserved = 0;
2763 pSMB->Flags = 0;
2764 pSMB->Timeout = 0;
2765 pSMB->Reserved2 = 0;
2766 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2767 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2768 pSMB->SetupCount = 1;
2769 pSMB->Reserved3 = 0;
2770 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2771 byte_count = params + 3 /* pad */ ;
2772 pSMB->ParameterCount = cpu_to_le16(params);
2773 pSMB->TotalParameterCount = pSMB->ParameterCount;
2774 pSMB->MaxReferralLevel = cpu_to_le16(3);
2775 pSMB->hdr.smb_buf_length += byte_count;
2776 pSMB->ByteCount = cpu_to_le16(byte_count);
2777
2778 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2779 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2780 if (rc) {
2781 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2782 } else { /* decode response */
2783/* BB Add logic to parse referrals here */
2784 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2785
2786 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
2787 rc = -EIO; /* bad smb */
2788 else {
2789 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2790 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2791
2792 cFYI(1,
2793 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2794 pSMBr->ByteCount, data_offset));
2795 referrals =
2796 (struct dfs_referral_level_3 *)
2797 (8 /* sizeof start of data block */ +
2798 data_offset +
2799 (char *) &pSMBr->hdr.Protocol);
2800 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
2801 le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
2802 /* BB This field is actually two bytes in from start of
2803 data block so we could do safety check that DataBlock
2804 begins at address of pSMBr->NumberOfReferrals */
2805 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2806
2807 /* BB Fix below so can return more than one referral */
2808 if(*number_of_UNC_in_array > 1)
2809 *number_of_UNC_in_array = 1;
2810
2811 /* get the length of the strings describing refs */
2812 name_len = 0;
2813 for(i=0;i<*number_of_UNC_in_array;i++) {
2814 /* make sure that DfsPathOffset not past end */
2815 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2816 if (offset > data_count) {
2817 /* if invalid referral, stop here and do
2818 not try to copy any more */
2819 *number_of_UNC_in_array = i;
2820 break;
2821 }
2822 temp = ((char *)referrals) + offset;
2823
2824 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2825 name_len += UniStrnlen((wchar_t *)temp,data_count);
2826 } else {
2827 name_len += strnlen(temp,data_count);
2828 }
2829 referrals++;
2830 /* BB add check that referral pointer does not fall off end PDU */
2831
2832 }
2833 /* BB add check for name_len bigger than bcc */
2834 *targetUNCs =
2835 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2836 if(*targetUNCs == NULL) {
2837 rc = -ENOMEM;
2838 goto GetDFSRefExit;
2839 }
2840 /* copy the ref strings */
2841 referrals =
2842 (struct dfs_referral_level_3 *)
2843 (8 /* sizeof data hdr */ +
2844 data_offset +
2845 (char *) &pSMBr->hdr.Protocol);
2846
2847 for(i=0;i<*number_of_UNC_in_array;i++) {
2848 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2849 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2850 cifs_strfromUCS_le(*targetUNCs,
2851 (wchar_t *) temp, name_len, nls_codepage);
2852 } else {
2853 strncpy(*targetUNCs,temp,name_len);
2854 }
2855 /* BB update target_uncs pointers */
2856 referrals++;
2857 }
2858 temp = *targetUNCs;
2859 temp[name_len] = 0;
2860 }
2861
2862 }
2863GetDFSRefExit:
2864 if (pSMB)
2865 cifs_buf_release(pSMB);
2866
2867 if (rc == -EAGAIN)
2868 goto getDFSRetry;
2869
2870 return rc;
2871}
2872
2873int
2874CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2875 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2876{
2877/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2878 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2879 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2880 FILE_SYSTEM_INFO *response_data;
2881 int rc = 0;
2882 int bytes_returned = 0;
2883 __u16 params, byte_count;
2884
2885 cFYI(1, ("In QFSInfo"));
2886QFSInfoRetry:
2887 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2888 (void **) &pSMBr);
2889 if (rc)
2890 return rc;
2891
2892 params = 2; /* level */
2893 pSMB->TotalDataCount = 0;
2894 pSMB->MaxParameterCount = cpu_to_le16(2);
2895 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2896 pSMB->MaxSetupCount = 0;
2897 pSMB->Reserved = 0;
2898 pSMB->Flags = 0;
2899 pSMB->Timeout = 0;
2900 pSMB->Reserved2 = 0;
2901 byte_count = params + 1 /* pad */ ;
2902 pSMB->TotalParameterCount = cpu_to_le16(params);
2903 pSMB->ParameterCount = pSMB->TotalParameterCount;
2904 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2905 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2906 pSMB->DataCount = 0;
2907 pSMB->DataOffset = 0;
2908 pSMB->SetupCount = 1;
2909 pSMB->Reserved3 = 0;
2910 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2911 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2912 pSMB->hdr.smb_buf_length += byte_count;
2913 pSMB->ByteCount = cpu_to_le16(byte_count);
2914
2915 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2916 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2917 if (rc) {
2918 cERROR(1, ("Send error in QFSInfo = %d", rc));
2919 } else { /* decode response */
2920 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2921
2922 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
2923 rc = -EIO; /* bad smb */
2924 else {
2925 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2926 cFYI(1,
2927 ("Decoding qfsinfo response. BCC: %d Offset %d",
2928 pSMBr->ByteCount, data_offset));
2929
2930 response_data =
2931 (FILE_SYSTEM_INFO
2932 *) (((char *) &pSMBr->hdr.Protocol) +
2933 data_offset);
2934 FSData->f_bsize =
2935 le32_to_cpu(response_data->BytesPerSector) *
2936 le32_to_cpu(response_data->
2937 SectorsPerAllocationUnit);
2938 FSData->f_blocks =
2939 le64_to_cpu(response_data->TotalAllocationUnits);
2940 FSData->f_bfree = FSData->f_bavail =
2941 le64_to_cpu(response_data->FreeAllocationUnits);
2942 cFYI(1,
2943 ("Blocks: %lld Free: %lld Block size %ld",
2944 (unsigned long long)FSData->f_blocks,
2945 (unsigned long long)FSData->f_bfree,
2946 FSData->f_bsize));
2947 }
2948 }
2949 cifs_buf_release(pSMB);
2950
2951 if (rc == -EAGAIN)
2952 goto QFSInfoRetry;
2953
2954 return rc;
2955}
2956
2957int
2958CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
2959 const struct nls_table *nls_codepage)
2960{
2961/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
2962 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2963 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2964 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
2965 int rc = 0;
2966 int bytes_returned = 0;
2967 __u16 params, byte_count;
2968
2969 cFYI(1, ("In QFSAttributeInfo"));
2970QFSAttributeRetry:
2971 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2972 (void **) &pSMBr);
2973 if (rc)
2974 return rc;
2975
2976 params = 2; /* level */
2977 pSMB->TotalDataCount = 0;
2978 pSMB->MaxParameterCount = cpu_to_le16(2);
2979 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2980 pSMB->MaxSetupCount = 0;
2981 pSMB->Reserved = 0;
2982 pSMB->Flags = 0;
2983 pSMB->Timeout = 0;
2984 pSMB->Reserved2 = 0;
2985 byte_count = params + 1 /* pad */ ;
2986 pSMB->TotalParameterCount = cpu_to_le16(params);
2987 pSMB->ParameterCount = pSMB->TotalParameterCount;
2988 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2989 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2990 pSMB->DataCount = 0;
2991 pSMB->DataOffset = 0;
2992 pSMB->SetupCount = 1;
2993 pSMB->Reserved3 = 0;
2994 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2995 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
2996 pSMB->hdr.smb_buf_length += byte_count;
2997 pSMB->ByteCount = cpu_to_le16(byte_count);
2998
2999 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3000 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3001 if (rc) {
3002 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3003 } else { /* decode response */
3004 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3005
3006 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3007 rc = -EIO; /* bad smb */
3008 } else {
3009 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3010 response_data =
3011 (FILE_SYSTEM_ATTRIBUTE_INFO
3012 *) (((char *) &pSMBr->hdr.Protocol) +
3013 data_offset);
3014 memcpy(&tcon->fsAttrInfo, response_data,
3015 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3016 }
3017 }
3018 cifs_buf_release(pSMB);
3019
3020 if (rc == -EAGAIN)
3021 goto QFSAttributeRetry;
3022
3023 return rc;
3024}
3025
3026int
3027CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
3028 const struct nls_table *nls_codepage)
3029{
3030/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3031 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3032 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3033 FILE_SYSTEM_DEVICE_INFO *response_data;
3034 int rc = 0;
3035 int bytes_returned = 0;
3036 __u16 params, byte_count;
3037
3038 cFYI(1, ("In QFSDeviceInfo"));
3039QFSDeviceRetry:
3040 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3041 (void **) &pSMBr);
3042 if (rc)
3043 return rc;
3044
3045 params = 2; /* level */
3046 pSMB->TotalDataCount = 0;
3047 pSMB->MaxParameterCount = cpu_to_le16(2);
3048 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3049 pSMB->MaxSetupCount = 0;
3050 pSMB->Reserved = 0;
3051 pSMB->Flags = 0;
3052 pSMB->Timeout = 0;
3053 pSMB->Reserved2 = 0;
3054 byte_count = params + 1 /* pad */ ;
3055 pSMB->TotalParameterCount = cpu_to_le16(params);
3056 pSMB->ParameterCount = pSMB->TotalParameterCount;
3057 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3058 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3059
3060 pSMB->DataCount = 0;
3061 pSMB->DataOffset = 0;
3062 pSMB->SetupCount = 1;
3063 pSMB->Reserved3 = 0;
3064 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3065 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3066 pSMB->hdr.smb_buf_length += byte_count;
3067 pSMB->ByteCount = cpu_to_le16(byte_count);
3068
3069 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3070 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3071 if (rc) {
3072 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3073 } else { /* decode response */
3074 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3075
3076 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3077 rc = -EIO; /* bad smb */
3078 else {
3079 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3080 response_data =
3081 (FILE_SYSTEM_DEVICE_INFO
3082 *) (((char *) &pSMBr->hdr.Protocol) +
3083 data_offset);
3084 memcpy(&tcon->fsDevInfo, response_data,
3085 sizeof (FILE_SYSTEM_DEVICE_INFO));
3086 }
3087 }
3088 cifs_buf_release(pSMB);
3089
3090 if (rc == -EAGAIN)
3091 goto QFSDeviceRetry;
3092
3093 return rc;
3094}
3095
3096int
3097CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
3098 const struct nls_table *nls_codepage)
3099{
3100/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3101 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3102 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3103 FILE_SYSTEM_UNIX_INFO *response_data;
3104 int rc = 0;
3105 int bytes_returned = 0;
3106 __u16 params, byte_count;
3107
3108 cFYI(1, ("In QFSUnixInfo"));
3109QFSUnixRetry:
3110 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3111 (void **) &pSMBr);
3112 if (rc)
3113 return rc;
3114
3115 params = 2; /* level */
3116 pSMB->TotalDataCount = 0;
3117 pSMB->DataCount = 0;
3118 pSMB->DataOffset = 0;
3119 pSMB->MaxParameterCount = cpu_to_le16(2);
3120 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3121 pSMB->MaxSetupCount = 0;
3122 pSMB->Reserved = 0;
3123 pSMB->Flags = 0;
3124 pSMB->Timeout = 0;
3125 pSMB->Reserved2 = 0;
3126 byte_count = params + 1 /* pad */ ;
3127 pSMB->ParameterCount = cpu_to_le16(params);
3128 pSMB->TotalParameterCount = pSMB->ParameterCount;
3129 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3130 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3131 pSMB->SetupCount = 1;
3132 pSMB->Reserved3 = 0;
3133 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3134 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3135 pSMB->hdr.smb_buf_length += byte_count;
3136 pSMB->ByteCount = cpu_to_le16(byte_count);
3137
3138 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3139 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3140 if (rc) {
3141 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3142 } else { /* decode response */
3143 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3144
3145 if (rc || (pSMBr->ByteCount < 13)) {
3146 rc = -EIO; /* bad smb */
3147 } else {
3148 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3149 response_data =
3150 (FILE_SYSTEM_UNIX_INFO
3151 *) (((char *) &pSMBr->hdr.Protocol) +
3152 data_offset);
3153 memcpy(&tcon->fsUnixInfo, response_data,
3154 sizeof (FILE_SYSTEM_UNIX_INFO));
3155 }
3156 }
3157 cifs_buf_release(pSMB);
3158
3159 if (rc == -EAGAIN)
3160 goto QFSUnixRetry;
3161
3162
3163 return rc;
3164}
3165
3166
3167int
3168CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3169 struct kstatfs *FSData, const struct nls_table *nls_codepage)
3170{
3171/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3172 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3173 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3174 FILE_SYSTEM_POSIX_INFO *response_data;
3175 int rc = 0;
3176 int bytes_returned = 0;
3177 __u16 params, byte_count;
3178
3179 cFYI(1, ("In QFSPosixInfo"));
3180QFSPosixRetry:
3181 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3182 (void **) &pSMBr);
3183 if (rc)
3184 return rc;
3185
3186 params = 2; /* level */
3187 pSMB->TotalDataCount = 0;
3188 pSMB->DataCount = 0;
3189 pSMB->DataOffset = 0;
3190 pSMB->MaxParameterCount = cpu_to_le16(2);
3191 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3192 pSMB->MaxSetupCount = 0;
3193 pSMB->Reserved = 0;
3194 pSMB->Flags = 0;
3195 pSMB->Timeout = 0;
3196 pSMB->Reserved2 = 0;
3197 byte_count = params + 1 /* pad */ ;
3198 pSMB->ParameterCount = cpu_to_le16(params);
3199 pSMB->TotalParameterCount = pSMB->ParameterCount;
3200 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3201 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3202 pSMB->SetupCount = 1;
3203 pSMB->Reserved3 = 0;
3204 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3205 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3206 pSMB->hdr.smb_buf_length += byte_count;
3207 pSMB->ByteCount = cpu_to_le16(byte_count);
3208
3209 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3210 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3211 if (rc) {
3212 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3213 } else { /* decode response */
3214 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3215
3216 if (rc || (pSMBr->ByteCount < 13)) {
3217 rc = -EIO; /* bad smb */
3218 } else {
3219 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3220 response_data =
3221 (FILE_SYSTEM_POSIX_INFO
3222 *) (((char *) &pSMBr->hdr.Protocol) +
3223 data_offset);
3224 FSData->f_bsize =
3225 le32_to_cpu(response_data->BlockSize);
3226 FSData->f_blocks =
3227 le64_to_cpu(response_data->TotalBlocks);
3228 FSData->f_bfree =
3229 le64_to_cpu(response_data->BlocksAvail);
3230 if(response_data->UserBlocksAvail == -1) {
3231 FSData->f_bavail = FSData->f_bfree;
3232 } else {
3233 FSData->f_bavail =
3234 le64_to_cpu(response_data->UserBlocksAvail);
3235 }
3236 if(response_data->TotalFileNodes != -1)
3237 FSData->f_files =
3238 le64_to_cpu(response_data->TotalFileNodes);
3239 if(response_data->FreeFileNodes != -1)
3240 FSData->f_ffree =
3241 le64_to_cpu(response_data->FreeFileNodes);
3242 }
3243 }
3244 cifs_buf_release(pSMB);
3245
3246 if (rc == -EAGAIN)
3247 goto QFSPosixRetry;
3248
3249 return rc;
3250}
3251
3252
3253/* We can not use write of zero bytes trick to
3254 set file size due to need for large file support. Also note that
3255 this SetPathInfo is preferred to SetFileInfo based method in next
3256 routine which is only needed to work around a sharing violation bug
3257 in Samba which this routine can run into */
3258
3259int
3260CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3261 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
3262{
3263 struct smb_com_transaction2_spi_req *pSMB = NULL;
3264 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3265 struct file_end_of_file_info *parm_data;
3266 int name_len;
3267 int rc = 0;
3268 int bytes_returned = 0;
3269 __u16 params, byte_count, data_count, param_offset, offset;
3270
3271 cFYI(1, ("In SetEOF"));
3272SetEOFRetry:
3273 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3274 (void **) &pSMBr);
3275 if (rc)
3276 return rc;
3277
3278 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3279 name_len =
3280 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3281 /* find define for this maxpathcomponent */
3282 , nls_codepage);
3283 name_len++; /* trailing null */
3284 name_len *= 2;
3285 } else { /* BB improve the check for buffer overruns BB */
3286 name_len = strnlen(fileName, PATH_MAX);
3287 name_len++; /* trailing null */
3288 strncpy(pSMB->FileName, fileName, name_len);
3289 }
3290 params = 6 + name_len;
3291 data_count = sizeof (struct file_end_of_file_info);
3292 pSMB->MaxParameterCount = cpu_to_le16(2);
3293 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3294 pSMB->MaxSetupCount = 0;
3295 pSMB->Reserved = 0;
3296 pSMB->Flags = 0;
3297 pSMB->Timeout = 0;
3298 pSMB->Reserved2 = 0;
3299 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3300 InformationLevel) - 4;
3301 offset = param_offset + params;
3302 if(SetAllocation) {
3303 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3304 pSMB->InformationLevel =
3305 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3306 else
3307 pSMB->InformationLevel =
3308 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3309 } else /* Set File Size */ {
3310 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3311 pSMB->InformationLevel =
3312 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3313 else
3314 pSMB->InformationLevel =
3315 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3316 }
3317
3318 parm_data =
3319 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3320 offset);
3321 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3322 pSMB->DataOffset = cpu_to_le16(offset);
3323 pSMB->SetupCount = 1;
3324 pSMB->Reserved3 = 0;
3325 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3326 byte_count = 3 /* pad */ + params + data_count;
3327 pSMB->DataCount = cpu_to_le16(data_count);
3328 pSMB->TotalDataCount = pSMB->DataCount;
3329 pSMB->ParameterCount = cpu_to_le16(params);
3330 pSMB->TotalParameterCount = pSMB->ParameterCount;
3331 pSMB->Reserved4 = 0;
3332 pSMB->hdr.smb_buf_length += byte_count;
3333 parm_data->FileSize = cpu_to_le64(size);
3334 pSMB->ByteCount = cpu_to_le16(byte_count);
3335 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3336 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3337 if (rc) {
3338 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3339 }
3340
3341 cifs_buf_release(pSMB);
3342
3343 if (rc == -EAGAIN)
3344 goto SetEOFRetry;
3345
3346 return rc;
3347}
3348
3349int
3350CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3351 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3352{
3353 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3354 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3355 char *data_offset;
3356 struct file_end_of_file_info *parm_data;
3357 int rc = 0;
3358 int bytes_returned = 0;
3359 __u16 params, param_offset, offset, byte_count, count;
3360
3361 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3362 (long long)size));
3363 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3364 (void **) &pSMBr);
3365 if (rc)
3366 return rc;
3367
3368 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3369 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3370
3371 params = 6;
3372 pSMB->MaxSetupCount = 0;
3373 pSMB->Reserved = 0;
3374 pSMB->Flags = 0;
3375 pSMB->Timeout = 0;
3376 pSMB->Reserved2 = 0;
3377 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3378 offset = param_offset + params;
3379
3380 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3381
3382 count = sizeof(struct file_end_of_file_info);
3383 pSMB->MaxParameterCount = cpu_to_le16(2);
3384 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3385 pSMB->SetupCount = 1;
3386 pSMB->Reserved3 = 0;
3387 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3388 byte_count = 3 /* pad */ + params + count;
3389 pSMB->DataCount = cpu_to_le16(count);
3390 pSMB->ParameterCount = cpu_to_le16(params);
3391 pSMB->TotalDataCount = pSMB->DataCount;
3392 pSMB->TotalParameterCount = pSMB->ParameterCount;
3393 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3394 parm_data =
3395 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3396 offset);
3397 pSMB->DataOffset = cpu_to_le16(offset);
3398 parm_data->FileSize = cpu_to_le64(size);
3399 pSMB->Fid = fid;
3400 if(SetAllocation) {
3401 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3402 pSMB->InformationLevel =
3403 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3404 else
3405 pSMB->InformationLevel =
3406 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3407 } else /* Set File Size */ {
3408 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3409 pSMB->InformationLevel =
3410 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3411 else
3412 pSMB->InformationLevel =
3413 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3414 }
3415 pSMB->Reserved4 = 0;
3416 pSMB->hdr.smb_buf_length += byte_count;
3417 pSMB->ByteCount = cpu_to_le16(byte_count);
3418 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3419 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3420 if (rc) {
3421 cFYI(1,
3422 ("Send error in SetFileInfo (SetFileSize) = %d",
3423 rc));
3424 }
3425
3426 if (pSMB)
3427 cifs_buf_release(pSMB);
3428
3429 /* Note: On -EAGAIN error only caller can retry on handle based calls
3430 since file handle passed in no longer valid */
3431
3432 return rc;
3433}
3434
3435/* Some legacy servers such as NT4 require that the file times be set on
3436 an open handle, rather than by pathname - this is awkward due to
3437 potential access conflicts on the open, but it is unavoidable for these
3438 old servers since the only other choice is to go from 100 nanosecond DCE
3439 time and resort to the original setpathinfo level which takes the ancient
3440 DOS time format with 2 second granularity */
3441int
3442CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3443 __u16 fid)
3444{
3445 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3446 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3447 char *data_offset;
3448 int rc = 0;
3449 int bytes_returned = 0;
3450 __u16 params, param_offset, offset, byte_count, count;
3451
3452 cFYI(1, ("Set Times (via SetFileInfo)"));
3453 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3454 (void **) &pSMBr);
3455 if (rc)
3456 return rc;
3457
3458 /* At this point there is no need to override the current pid
3459 with the pid of the opener, but that could change if we someday
3460 use an existing handle (rather than opening one on the fly) */
3461 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3462 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3463
3464 params = 6;
3465 pSMB->MaxSetupCount = 0;
3466 pSMB->Reserved = 0;
3467 pSMB->Flags = 0;
3468 pSMB->Timeout = 0;
3469 pSMB->Reserved2 = 0;
3470 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3471 offset = param_offset + params;
3472
3473 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3474
3475 count = sizeof (FILE_BASIC_INFO);
3476 pSMB->MaxParameterCount = cpu_to_le16(2);
3477 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3478 pSMB->SetupCount = 1;
3479 pSMB->Reserved3 = 0;
3480 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3481 byte_count = 3 /* pad */ + params + count;
3482 pSMB->DataCount = cpu_to_le16(count);
3483 pSMB->ParameterCount = cpu_to_le16(params);
3484 pSMB->TotalDataCount = pSMB->DataCount;
3485 pSMB->TotalParameterCount = pSMB->ParameterCount;
3486 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3487 pSMB->DataOffset = cpu_to_le16(offset);
3488 pSMB->Fid = fid;
3489 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3490 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3491 else
3492 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3493 pSMB->Reserved4 = 0;
3494 pSMB->hdr.smb_buf_length += byte_count;
3495 pSMB->ByteCount = cpu_to_le16(byte_count);
3496 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3497 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3498 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3499 if (rc) {
3500 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3501 }
3502
3503 cifs_buf_release(pSMB);
3504
3505 /* Note: On -EAGAIN error only caller can retry on handle based calls
3506 since file handle passed in no longer valid */
3507
3508 return rc;
3509}
3510
3511
3512int
3513CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3514 const FILE_BASIC_INFO * data,
3515 const struct nls_table *nls_codepage)
3516{
3517 TRANSACTION2_SPI_REQ *pSMB = NULL;
3518 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3519 int name_len;
3520 int rc = 0;
3521 int bytes_returned = 0;
3522 char *data_offset;
3523 __u16 params, param_offset, offset, byte_count, count;
3524
3525 cFYI(1, ("In SetTimes"));
3526
3527SetTimesRetry:
3528 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3529 (void **) &pSMBr);
3530 if (rc)
3531 return rc;
3532
3533 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3534 name_len =
3535 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3536 /* find define for this maxpathcomponent */
3537 , nls_codepage);
3538 name_len++; /* trailing null */
3539 name_len *= 2;
3540 } else { /* BB improve the check for buffer overruns BB */
3541 name_len = strnlen(fileName, PATH_MAX);
3542 name_len++; /* trailing null */
3543 strncpy(pSMB->FileName, fileName, name_len);
3544 }
3545
3546 params = 6 + name_len;
3547 count = sizeof (FILE_BASIC_INFO);
3548 pSMB->MaxParameterCount = cpu_to_le16(2);
3549 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3550 pSMB->MaxSetupCount = 0;
3551 pSMB->Reserved = 0;
3552 pSMB->Flags = 0;
3553 pSMB->Timeout = 0;
3554 pSMB->Reserved2 = 0;
3555 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3556 InformationLevel) - 4;
3557 offset = param_offset + params;
3558 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3559 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3560 pSMB->DataOffset = cpu_to_le16(offset);
3561 pSMB->SetupCount = 1;
3562 pSMB->Reserved3 = 0;
3563 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3564 byte_count = 3 /* pad */ + params + count;
3565
3566 pSMB->DataCount = cpu_to_le16(count);
3567 pSMB->ParameterCount = cpu_to_le16(params);
3568 pSMB->TotalDataCount = pSMB->DataCount;
3569 pSMB->TotalParameterCount = pSMB->ParameterCount;
3570 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3571 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3572 else
3573 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3574 pSMB->Reserved4 = 0;
3575 pSMB->hdr.smb_buf_length += byte_count;
3576 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3577 pSMB->ByteCount = cpu_to_le16(byte_count);
3578 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3579 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3580 if (rc) {
3581 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3582 }
3583
3584 cifs_buf_release(pSMB);
3585
3586 if (rc == -EAGAIN)
3587 goto SetTimesRetry;
3588
3589 return rc;
3590}
3591
3592/* Can not be used to set time stamps yet (due to old DOS time format) */
3593/* Can be used to set attributes */
3594#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3595 handling it anyway and NT4 was what we thought it would be needed for
3596 Do not delete it until we prove whether needed for Win9x though */
3597int
3598CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3599 __u16 dos_attrs, const struct nls_table *nls_codepage)
3600{
3601 SETATTR_REQ *pSMB = NULL;
3602 SETATTR_RSP *pSMBr = NULL;
3603 int rc = 0;
3604 int bytes_returned;
3605 int name_len;
3606
3607 cFYI(1, ("In SetAttrLegacy"));
3608
3609SetAttrLgcyRetry:
3610 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
3611 (void **) &pSMBr);
3612 if (rc)
3613 return rc;
3614
3615 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3616 name_len =
3617 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName,
3618 PATH_MAX, nls_codepage);
3619 name_len++; /* trailing null */
3620 name_len *= 2;
3621 } else { /* BB improve the check for buffer overruns BB */
3622 name_len = strnlen(fileName, PATH_MAX);
3623 name_len++; /* trailing null */
3624 strncpy(pSMB->fileName, fileName, name_len);
3625 }
3626 pSMB->attr = cpu_to_le16(dos_attrs);
3627 pSMB->BufferFormat = 0x04;
3628 pSMB->hdr.smb_buf_length += name_len + 1;
3629 pSMB->ByteCount = cpu_to_le16(name_len + 1);
3630 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3631 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3632 if (rc) {
3633 cFYI(1, ("Error in LegacySetAttr = %d", rc));
3634 }
3635
3636 cifs_buf_release(pSMB);
3637
3638 if (rc == -EAGAIN)
3639 goto SetAttrLgcyRetry;
3640
3641 return rc;
3642}
3643#endif /* temporarily unneeded SetAttr legacy function */
3644
3645int
3646CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3647 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3648 dev_t device, const struct nls_table *nls_codepage)
3649{
3650 TRANSACTION2_SPI_REQ *pSMB = NULL;
3651 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3652 int name_len;
3653 int rc = 0;
3654 int bytes_returned = 0;
3655 FILE_UNIX_BASIC_INFO *data_offset;
3656 __u16 params, param_offset, offset, count, byte_count;
3657
3658 cFYI(1, ("In SetUID/GID/Mode"));
3659setPermsRetry:
3660 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3661 (void **) &pSMBr);
3662 if (rc)
3663 return rc;
3664
3665 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3666 name_len =
3667 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3668 /* find define for this maxpathcomponent */
3669 , nls_codepage);
3670 name_len++; /* trailing null */
3671 name_len *= 2;
3672 } else { /* BB improve the check for buffer overruns BB */
3673 name_len = strnlen(fileName, PATH_MAX);
3674 name_len++; /* trailing null */
3675 strncpy(pSMB->FileName, fileName, name_len);
3676 }
3677
3678 params = 6 + name_len;
3679 count = sizeof (FILE_UNIX_BASIC_INFO);
3680 pSMB->MaxParameterCount = cpu_to_le16(2);
3681 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3682 pSMB->MaxSetupCount = 0;
3683 pSMB->Reserved = 0;
3684 pSMB->Flags = 0;
3685 pSMB->Timeout = 0;
3686 pSMB->Reserved2 = 0;
3687 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3688 InformationLevel) - 4;
3689 offset = param_offset + params;
3690 data_offset =
3691 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3692 offset);
3693 memset(data_offset, 0, count);
3694 pSMB->DataOffset = cpu_to_le16(offset);
3695 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3696 pSMB->SetupCount = 1;
3697 pSMB->Reserved3 = 0;
3698 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3699 byte_count = 3 /* pad */ + params + count;
3700 pSMB->ParameterCount = cpu_to_le16(params);
3701 pSMB->DataCount = cpu_to_le16(count);
3702 pSMB->TotalParameterCount = pSMB->ParameterCount;
3703 pSMB->TotalDataCount = pSMB->DataCount;
3704 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3705 pSMB->Reserved4 = 0;
3706 pSMB->hdr.smb_buf_length += byte_count;
3707 data_offset->Uid = cpu_to_le64(uid);
3708 data_offset->Gid = cpu_to_le64(gid);
3709 /* better to leave device as zero when it is */
3710 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3711 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3712 data_offset->Permissions = cpu_to_le64(mode);
3713
3714 if(S_ISREG(mode))
3715 data_offset->Type = cpu_to_le32(UNIX_FILE);
3716 else if(S_ISDIR(mode))
3717 data_offset->Type = cpu_to_le32(UNIX_DIR);
3718 else if(S_ISLNK(mode))
3719 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3720 else if(S_ISCHR(mode))
3721 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3722 else if(S_ISBLK(mode))
3723 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3724 else if(S_ISFIFO(mode))
3725 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3726 else if(S_ISSOCK(mode))
3727 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3728
3729
3730 pSMB->ByteCount = cpu_to_le16(byte_count);
3731 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3732 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3733 if (rc) {
3734 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3735 }
3736
3737 if (pSMB)
3738 cifs_buf_release(pSMB);
3739 if (rc == -EAGAIN)
3740 goto setPermsRetry;
3741 return rc;
3742}
3743
3744int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3745 const int notify_subdirs, const __u16 netfid,
3746 __u32 filter, const struct nls_table *nls_codepage)
3747{
3748 int rc = 0;
3749 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3750 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3751 int bytes_returned;
3752
3753 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3754 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3755 (void **) &pSMBr);
3756 if (rc)
3757 return rc;
3758
3759 pSMB->TotalParameterCount = 0 ;
3760 pSMB->TotalDataCount = 0;
3761 pSMB->MaxParameterCount = cpu_to_le32(2);
3762 /* BB find exact data count max from sess structure BB */
3763 pSMB->MaxDataCount = 0; /* same in little endian or be */
3764 pSMB->MaxSetupCount = 4;
3765 pSMB->Reserved = 0;
3766 pSMB->ParameterOffset = 0;
3767 pSMB->DataCount = 0;
3768 pSMB->DataOffset = 0;
3769 pSMB->SetupCount = 4; /* single byte does not need le conversion */
3770 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
3771 pSMB->ParameterCount = pSMB->TotalParameterCount;
3772 if(notify_subdirs)
3773 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
3774 pSMB->Reserved2 = 0;
3775 pSMB->CompletionFilter = cpu_to_le32(filter);
3776 pSMB->Fid = netfid; /* file handle always le */
3777 pSMB->ByteCount = 0;
3778
3779 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3780 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3781 if (rc) {
3782 cFYI(1, ("Error in Notify = %d", rc));
3783 }
3784 cifs_buf_release(pSMB);
3785 return rc;
3786}
3787#ifdef CONFIG_CIFS_XATTR
3788ssize_t
3789CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3790 const unsigned char *searchName,
3791 char * EAData, size_t buf_size,
3792 const struct nls_table *nls_codepage)
3793{
3794 /* BB assumes one setup word */
3795 TRANSACTION2_QPI_REQ *pSMB = NULL;
3796 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3797 int rc = 0;
3798 int bytes_returned;
3799 int name_len;
3800 struct fea * temp_fea;
3801 char * temp_ptr;
3802 __u16 params, byte_count;
3803
3804 cFYI(1, ("In Query All EAs path %s", searchName));
3805QAllEAsRetry:
3806 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3807 (void **) &pSMBr);
3808 if (rc)
3809 return rc;
3810
3811 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3812 name_len =
3813 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
3814 /* find define for this maxpathcomponent */
3815 , nls_codepage);
3816 name_len++; /* trailing null */
3817 name_len *= 2;
3818 } else { /* BB improve the check for buffer overruns BB */
3819 name_len = strnlen(searchName, PATH_MAX);
3820 name_len++; /* trailing null */
3821 strncpy(pSMB->FileName, searchName, name_len);
3822 }
3823
3824 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3825 pSMB->TotalDataCount = 0;
3826 pSMB->MaxParameterCount = cpu_to_le16(2);
3827 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3828 pSMB->MaxSetupCount = 0;
3829 pSMB->Reserved = 0;
3830 pSMB->Flags = 0;
3831 pSMB->Timeout = 0;
3832 pSMB->Reserved2 = 0;
3833 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3834 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3835 pSMB->DataCount = 0;
3836 pSMB->DataOffset = 0;
3837 pSMB->SetupCount = 1;
3838 pSMB->Reserved3 = 0;
3839 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3840 byte_count = params + 1 /* pad */ ;
3841 pSMB->TotalParameterCount = cpu_to_le16(params);
3842 pSMB->ParameterCount = pSMB->TotalParameterCount;
3843 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3844 pSMB->Reserved4 = 0;
3845 pSMB->hdr.smb_buf_length += byte_count;
3846 pSMB->ByteCount = cpu_to_le16(byte_count);
3847
3848 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3849 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3850 if (rc) {
3851 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
3852 } else { /* decode response */
3853 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3854
3855 /* BB also check enough total bytes returned */
3856 /* BB we need to improve the validity checking
3857 of these trans2 responses */
3858 if (rc || (pSMBr->ByteCount < 4))
3859 rc = -EIO; /* bad smb */
3860 /* else if (pFindData){
3861 memcpy((char *) pFindData,
3862 (char *) &pSMBr->hdr.Protocol +
3863 data_offset, kl);
3864 }*/ else {
3865 /* check that length of list is not more than bcc */
3866 /* check that each entry does not go beyond length
3867 of list */
3868 /* check that each element of each entry does not
3869 go beyond end of list */
3870 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3871 struct fealist * ea_response_data;
3872 rc = 0;
3873 /* validate_trans2_offsets() */
3874 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3875 ea_response_data = (struct fealist *)
3876 (((char *) &pSMBr->hdr.Protocol) +
3877 data_offset);
3878 name_len = le32_to_cpu(ea_response_data->list_len);
3879 cFYI(1,("ea length %d", name_len));
3880 if(name_len <= 8) {
3881 /* returned EA size zeroed at top of function */
3882 cFYI(1,("empty EA list returned from server"));
3883 } else {
3884 /* account for ea list len */
3885 name_len -= 4;
3886 temp_fea = ea_response_data->list;
3887 temp_ptr = (char *)temp_fea;
3888 while(name_len > 0) {
3889 __u16 value_len;
3890 name_len -= 4;
3891 temp_ptr += 4;
3892 rc += temp_fea->name_len;
3893 /* account for prefix user. and trailing null */
3894 rc = rc + 5 + 1;
3895 if(rc<(int)buf_size) {
3896 memcpy(EAData,"user.",5);
3897 EAData+=5;
3898 memcpy(EAData,temp_ptr,temp_fea->name_len);
3899 EAData+=temp_fea->name_len;
3900 /* null terminate name */
3901 *EAData = 0;
3902 EAData = EAData + 1;
3903 } else if(buf_size == 0) {
3904 /* skip copy - calc size only */
3905 } else {
3906 /* stop before overrun buffer */
3907 rc = -ERANGE;
3908 break;
3909 }
3910 name_len -= temp_fea->name_len;
3911 temp_ptr += temp_fea->name_len;
3912 /* account for trailing null */
3913 name_len--;
3914 temp_ptr++;
3915 value_len = le16_to_cpu(temp_fea->value_len);
3916 name_len -= value_len;
3917 temp_ptr += value_len;
3918 /* BB check that temp_ptr is still within smb BB*/
3919 /* no trailing null to account for in value len */
3920 /* go on to next EA */
3921 temp_fea = (struct fea *)temp_ptr;
3922 }
3923 }
3924 }
3925 }
3926 if (pSMB)
3927 cifs_buf_release(pSMB);
3928 if (rc == -EAGAIN)
3929 goto QAllEAsRetry;
3930
3931 return (ssize_t)rc;
3932}
3933
3934ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
3935 const unsigned char * searchName,const unsigned char * ea_name,
3936 unsigned char * ea_value, size_t buf_size,
3937 const struct nls_table *nls_codepage)
3938{
3939 TRANSACTION2_QPI_REQ *pSMB = NULL;
3940 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3941 int rc = 0;
3942 int bytes_returned;
3943 int name_len;
3944 struct fea * temp_fea;
3945 char * temp_ptr;
3946 __u16 params, byte_count;
3947
3948 cFYI(1, ("In Query EA path %s", searchName));
3949QEARetry:
3950 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3951 (void **) &pSMBr);
3952 if (rc)
3953 return rc;
3954
3955 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3956 name_len =
3957 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
3958 /* find define for this maxpathcomponent */
3959 , nls_codepage);
3960 name_len++; /* trailing null */
3961 name_len *= 2;
3962 } else { /* BB improve the check for buffer overruns BB */
3963 name_len = strnlen(searchName, PATH_MAX);
3964 name_len++; /* trailing null */
3965 strncpy(pSMB->FileName, searchName, name_len);
3966 }
3967
3968 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3969 pSMB->TotalDataCount = 0;
3970 pSMB->MaxParameterCount = cpu_to_le16(2);
3971 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3972 pSMB->MaxSetupCount = 0;
3973 pSMB->Reserved = 0;
3974 pSMB->Flags = 0;
3975 pSMB->Timeout = 0;
3976 pSMB->Reserved2 = 0;
3977 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3978 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3979 pSMB->DataCount = 0;
3980 pSMB->DataOffset = 0;
3981 pSMB->SetupCount = 1;
3982 pSMB->Reserved3 = 0;
3983 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3984 byte_count = params + 1 /* pad */ ;
3985 pSMB->TotalParameterCount = cpu_to_le16(params);
3986 pSMB->ParameterCount = pSMB->TotalParameterCount;
3987 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3988 pSMB->Reserved4 = 0;
3989 pSMB->hdr.smb_buf_length += byte_count;
3990 pSMB->ByteCount = cpu_to_le16(byte_count);
3991
3992 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3993 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3994 if (rc) {
3995 cFYI(1, ("Send error in Query EA = %d", rc));
3996 } else { /* decode response */
3997 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3998
3999 /* BB also check enough total bytes returned */
4000 /* BB we need to improve the validity checking
4001 of these trans2 responses */
4002 if (rc || (pSMBr->ByteCount < 4))
4003 rc = -EIO; /* bad smb */
4004 /* else if (pFindData){
4005 memcpy((char *) pFindData,
4006 (char *) &pSMBr->hdr.Protocol +
4007 data_offset, kl);
4008 }*/ else {
4009 /* check that length of list is not more than bcc */
4010 /* check that each entry does not go beyond length
4011 of list */
4012 /* check that each element of each entry does not
4013 go beyond end of list */
4014 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4015 struct fealist * ea_response_data;
4016 rc = -ENODATA;
4017 /* validate_trans2_offsets() */
4018 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4019 ea_response_data = (struct fealist *)
4020 (((char *) &pSMBr->hdr.Protocol) +
4021 data_offset);
4022 name_len = le32_to_cpu(ea_response_data->list_len);
4023 cFYI(1,("ea length %d", name_len));
4024 if(name_len <= 8) {
4025 /* returned EA size zeroed at top of function */
4026 cFYI(1,("empty EA list returned from server"));
4027 } else {
4028 /* account for ea list len */
4029 name_len -= 4;
4030 temp_fea = ea_response_data->list;
4031 temp_ptr = (char *)temp_fea;
4032 /* loop through checking if we have a matching
4033 name and then return the associated value */
4034 while(name_len > 0) {
4035 __u16 value_len;
4036 name_len -= 4;
4037 temp_ptr += 4;
4038 value_len = le16_to_cpu(temp_fea->value_len);
4039 /* BB validate that value_len falls within SMB,
4040 even though maximum for name_len is 255 */
4041 if(memcmp(temp_fea->name,ea_name,
4042 temp_fea->name_len) == 0) {
4043 /* found a match */
4044 rc = value_len;
4045 /* account for prefix user. and trailing null */
4046 if(rc<=(int)buf_size) {
4047 memcpy(ea_value,
4048 temp_fea->name+temp_fea->name_len+1,
4049 rc);
4050 /* ea values, unlike ea names,
4051 are not null terminated */
4052 } else if(buf_size == 0) {
4053 /* skip copy - calc size only */
4054 } else {
4055 /* stop before overrun buffer */
4056 rc = -ERANGE;
4057 }
4058 break;
4059 }
4060 name_len -= temp_fea->name_len;
4061 temp_ptr += temp_fea->name_len;
4062 /* account for trailing null */
4063 name_len--;
4064 temp_ptr++;
4065 name_len -= value_len;
4066 temp_ptr += value_len;
4067 /* no trailing null to account for in value len */
4068 /* go on to next EA */
4069 temp_fea = (struct fea *)temp_ptr;
4070 }
4071 }
4072 }
4073 }
4074 if (pSMB)
4075 cifs_buf_release(pSMB);
4076 if (rc == -EAGAIN)
4077 goto QEARetry;
4078
4079 return (ssize_t)rc;
4080}
4081
4082int
4083CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4084 const char * ea_name, const void * ea_value,
4085 const __u16 ea_value_len, const struct nls_table *nls_codepage)
4086{
4087 struct smb_com_transaction2_spi_req *pSMB = NULL;
4088 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4089 struct fealist *parm_data;
4090 int name_len;
4091 int rc = 0;
4092 int bytes_returned = 0;
4093 __u16 params, param_offset, byte_count, offset, count;
4094
4095 cFYI(1, ("In SetEA"));
4096SetEARetry:
4097 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4098 (void **) &pSMBr);
4099 if (rc)
4100 return rc;
4101
4102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4103 name_len =
4104 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
4105 /* find define for this maxpathcomponent */
4106 , nls_codepage);
4107 name_len++; /* trailing null */
4108 name_len *= 2;
4109 } else { /* BB improve the check for buffer overruns BB */
4110 name_len = strnlen(fileName, PATH_MAX);
4111 name_len++; /* trailing null */
4112 strncpy(pSMB->FileName, fileName, name_len);
4113 }
4114
4115 params = 6 + name_len;
4116
4117 /* done calculating parms using name_len of file name,
4118 now use name_len to calculate length of ea name
4119 we are going to create in the inode xattrs */
4120 if(ea_name == NULL)
4121 name_len = 0;
4122 else
4123 name_len = strnlen(ea_name,255);
4124
4125 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4126 pSMB->MaxParameterCount = cpu_to_le16(2);
4127 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4128 pSMB->MaxSetupCount = 0;
4129 pSMB->Reserved = 0;
4130 pSMB->Flags = 0;
4131 pSMB->Timeout = 0;
4132 pSMB->Reserved2 = 0;
4133 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4134 InformationLevel) - 4;
4135 offset = param_offset + params;
4136 pSMB->InformationLevel =
4137 cpu_to_le16(SMB_SET_FILE_EA);
4138
4139 parm_data =
4140 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4141 offset);
4142 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4143 pSMB->DataOffset = cpu_to_le16(offset);
4144 pSMB->SetupCount = 1;
4145 pSMB->Reserved3 = 0;
4146 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4147 byte_count = 3 /* pad */ + params + count;
4148 pSMB->DataCount = cpu_to_le16(count);
4149 parm_data->list_len = cpu_to_le32(count);
4150 parm_data->list[0].EA_flags = 0;
4151 /* we checked above that name len is less than 255 */
4152 parm_data->list[0].name_len = (__u8)name_len;;
4153 /* EA names are always ASCII */
4154 if(ea_name)
4155 strncpy(parm_data->list[0].name,ea_name,name_len);
4156 parm_data->list[0].name[name_len] = 0;
4157 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4158 /* caller ensures that ea_value_len is less than 64K but
4159 we need to ensure that it fits within the smb */
4160
4161 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4162 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4163 if(ea_value_len)
4164 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4165
4166 pSMB->TotalDataCount = pSMB->DataCount;
4167 pSMB->ParameterCount = cpu_to_le16(params);
4168 pSMB->TotalParameterCount = pSMB->ParameterCount;
4169 pSMB->Reserved4 = 0;
4170 pSMB->hdr.smb_buf_length += byte_count;
4171 pSMB->ByteCount = cpu_to_le16(byte_count);
4172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4173 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4174 if (rc) {
4175 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4176 }
4177
4178 cifs_buf_release(pSMB);
4179
4180 if (rc == -EAGAIN)
4181 goto SetEARetry;
4182
4183 return rc;
4184}
4185
4186#endif
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
new file mode 100644
index 000000000000..40470b9d5477
--- /dev/null
+++ b/fs/cifs/connect.c
@@ -0,0 +1,3064 @@
1/*
2 * fs/cifs/connect.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
24#include <linux/list.h>
25#include <linux/wait.h>
26#include <linux/ipv6.h>
27#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
31#include <asm/uaccess.h>
32#include <asm/processor.h>
33#include "cifspdu.h"
34#include "cifsglob.h"
35#include "cifsproto.h"
36#include "cifs_unicode.h"
37#include "cifs_debug.h"
38#include "cifs_fs_sb.h"
39#include "ntlmssp.h"
40#include "nterr.h"
41#include "rfc1002pdu.h"
42
43#define CIFS_PORT 445
44#define RFC1001_PORT 139
45
46extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
47 unsigned char *p24);
48extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
49 unsigned char *p24);
50
51extern mempool_t *cifs_req_poolp;
52
53struct smb_vol {
54 char *username;
55 char *password;
56 char *domainname;
57 char *UNC;
58 char *UNCip;
59 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
60 char *iocharset; /* local code page for mapping to and from Unicode */
61 char source_rfc1001_name[16]; /* netbios name of client */
62 uid_t linux_uid;
63 gid_t linux_gid;
64 mode_t file_mode;
65 mode_t dir_mode;
66 unsigned rw:1;
67 unsigned retry:1;
68 unsigned intr:1;
69 unsigned setuids:1;
70 unsigned noperm:1;
71 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
72 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
73 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
74 unsigned direct_io:1;
75 unsigned int rsize;
76 unsigned int wsize;
77 unsigned int sockopt;
78 unsigned short int port;
79};
80
81static int ipv4_connect(struct sockaddr_in *psin_server,
82 struct socket **csocket,
83 char * netb_name);
84static int ipv6_connect(struct sockaddr_in6 *psin_server,
85 struct socket **csocket);
86
87
88 /*
89 * cifs tcp session reconnection
90 *
91 * mark tcp session as reconnecting so temporarily locked
92 * mark all smb sessions as reconnecting for tcp session
93 * reconnect tcp session
94 * wake up waiters on reconnection? - (not needed currently)
95 */
96
97int
98cifs_reconnect(struct TCP_Server_Info *server)
99{
100 int rc = 0;
101 struct list_head *tmp;
102 struct cifsSesInfo *ses;
103 struct cifsTconInfo *tcon;
104 struct mid_q_entry * mid_entry;
105
106 spin_lock(&GlobalMid_Lock);
107 if(server->tcpStatus == CifsExiting) {
108 /* the demux thread will exit normally
109 next time through the loop */
110 spin_unlock(&GlobalMid_Lock);
111 return rc;
112 } else
113 server->tcpStatus = CifsNeedReconnect;
114 spin_unlock(&GlobalMid_Lock);
115 server->maxBuf = 0;
116
117 cFYI(1, ("Reconnecting tcp session "));
118
119 /* before reconnecting the tcp session, mark the smb session (uid)
120 and the tid bad so they are not used until reconnected */
121 read_lock(&GlobalSMBSeslock);
122 list_for_each(tmp, &GlobalSMBSessionList) {
123 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
124 if (ses->server) {
125 if (ses->server == server) {
126 ses->status = CifsNeedReconnect;
127 ses->ipc_tid = 0;
128 }
129 }
130 /* else tcp and smb sessions need reconnection */
131 }
132 list_for_each(tmp, &GlobalTreeConnectionList) {
133 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
134 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
135 tcon->tidStatus = CifsNeedReconnect;
136 }
137 }
138 read_unlock(&GlobalSMBSeslock);
139 /* do not want to be sending data on a socket we are freeing */
140 down(&server->tcpSem);
141 if(server->ssocket) {
142 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
143 server->ssocket->flags));
144 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
145 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
146 server->ssocket->flags));
147 sock_release(server->ssocket);
148 server->ssocket = NULL;
149 }
150
151 spin_lock(&GlobalMid_Lock);
152 list_for_each(tmp, &server->pending_mid_q) {
153 mid_entry = list_entry(tmp, struct
154 mid_q_entry,
155 qhead);
156 if(mid_entry) {
157 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
158 /* Mark other intransit requests as needing retry so
159 we do not immediately mark the session bad again
160 (ie after we reconnect below) as they timeout too */
161 mid_entry->midState = MID_RETRY_NEEDED;
162 }
163 }
164 }
165 spin_unlock(&GlobalMid_Lock);
166 up(&server->tcpSem);
167
168 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
169 {
170 if(server->protocolType == IPV6) {
171 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
172 } else {
173 rc = ipv4_connect(&server->addr.sockAddr,
174 &server->ssocket,
175 server->workstation_RFC1001_name);
176 }
177 if(rc) {
178 set_current_state(TASK_INTERRUPTIBLE);
179 schedule_timeout(3 * HZ);
180 } else {
181 atomic_inc(&tcpSesReconnectCount);
182 spin_lock(&GlobalMid_Lock);
183 if(server->tcpStatus != CifsExiting)
184 server->tcpStatus = CifsGood;
185 spin_unlock(&GlobalMid_Lock);
186 /* atomic_set(&server->inFlight,0);*/
187 wake_up(&server->response_q);
188 }
189 }
190 return rc;
191}
192
193static int
194cifs_demultiplex_thread(struct TCP_Server_Info *server)
195{
196 int length;
197 unsigned int pdu_length, total_read;
198 struct smb_hdr *smb_buffer = NULL;
199 struct msghdr smb_msg;
200 struct kvec iov;
201 struct socket *csocket = server->ssocket;
202 struct list_head *tmp;
203 struct cifsSesInfo *ses;
204 struct task_struct *task_to_wake = NULL;
205 struct mid_q_entry *mid_entry;
206 char *temp;
207
208 daemonize("cifsd");
209 allow_signal(SIGKILL);
210 current->flags |= PF_MEMALLOC;
211 server->tsk = current; /* save process info to wake at shutdown */
212 cFYI(1, ("Demultiplex PID: %d", current->pid));
213 write_lock(&GlobalSMBSeslock);
214 atomic_inc(&tcpSesAllocCount);
215 length = tcpSesAllocCount.counter;
216 write_unlock(&GlobalSMBSeslock);
217 if(length > 1) {
218 mempool_resize(cifs_req_poolp,
219 length + cifs_min_rcv,
220 GFP_KERNEL);
221 }
222
223 while (server->tcpStatus != CifsExiting) {
224 if (smb_buffer == NULL)
225 smb_buffer = cifs_buf_get();
226 else
227 memset(smb_buffer, 0, sizeof (struct smb_hdr));
228
229 if (smb_buffer == NULL) {
230 cERROR(1,("Can not get memory for SMB response"));
231 set_current_state(TASK_INTERRUPTIBLE);
232 schedule_timeout(HZ * 3); /* give system time to free memory */
233 continue;
234 }
235 iov.iov_base = smb_buffer;
236 iov.iov_len = 4;
237 smb_msg.msg_control = NULL;
238 smb_msg.msg_controllen = 0;
239 length =
240 kernel_recvmsg(csocket, &smb_msg,
241 &iov, 1, 4, 0 /* BB see socket.h flags */);
242
243 if(server->tcpStatus == CifsExiting) {
244 break;
245 } else if (server->tcpStatus == CifsNeedReconnect) {
246 cFYI(1,("Reconnecting after server stopped responding"));
247 cifs_reconnect(server);
248 cFYI(1,("call to reconnect done"));
249 csocket = server->ssocket;
250 continue;
251 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
252 set_current_state(TASK_INTERRUPTIBLE);
253 schedule_timeout(1); /* minimum sleep to prevent looping
254 allowing socket to clear and app threads to set
255 tcpStatus CifsNeedReconnect if server hung */
256 continue;
257 } else if (length <= 0) {
258 if(server->tcpStatus == CifsNew) {
259 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
260 /* some servers kill tcp session rather than returning
261 smb negprot error in which case reconnecting here is
262 not going to help - return error to mount */
263 break;
264 }
265 if(length == -EINTR) {
266 cFYI(1,("cifsd thread killed"));
267 break;
268 }
269 cFYI(1,("Reconnecting after unexpected peek error %d",length));
270 cifs_reconnect(server);
271 csocket = server->ssocket;
272 wake_up(&server->response_q);
273 continue;
274 } else if (length > 3) {
275 pdu_length = ntohl(smb_buffer->smb_buf_length);
276 /* Only read pdu_length after below checks for too short (due
277 to e.g. int overflow) and too long ie beyond end of buf */
278 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
279
280 temp = (char *) smb_buffer;
281 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
282 cFYI(0,("Received 4 byte keep alive packet"));
283 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
284 cFYI(1,("Good RFC 1002 session rsp"));
285 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
286 /* we get this from Windows 98 instead of error on SMB negprot response */
287 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
288 if(server->tcpStatus == CifsNew) {
289 /* if nack on negprot (rather than
290 ret of smb negprot error) reconnecting
291 not going to help, ret error to mount */
292 break;
293 } else {
294 /* give server a second to
295 clean up before reconnect attempt */
296 set_current_state(TASK_INTERRUPTIBLE);
297 schedule_timeout(HZ);
298 /* always try 445 first on reconnect
299 since we get NACK on some if we ever
300 connected to port 139 (the NACK is
301 since we do not begin with RFC1001
302 session initialize frame) */
303 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
304 cifs_reconnect(server);
305 csocket = server->ssocket;
306 wake_up(&server->response_q);
307 continue;
308 }
309 } else if (temp[0] != (char) 0) {
310 cERROR(1,("Unknown RFC 1002 frame"));
311 cifs_dump_mem(" Received Data: ", temp, length);
312 cifs_reconnect(server);
313 csocket = server->ssocket;
314 continue;
315 } else {
316 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
317 || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
318 cERROR(1,
319 ("Invalid size SMB length %d and pdu_length %d",
320 length, pdu_length+4));
321 cifs_reconnect(server);
322 csocket = server->ssocket;
323 wake_up(&server->response_q);
324 continue;
325 } else { /* length ok */
326 length = 0;
327 iov.iov_base = 4 + (char *)smb_buffer;
328 iov.iov_len = pdu_length;
329 for (total_read = 0;
330 total_read < pdu_length;
331 total_read += length) {
332 length = kernel_recvmsg(csocket, &smb_msg,
333 &iov, 1,
334 pdu_length - total_read, 0);
335 if (length == 0) {
336 cERROR(1,
337 ("Zero length receive when expecting %d ",
338 pdu_length - total_read));
339 cifs_reconnect(server);
340 csocket = server->ssocket;
341 wake_up(&server->response_q);
342 continue;
343 }
344 }
345 length += 4; /* account for rfc1002 hdr */
346 }
347
348 dump_smb(smb_buffer, length);
349 if (checkSMB
350 (smb_buffer, smb_buffer->Mid, total_read+4)) {
351 cERROR(1, ("Bad SMB Received "));
352 continue;
353 }
354
355 task_to_wake = NULL;
356 spin_lock(&GlobalMid_Lock);
357 list_for_each(tmp, &server->pending_mid_q) {
358 mid_entry = list_entry(tmp, struct
359 mid_q_entry,
360 qhead);
361
362 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
363 cFYI(1,
364 (" Mid 0x%x matched - waking up ",mid_entry->mid));
365 task_to_wake = mid_entry->tsk;
366 mid_entry->resp_buf =
367 smb_buffer;
368 mid_entry->midState =
369 MID_RESPONSE_RECEIVED;
370 }
371 }
372 spin_unlock(&GlobalMid_Lock);
373 if (task_to_wake) {
374 smb_buffer = NULL; /* will be freed by users thread after he is done */
375 wake_up_process(task_to_wake);
376 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
377 cERROR(1, ("No task to wake, unknown frame rcvd!"));
378 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
379 }
380 }
381 } else {
382 cFYI(1,
383 ("Frame less than four bytes received %d bytes long.",
384 length));
385 cifs_reconnect(server);
386 csocket = server->ssocket;
387 wake_up(&server->response_q);
388 continue;
389 }
390 }
391 spin_lock(&GlobalMid_Lock);
392 server->tcpStatus = CifsExiting;
393 server->tsk = NULL;
394 atomic_set(&server->inFlight, 0);
395 spin_unlock(&GlobalMid_Lock);
396 /* Although there should not be any requests blocked on
397 this queue it can not hurt to be paranoid and try to wake up requests
398 that may haven been blocked when more than 50 at time were on the wire
399 to the same server - they now will see the session is in exit state
400 and get out of SendReceive. */
401 wake_up_all(&server->request_q);
402 /* give those requests time to exit */
403 set_current_state(TASK_INTERRUPTIBLE);
404 schedule_timeout(HZ/8);
405
406 if(server->ssocket) {
407 sock_release(csocket);
408 server->ssocket = NULL;
409 }
410 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
411 cifs_buf_release(smb_buffer);
412
413 read_lock(&GlobalSMBSeslock);
414 if (list_empty(&server->pending_mid_q)) {
415 /* loop through server session structures attached to this and mark them dead */
416 list_for_each(tmp, &GlobalSMBSessionList) {
417 ses =
418 list_entry(tmp, struct cifsSesInfo,
419 cifsSessionList);
420 if (ses->server == server) {
421 ses->status = CifsExiting;
422 ses->server = NULL;
423 }
424 }
425 read_unlock(&GlobalSMBSeslock);
426 } else {
427 spin_lock(&GlobalMid_Lock);
428 list_for_each(tmp, &server->pending_mid_q) {
429 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
430 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
431 cFYI(1,
432 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
433 task_to_wake = mid_entry->tsk;
434 if(task_to_wake) {
435 wake_up_process(task_to_wake);
436 }
437 }
438 }
439 spin_unlock(&GlobalMid_Lock);
440 read_unlock(&GlobalSMBSeslock);
441 set_current_state(TASK_INTERRUPTIBLE);
442 /* 1/8th of sec is more than enough time for them to exit */
443 schedule_timeout(HZ/8);
444 }
445
446 if (list_empty(&server->pending_mid_q)) {
447 /* mpx threads have not exited yet give them
448 at least the smb send timeout time for long ops */
449 cFYI(1, ("Wait for exit from demultiplex thread"));
450 set_current_state(TASK_INTERRUPTIBLE);
451 schedule_timeout(46 * HZ);
452 /* if threads still have not exited they are probably never
453 coming home not much else we can do but free the memory */
454 }
455 kfree(server);
456
457 write_lock(&GlobalSMBSeslock);
458 atomic_dec(&tcpSesAllocCount);
459 length = tcpSesAllocCount.counter;
460 write_unlock(&GlobalSMBSeslock);
461 if(length > 0) {
462 mempool_resize(cifs_req_poolp,
463 length + cifs_min_rcv,
464 GFP_KERNEL);
465 }
466
467 set_current_state(TASK_INTERRUPTIBLE);
468 schedule_timeout(HZ/4);
469 return 0;
470}
471
472static void *
473cifs_kcalloc(size_t size, unsigned int __nocast type)
474{
475 void *addr;
476 addr = kmalloc(size, type);
477 if (addr)
478 memset(addr, 0, size);
479 return addr;
480}
481
482static int
483cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
484{
485 char *value;
486 char *data;
487 unsigned int temp_len, i, j;
488 char separator[2];
489
490 separator[0] = ',';
491 separator[1] = 0;
492
493 memset(vol->source_rfc1001_name,0x20,15);
494 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
495 /* does not have to be a perfect mapping since the field is
496 informational, only used for servers that do not support
497 port 445 and it can be overridden at mount time */
498 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
499 }
500 vol->source_rfc1001_name[15] = 0;
501
502 vol->linux_uid = current->uid; /* current->euid instead? */
503 vol->linux_gid = current->gid;
504 vol->dir_mode = S_IRWXUGO;
505 /* 2767 perms indicate mandatory locking support */
506 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
507
508 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
509 vol->rw = TRUE;
510
511 if (!options)
512 return 1;
513
514 if(strncmp(options,"sep=",4) == 0) {
515 if(options[4] != 0) {
516 separator[0] = options[4];
517 options += 5;
518 } else {
519 cFYI(1,("Null separator not allowed"));
520 }
521 }
522
523 while ((data = strsep(&options, separator)) != NULL) {
524 if (!*data)
525 continue;
526 if ((value = strchr(data, '=')) != NULL)
527 *value++ = '\0';
528
529 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
530 vol->no_xattr = 0;
531 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
532 vol->no_xattr = 1;
533 } else if (strnicmp(data, "user", 4) == 0) {
534 if (!value || !*value) {
535 printk(KERN_WARNING
536 "CIFS: invalid or missing username\n");
537 return 1; /* needs_arg; */
538 }
539 if (strnlen(value, 200) < 200) {
540 vol->username = value;
541 } else {
542 printk(KERN_WARNING "CIFS: username too long\n");
543 return 1;
544 }
545 } else if (strnicmp(data, "pass", 4) == 0) {
546 if (!value) {
547 vol->password = NULL;
548 continue;
549 } else if(value[0] == 0) {
550 /* check if string begins with double comma
551 since that would mean the password really
552 does start with a comma, and would not
553 indicate an empty string */
554 if(value[1] != separator[0]) {
555 vol->password = NULL;
556 continue;
557 }
558 }
559 temp_len = strlen(value);
560 /* removed password length check, NTLM passwords
561 can be arbitrarily long */
562
563 /* if comma in password, the string will be
564 prematurely null terminated. Commas in password are
565 specified across the cifs mount interface by a double
566 comma ie ,, and a comma used as in other cases ie ','
567 as a parameter delimiter/separator is single and due
568 to the strsep above is temporarily zeroed. */
569
570 /* NB: password legally can have multiple commas and
571 the only illegal character in a password is null */
572
573 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
574 /* reinsert comma */
575 value[temp_len] = separator[0];
576 temp_len+=2; /* move after the second comma */
577 while(value[temp_len] != 0) {
578 if (value[temp_len] == separator[0]) {
579 if (value[temp_len+1] == separator[0]) {
580 temp_len++; /* skip second comma */
581 } else {
582 /* single comma indicating start
583 of next parm */
584 break;
585 }
586 }
587 temp_len++;
588 }
589 if(value[temp_len] == 0) {
590 options = NULL;
591 } else {
592 value[temp_len] = 0;
593 /* point option to start of next parm */
594 options = value + temp_len + 1;
595 }
596 /* go from value to value + temp_len condensing
597 double commas to singles. Note that this ends up
598 allocating a few bytes too many, which is ok */
599 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
600 for(i=0,j=0;i<temp_len;i++,j++) {
601 vol->password[j] = value[i];
602 if(value[i] == separator[0] && value[i+1] == separator[0]) {
603 /* skip second comma */
604 i++;
605 }
606 }
607 vol->password[j] = 0;
608 } else {
609 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
610 strcpy(vol->password, value);
611 }
612 } else if (strnicmp(data, "ip", 2) == 0) {
613 if (!value || !*value) {
614 vol->UNCip = NULL;
615 } else if (strnlen(value, 35) < 35) {
616 vol->UNCip = value;
617 } else {
618 printk(KERN_WARNING "CIFS: ip address too long\n");
619 return 1;
620 }
621 } else if ((strnicmp(data, "unc", 3) == 0)
622 || (strnicmp(data, "target", 6) == 0)
623 || (strnicmp(data, "path", 4) == 0)) {
624 if (!value || !*value) {
625 printk(KERN_WARNING
626 "CIFS: invalid path to network resource\n");
627 return 1; /* needs_arg; */
628 }
629 if ((temp_len = strnlen(value, 300)) < 300) {
630 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
631 if(vol->UNC == NULL)
632 return 1;
633 strcpy(vol->UNC,value);
634 if (strncmp(vol->UNC, "//", 2) == 0) {
635 vol->UNC[0] = '\\';
636 vol->UNC[1] = '\\';
637 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
638 printk(KERN_WARNING
639 "CIFS: UNC Path does not begin with // or \\\\ \n");
640 return 1;
641 }
642 } else {
643 printk(KERN_WARNING "CIFS: UNC name too long\n");
644 return 1;
645 }
646 } else if ((strnicmp(data, "domain", 3) == 0)
647 || (strnicmp(data, "workgroup", 5) == 0)) {
648 if (!value || !*value) {
649 printk(KERN_WARNING "CIFS: invalid domain name\n");
650 return 1; /* needs_arg; */
651 }
652 /* BB are there cases in which a comma can be valid in
653 a domain name and need special handling? */
654 if (strnlen(value, 65) < 65) {
655 vol->domainname = value;
656 cFYI(1, ("Domain name set"));
657 } else {
658 printk(KERN_WARNING "CIFS: domain name too long\n");
659 return 1;
660 }
661 } else if (strnicmp(data, "iocharset", 9) == 0) {
662 if (!value || !*value) {
663 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
664 return 1; /* needs_arg; */
665 }
666 if (strnlen(value, 65) < 65) {
667 if(strnicmp(value,"default",7))
668 vol->iocharset = value;
669 /* if iocharset not set load_nls_default used by caller */
670 cFYI(1, ("iocharset set to %s",value));
671 } else {
672 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
673 return 1;
674 }
675 } else if (strnicmp(data, "uid", 3) == 0) {
676 if (value && *value) {
677 vol->linux_uid =
678 simple_strtoul(value, &value, 0);
679 }
680 } else if (strnicmp(data, "gid", 3) == 0) {
681 if (value && *value) {
682 vol->linux_gid =
683 simple_strtoul(value, &value, 0);
684 }
685 } else if (strnicmp(data, "file_mode", 4) == 0) {
686 if (value && *value) {
687 vol->file_mode =
688 simple_strtoul(value, &value, 0);
689 }
690 } else if (strnicmp(data, "dir_mode", 4) == 0) {
691 if (value && *value) {
692 vol->dir_mode =
693 simple_strtoul(value, &value, 0);
694 }
695 } else if (strnicmp(data, "dirmode", 4) == 0) {
696 if (value && *value) {
697 vol->dir_mode =
698 simple_strtoul(value, &value, 0);
699 }
700 } else if (strnicmp(data, "port", 4) == 0) {
701 if (value && *value) {
702 vol->port =
703 simple_strtoul(value, &value, 0);
704 }
705 } else if (strnicmp(data, "rsize", 5) == 0) {
706 if (value && *value) {
707 vol->rsize =
708 simple_strtoul(value, &value, 0);
709 }
710 } else if (strnicmp(data, "wsize", 5) == 0) {
711 if (value && *value) {
712 vol->wsize =
713 simple_strtoul(value, &value, 0);
714 }
715 } else if (strnicmp(data, "sockopt", 5) == 0) {
716 if (value && *value) {
717 vol->sockopt =
718 simple_strtoul(value, &value, 0);
719 }
720 } else if (strnicmp(data, "netbiosname", 4) == 0) {
721 if (!value || !*value || (*value == ' ')) {
722 cFYI(1,("invalid (empty) netbiosname specified"));
723 } else {
724 memset(vol->source_rfc1001_name,0x20,15);
725 for(i=0;i<15;i++) {
726 /* BB are there cases in which a comma can be
727 valid in this workstation netbios name (and need
728 special handling)? */
729
730 /* We do not uppercase netbiosname for user */
731 if (value[i]==0)
732 break;
733 else
734 vol->source_rfc1001_name[i] = value[i];
735 }
736 /* The string has 16th byte zero still from
737 set at top of the function */
738 if((i==15) && (value[i] != 0))
739 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
740 }
741 } else if (strnicmp(data, "credentials", 4) == 0) {
742 /* ignore */
743 } else if (strnicmp(data, "version", 3) == 0) {
744 /* ignore */
745 } else if (strnicmp(data, "guest",5) == 0) {
746 /* ignore */
747 } else if (strnicmp(data, "rw", 2) == 0) {
748 vol->rw = TRUE;
749 } else if ((strnicmp(data, "suid", 4) == 0) ||
750 (strnicmp(data, "nosuid", 6) == 0) ||
751 (strnicmp(data, "exec", 4) == 0) ||
752 (strnicmp(data, "noexec", 6) == 0) ||
753 (strnicmp(data, "nodev", 5) == 0) ||
754 (strnicmp(data, "noauto", 6) == 0) ||
755 (strnicmp(data, "dev", 3) == 0)) {
756 /* The mount tool or mount.cifs helper (if present)
757 uses these opts to set flags, and the flags are read
758 by the kernel vfs layer before we get here (ie
759 before read super) so there is no point trying to
760 parse these options again and set anything and it
761 is ok to just ignore them */
762 continue;
763 } else if (strnicmp(data, "ro", 2) == 0) {
764 vol->rw = FALSE;
765 } else if (strnicmp(data, "hard", 4) == 0) {
766 vol->retry = 1;
767 } else if (strnicmp(data, "soft", 4) == 0) {
768 vol->retry = 0;
769 } else if (strnicmp(data, "perm", 4) == 0) {
770 vol->noperm = 0;
771 } else if (strnicmp(data, "noperm", 6) == 0) {
772 vol->noperm = 1;
773 } else if (strnicmp(data, "setuids", 7) == 0) {
774 vol->setuids = 1;
775 } else if (strnicmp(data, "nosetuids", 9) == 0) {
776 vol->setuids = 0;
777 } else if (strnicmp(data, "nohard", 6) == 0) {
778 vol->retry = 0;
779 } else if (strnicmp(data, "nosoft", 6) == 0) {
780 vol->retry = 1;
781 } else if (strnicmp(data, "nointr", 6) == 0) {
782 vol->intr = 0;
783 } else if (strnicmp(data, "intr", 4) == 0) {
784 vol->intr = 1;
785 } else if (strnicmp(data, "serverino",7) == 0) {
786 vol->server_ino = 1;
787 } else if (strnicmp(data, "noserverino",9) == 0) {
788 vol->server_ino = 0;
789 } else if (strnicmp(data, "acl",3) == 0) {
790 vol->no_psx_acl = 0;
791 } else if (strnicmp(data, "noacl",5) == 0) {
792 vol->no_psx_acl = 1;
793 } else if (strnicmp(data, "direct",6) == 0) {
794 vol->direct_io = 1;
795 } else if (strnicmp(data, "forcedirectio",13) == 0) {
796 vol->direct_io = 1;
797 } else if (strnicmp(data, "in6_addr",8) == 0) {
798 if (!value || !*value) {
799 vol->in6_addr = NULL;
800 } else if (strnlen(value, 49) == 48) {
801 vol->in6_addr = value;
802 } else {
803 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
804 return 1;
805 }
806 } else if (strnicmp(data, "noac", 4) == 0) {
807 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
808 } else
809 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
810 }
811 if (vol->UNC == NULL) {
812 if(devname == NULL) {
813 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
814 return 1;
815 }
816 if ((temp_len = strnlen(devname, 300)) < 300) {
817 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
818 if(vol->UNC == NULL)
819 return 1;
820 strcpy(vol->UNC,devname);
821 if (strncmp(vol->UNC, "//", 2) == 0) {
822 vol->UNC[0] = '\\';
823 vol->UNC[1] = '\\';
824 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
825 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
826 return 1;
827 }
828 } else {
829 printk(KERN_WARNING "CIFS: UNC name too long\n");
830 return 1;
831 }
832 }
833 if(vol->UNCip == NULL)
834 vol->UNCip = &vol->UNC[2];
835
836 return 0;
837}
838
839static struct cifsSesInfo *
840cifs_find_tcp_session(struct in_addr * target_ip_addr,
841 struct in6_addr *target_ip6_addr,
842 char *userName, struct TCP_Server_Info **psrvTcp)
843{
844 struct list_head *tmp;
845 struct cifsSesInfo *ses;
846 *psrvTcp = NULL;
847 read_lock(&GlobalSMBSeslock);
848
849 list_for_each(tmp, &GlobalSMBSessionList) {
850 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
851 if (ses->server) {
852 if((target_ip_addr &&
853 (ses->server->addr.sockAddr.sin_addr.s_addr
854 == target_ip_addr->s_addr)) || (target_ip6_addr
855 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
856 target_ip6_addr,sizeof(*target_ip6_addr)))){
857 /* BB lock server and tcp session and increment use count here?? */
858 *psrvTcp = ses->server; /* found a match on the TCP session */
859 /* BB check if reconnection needed */
860 if (strncmp
861 (ses->userName, userName,
862 MAX_USERNAME_SIZE) == 0){
863 read_unlock(&GlobalSMBSeslock);
864 return ses; /* found exact match on both tcp and SMB sessions */
865 }
866 }
867 }
868 /* else tcp and smb sessions need reconnection */
869 }
870 read_unlock(&GlobalSMBSeslock);
871 return NULL;
872}
873
874static struct cifsTconInfo *
875find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
876{
877 struct list_head *tmp;
878 struct cifsTconInfo *tcon;
879
880 read_lock(&GlobalSMBSeslock);
881 list_for_each(tmp, &GlobalTreeConnectionList) {
882 cFYI(1, ("Next tcon - "));
883 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
884 if (tcon->ses) {
885 if (tcon->ses->server) {
886 cFYI(1,
887 (" old ip addr: %x == new ip %x ?",
888 tcon->ses->server->addr.sockAddr.sin_addr.
889 s_addr, new_target_ip_addr));
890 if (tcon->ses->server->addr.sockAddr.sin_addr.
891 s_addr == new_target_ip_addr) {
892 /* BB lock tcon and server and tcp session and increment use count here? */
893 /* found a match on the TCP session */
894 /* BB check if reconnection needed */
895 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
896 tcon->treeName, uncName));
897 if (strncmp
898 (tcon->treeName, uncName,
899 MAX_TREE_SIZE) == 0) {
900 cFYI(1,
901 ("Matched UNC, old user: %s == new: %s ?",
902 tcon->treeName, uncName));
903 if (strncmp
904 (tcon->ses->userName,
905 userName,
906 MAX_USERNAME_SIZE) == 0) {
907 read_unlock(&GlobalSMBSeslock);
908 return tcon;/* also matched user (smb session)*/
909 }
910 }
911 }
912 }
913 }
914 }
915 read_unlock(&GlobalSMBSeslock);
916 return NULL;
917}
918
919int
920connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
921 const char *old_path, const struct nls_table *nls_codepage)
922{
923 unsigned char *referrals = NULL;
924 unsigned int num_referrals;
925 int rc = 0;
926
927 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
928 &num_referrals, &referrals);
929
930 /* BB Add in code to: if valid refrl, if not ip address contact
931 the helper that resolves tcp names, mount to it, try to
932 tcon to it unmount it if fail */
933
934 if(referrals)
935 kfree(referrals);
936
937 return rc;
938}
939
940int
941get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
942 const char *old_path, const struct nls_table *nls_codepage,
943 unsigned int *pnum_referrals, unsigned char ** preferrals)
944{
945 char *temp_unc;
946 int rc = 0;
947
948 *pnum_referrals = 0;
949
950 if (pSesInfo->ipc_tid == 0) {
951 temp_unc = kmalloc(2 /* for slashes */ +
952 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
953 + 1 + 4 /* slash IPC$ */ + 2,
954 GFP_KERNEL);
955 if (temp_unc == NULL)
956 return -ENOMEM;
957 temp_unc[0] = '\\';
958 temp_unc[1] = '\\';
959 strcpy(temp_unc + 2, pSesInfo->serverName);
960 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
961 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
962 cFYI(1,
963 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
964 kfree(temp_unc);
965 }
966 if (rc == 0)
967 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
968 pnum_referrals, nls_codepage);
969
970 return rc;
971}
972
973/* See RFC1001 section 14 on representation of Netbios names */
974static void rfc1002mangle(char * target,char * source, unsigned int length)
975{
976 unsigned int i,j;
977
978 for(i=0,j=0;i<(length);i++) {
979 /* mask a nibble at a time and encode */
980 target[j] = 'A' + (0x0F & (source[i] >> 4));
981 target[j+1] = 'A' + (0x0F & source[i]);
982 j+=2;
983 }
984
985}
986
987
988static int
989ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
990 char * netbios_name)
991{
992 int rc = 0;
993 int connected = 0;
994 __be16 orig_port = 0;
995
996 if(*csocket == NULL) {
997 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
998 if (rc < 0) {
999 cERROR(1, ("Error %d creating socket",rc));
1000 *csocket = NULL;
1001 return rc;
1002 } else {
1003 /* BB other socket options to set KEEPALIVE, NODELAY? */
1004 cFYI(1,("Socket created"));
1005 (*csocket)->sk->sk_allocation = GFP_NOFS;
1006 }
1007 }
1008
1009 psin_server->sin_family = AF_INET;
1010 if(psin_server->sin_port) { /* user overrode default port */
1011 rc = (*csocket)->ops->connect(*csocket,
1012 (struct sockaddr *) psin_server,
1013 sizeof (struct sockaddr_in),0);
1014 if (rc >= 0)
1015 connected = 1;
1016 }
1017
1018 if(!connected) {
1019 /* save original port so we can retry user specified port
1020 later if fall back ports fail this time */
1021 orig_port = psin_server->sin_port;
1022
1023 /* do not retry on the same port we just failed on */
1024 if(psin_server->sin_port != htons(CIFS_PORT)) {
1025 psin_server->sin_port = htons(CIFS_PORT);
1026
1027 rc = (*csocket)->ops->connect(*csocket,
1028 (struct sockaddr *) psin_server,
1029 sizeof (struct sockaddr_in),0);
1030 if (rc >= 0)
1031 connected = 1;
1032 }
1033 }
1034 if (!connected) {
1035 psin_server->sin_port = htons(RFC1001_PORT);
1036 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1037 psin_server, sizeof (struct sockaddr_in),0);
1038 if (rc >= 0)
1039 connected = 1;
1040 }
1041
1042 /* give up here - unless we want to retry on different
1043 protocol families some day */
1044 if (!connected) {
1045 if(orig_port)
1046 psin_server->sin_port = orig_port;
1047 cFYI(1,("Error %d connecting to server via ipv4",rc));
1048 sock_release(*csocket);
1049 *csocket = NULL;
1050 return rc;
1051 }
1052 /* Eventually check for other socket options to change from
1053 the default. sock_setsockopt not used because it expects
1054 user space buffer */
1055 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1056
1057 /* send RFC1001 sessinit */
1058
1059 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1060 /* some servers require RFC1001 sessinit before sending
1061 negprot - BB check reconnection in case where second
1062 sessinit is sent but no second negprot */
1063 struct rfc1002_session_packet * ses_init_buf;
1064 struct smb_hdr * smb_buf;
1065 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1066 if(ses_init_buf) {
1067 ses_init_buf->trailer.session_req.called_len = 32;
1068 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1069 DEFAULT_CIFS_CALLED_NAME,16);
1070 ses_init_buf->trailer.session_req.calling_len = 32;
1071 /* calling name ends in null (byte 16) from old smb
1072 convention. */
1073 if(netbios_name && (netbios_name[0] !=0)) {
1074 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1075 netbios_name,16);
1076 } else {
1077 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1078 "LINUX_CIFS_CLNT",16);
1079 }
1080 ses_init_buf->trailer.session_req.scope1 = 0;
1081 ses_init_buf->trailer.session_req.scope2 = 0;
1082 smb_buf = (struct smb_hdr *)ses_init_buf;
1083 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1084 smb_buf->smb_buf_length = 0x81000044;
1085 rc = smb_send(*csocket, smb_buf, 0x44,
1086 (struct sockaddr *)psin_server);
1087 kfree(ses_init_buf);
1088 }
1089 /* else the negprot may still work without this
1090 even though malloc failed */
1091
1092 }
1093
1094 return rc;
1095}
1096
1097static int
1098ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1099{
1100 int rc = 0;
1101 int connected = 0;
1102 __be16 orig_port = 0;
1103
1104 if(*csocket == NULL) {
1105 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1106 if (rc < 0) {
1107 cERROR(1, ("Error %d creating ipv6 socket",rc));
1108 *csocket = NULL;
1109 return rc;
1110 } else {
1111 /* BB other socket options to set KEEPALIVE, NODELAY? */
1112 cFYI(1,("ipv6 Socket created"));
1113 (*csocket)->sk->sk_allocation = GFP_NOFS;
1114 }
1115 }
1116
1117 psin_server->sin6_family = AF_INET6;
1118
1119 if(psin_server->sin6_port) { /* user overrode default port */
1120 rc = (*csocket)->ops->connect(*csocket,
1121 (struct sockaddr *) psin_server,
1122 sizeof (struct sockaddr_in6),0);
1123 if (rc >= 0)
1124 connected = 1;
1125 }
1126
1127 if(!connected) {
1128 /* save original port so we can retry user specified port
1129 later if fall back ports fail this time */
1130
1131 orig_port = psin_server->sin6_port;
1132 /* do not retry on the same port we just failed on */
1133 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1134 psin_server->sin6_port = htons(CIFS_PORT);
1135
1136 rc = (*csocket)->ops->connect(*csocket,
1137 (struct sockaddr *) psin_server,
1138 sizeof (struct sockaddr_in6),0);
1139 if (rc >= 0)
1140 connected = 1;
1141 }
1142 }
1143 if (!connected) {
1144 psin_server->sin6_port = htons(RFC1001_PORT);
1145 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1146 psin_server, sizeof (struct sockaddr_in6),0);
1147 if (rc >= 0)
1148 connected = 1;
1149 }
1150
1151 /* give up here - unless we want to retry on different
1152 protocol families some day */
1153 if (!connected) {
1154 if(orig_port)
1155 psin_server->sin6_port = orig_port;
1156 cFYI(1,("Error %d connecting to server via ipv6",rc));
1157 sock_release(*csocket);
1158 *csocket = NULL;
1159 return rc;
1160 }
1161 /* Eventually check for other socket options to change from
1162 the default. sock_setsockopt not used because it expects
1163 user space buffer */
1164 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1165
1166 return rc;
1167}
1168
1169int
1170cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1171 char *mount_data, const char *devname)
1172{
1173 int rc = 0;
1174 int xid;
1175 int address_type = AF_INET;
1176 struct socket *csocket = NULL;
1177 struct sockaddr_in sin_server;
1178 struct sockaddr_in6 sin_server6;
1179 struct smb_vol volume_info;
1180 struct cifsSesInfo *pSesInfo = NULL;
1181 struct cifsSesInfo *existingCifsSes = NULL;
1182 struct cifsTconInfo *tcon = NULL;
1183 struct TCP_Server_Info *srvTcp = NULL;
1184
1185 xid = GetXid();
1186
1187/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1188
1189 memset(&volume_info,0,sizeof(struct smb_vol));
1190 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1191 if(volume_info.UNC)
1192 kfree(volume_info.UNC);
1193 if(volume_info.password)
1194 kfree(volume_info.password);
1195 FreeXid(xid);
1196 return -EINVAL;
1197 }
1198
1199 if (volume_info.username) {
1200 /* BB fixme parse for domain name here */
1201 cFYI(1, ("Username: %s ", volume_info.username));
1202
1203 } else {
1204 cifserror("No username specified ");
1205 /* In userspace mount helper we can get user name from alternate
1206 locations such as env variables and files on disk */
1207 if(volume_info.UNC)
1208 kfree(volume_info.UNC);
1209 if(volume_info.password)
1210 kfree(volume_info.password);
1211 FreeXid(xid);
1212 return -EINVAL;
1213 }
1214
1215 if (volume_info.UNCip && volume_info.UNC) {
1216 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1217
1218 if(rc <= 0) {
1219 /* not ipv4 address, try ipv6 */
1220 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1221 if(rc > 0)
1222 address_type = AF_INET6;
1223 } else {
1224 address_type = AF_INET;
1225 }
1226
1227 if(rc <= 0) {
1228 /* we failed translating address */
1229 if(volume_info.UNC)
1230 kfree(volume_info.UNC);
1231 if(volume_info.password)
1232 kfree(volume_info.password);
1233 FreeXid(xid);
1234 return -EINVAL;
1235 }
1236
1237 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1238 /* success */
1239 rc = 0;
1240 } else if (volume_info.UNCip){
1241 /* BB using ip addr as server name connect to the DFS root below */
1242 cERROR(1,("Connecting to DFS root not implemented yet"));
1243 if(volume_info.UNC)
1244 kfree(volume_info.UNC);
1245 if(volume_info.password)
1246 kfree(volume_info.password);
1247 FreeXid(xid);
1248 return -EINVAL;
1249 } else /* which servers DFS root would we conect to */ {
1250 cERROR(1,
1251 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1252 if(volume_info.UNC)
1253 kfree(volume_info.UNC);
1254 if(volume_info.password)
1255 kfree(volume_info.password);
1256 FreeXid(xid);
1257 return -EINVAL;
1258 }
1259
1260 /* this is needed for ASCII cp to Unicode converts */
1261 if(volume_info.iocharset == NULL) {
1262 cifs_sb->local_nls = load_nls_default();
1263 /* load_nls_default can not return null */
1264 } else {
1265 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1266 if(cifs_sb->local_nls == NULL) {
1267 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1268 if(volume_info.UNC)
1269 kfree(volume_info.UNC);
1270 if(volume_info.password)
1271 kfree(volume_info.password);
1272 FreeXid(xid);
1273 return -ELIBACC;
1274 }
1275 }
1276
1277 if(address_type == AF_INET)
1278 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1279 NULL /* no ipv6 addr */,
1280 volume_info.username, &srvTcp);
1281 else if(address_type == AF_INET6)
1282 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1283 &sin_server6.sin6_addr,
1284 volume_info.username, &srvTcp);
1285 else {
1286 if(volume_info.UNC)
1287 kfree(volume_info.UNC);
1288 if(volume_info.password)
1289 kfree(volume_info.password);
1290 FreeXid(xid);
1291 return -EINVAL;
1292 }
1293
1294
1295 if (srvTcp) {
1296 cFYI(1, ("Existing tcp session with server found "));
1297 } else { /* create socket */
1298 if(volume_info.port)
1299 sin_server.sin_port = htons(volume_info.port);
1300 else
1301 sin_server.sin_port = 0;
1302 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1303 if (rc < 0) {
1304 cERROR(1,
1305 ("Error connecting to IPv4 socket. Aborting operation"));
1306 if(csocket != NULL)
1307 sock_release(csocket);
1308 if(volume_info.UNC)
1309 kfree(volume_info.UNC);
1310 if(volume_info.password)
1311 kfree(volume_info.password);
1312 FreeXid(xid);
1313 return rc;
1314 }
1315
1316 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1317 if (srvTcp == NULL) {
1318 rc = -ENOMEM;
1319 sock_release(csocket);
1320 if(volume_info.UNC)
1321 kfree(volume_info.UNC);
1322 if(volume_info.password)
1323 kfree(volume_info.password);
1324 FreeXid(xid);
1325 return rc;
1326 } else {
1327 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1328 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1329 atomic_set(&srvTcp->inFlight,0);
1330 /* BB Add code for ipv6 case too */
1331 srvTcp->ssocket = csocket;
1332 srvTcp->protocolType = IPV4;
1333 init_waitqueue_head(&srvTcp->response_q);
1334 init_waitqueue_head(&srvTcp->request_q);
1335 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1336 /* at this point we are the only ones with the pointer
1337 to the struct since the kernel thread not created yet
1338 so no need to spinlock this init of tcpStatus */
1339 srvTcp->tcpStatus = CifsNew;
1340 init_MUTEX(&srvTcp->tcpSem);
1341 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1342 CLONE_FS | CLONE_FILES | CLONE_VM);
1343 if(rc < 0) {
1344 rc = -ENOMEM;
1345 sock_release(csocket);
1346 if(volume_info.UNC)
1347 kfree(volume_info.UNC);
1348 if(volume_info.password)
1349 kfree(volume_info.password);
1350 FreeXid(xid);
1351 return rc;
1352 } else
1353 rc = 0;
1354 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1355 }
1356 }
1357
1358 if (existingCifsSes) {
1359 pSesInfo = existingCifsSes;
1360 cFYI(1, ("Existing smb sess found "));
1361 if(volume_info.password)
1362 kfree(volume_info.password);
1363 /* volume_info.UNC freed at end of function */
1364 } else if (!rc) {
1365 cFYI(1, ("Existing smb sess not found "));
1366 pSesInfo = sesInfoAlloc();
1367 if (pSesInfo == NULL)
1368 rc = -ENOMEM;
1369 else {
1370 pSesInfo->server = srvTcp;
1371 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1372 NIPQUAD(sin_server.sin_addr.s_addr));
1373 }
1374
1375 if (!rc){
1376 /* volume_info.password freed at unmount */
1377 if (volume_info.password)
1378 pSesInfo->password = volume_info.password;
1379 if (volume_info.username)
1380 strncpy(pSesInfo->userName,
1381 volume_info.username,MAX_USERNAME_SIZE);
1382 if (volume_info.domainname)
1383 strncpy(pSesInfo->domainName,
1384 volume_info.domainname,MAX_USERNAME_SIZE);
1385 pSesInfo->linux_uid = volume_info.linux_uid;
1386 down(&pSesInfo->sesSem);
1387 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1388 up(&pSesInfo->sesSem);
1389 if(!rc)
1390 atomic_inc(&srvTcp->socketUseCount);
1391 } else
1392 if(volume_info.password)
1393 kfree(volume_info.password);
1394 }
1395
1396 /* search for existing tcon to this server share */
1397 if (!rc) {
1398 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1399 cifs_sb->rsize = volume_info.rsize;
1400 else
1401 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1402 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1403 cifs_sb->wsize = volume_info.wsize;
1404 else
1405 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1406 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1407 cifs_sb->rsize = PAGE_CACHE_SIZE;
1408 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1409 }
1410 cifs_sb->mnt_uid = volume_info.linux_uid;
1411 cifs_sb->mnt_gid = volume_info.linux_gid;
1412 cifs_sb->mnt_file_mode = volume_info.file_mode;
1413 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1414 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1415
1416 if(volume_info.noperm)
1417 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1418 if(volume_info.setuids)
1419 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1420 if(volume_info.server_ino)
1421 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1422 if(volume_info.no_xattr)
1423 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1424 if(volume_info.direct_io) {
1425 cERROR(1,("mounting share using direct i/o"));
1426 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1427 }
1428
1429 tcon =
1430 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1431 volume_info.username);
1432 if (tcon) {
1433 cFYI(1, ("Found match on UNC path "));
1434 /* we can have only one retry value for a connection
1435 to a share so for resources mounted more than once
1436 to the same server share the last value passed in
1437 for the retry flag is used */
1438 tcon->retry = volume_info.retry;
1439 } else {
1440 tcon = tconInfoAlloc();
1441 if (tcon == NULL)
1442 rc = -ENOMEM;
1443 else {
1444 /* check for null share name ie connect to dfs root */
1445
1446 /* BB check if this works for exactly length three strings */
1447 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1448 && (strchr(volume_info.UNC + 3, '/') ==
1449 NULL)) {
1450 rc = connect_to_dfs_path(xid,
1451 pSesInfo,
1452 "",
1453 cifs_sb->
1454 local_nls);
1455 if(volume_info.UNC)
1456 kfree(volume_info.UNC);
1457 FreeXid(xid);
1458 return -ENODEV;
1459 } else {
1460 rc = CIFSTCon(xid, pSesInfo,
1461 volume_info.UNC,
1462 tcon, cifs_sb->local_nls);
1463 cFYI(1, ("CIFS Tcon rc = %d", rc));
1464 }
1465 if (!rc) {
1466 atomic_inc(&pSesInfo->inUse);
1467 tcon->retry = volume_info.retry;
1468 }
1469 }
1470 }
1471 }
1472 if(pSesInfo) {
1473 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1474 sb->s_maxbytes = (u64) 1 << 63;
1475 } else
1476 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1477 }
1478
1479 sb->s_time_gran = 100;
1480
1481/* on error free sesinfo and tcon struct if needed */
1482 if (rc) {
1483 /* if session setup failed, use count is zero but
1484 we still need to free cifsd thread */
1485 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1486 spin_lock(&GlobalMid_Lock);
1487 srvTcp->tcpStatus = CifsExiting;
1488 spin_unlock(&GlobalMid_Lock);
1489 if(srvTcp->tsk)
1490 send_sig(SIGKILL,srvTcp->tsk,1);
1491 }
1492 /* If find_unc succeeded then rc == 0 so we can not end */
1493 if (tcon) /* up accidently freeing someone elses tcon struct */
1494 tconInfoFree(tcon);
1495 if (existingCifsSes == NULL) {
1496 if (pSesInfo) {
1497 if ((pSesInfo->server) &&
1498 (pSesInfo->status == CifsGood)) {
1499 int temp_rc;
1500 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1501 /* if the socketUseCount is now zero */
1502 if((temp_rc == -ESHUTDOWN) &&
1503 (pSesInfo->server->tsk))
1504 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1505 } else
1506 cFYI(1, ("No session or bad tcon"));
1507 sesInfoFree(pSesInfo);
1508 /* pSesInfo = NULL; */
1509 }
1510 }
1511 } else {
1512 atomic_inc(&tcon->useCount);
1513 cifs_sb->tcon = tcon;
1514 tcon->ses = pSesInfo;
1515
1516 /* do not care if following two calls succeed - informational only */
1517 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1518 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1519 if (tcon->ses->capabilities & CAP_UNIX) {
1520 if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) {
1521 if(!volume_info.no_psx_acl) {
1522 if(CIFS_UNIX_POSIX_ACL_CAP &
1523 le64_to_cpu(tcon->fsUnixInfo.Capability))
1524 cFYI(1,("server negotiated posix acl support"));
1525 sb->s_flags |= MS_POSIXACL;
1526 }
1527 }
1528 }
1529 }
1530
1531 /* volume_info.password is freed above when existing session found
1532 (in which case it is not needed anymore) but when new sesion is created
1533 the password ptr is put in the new session structure (in which case the
1534 password will be freed at unmount time) */
1535 if(volume_info.UNC)
1536 kfree(volume_info.UNC);
1537 FreeXid(xid);
1538 return rc;
1539}
1540
1541static int
1542CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1543 char session_key[CIFS_SESSION_KEY_SIZE],
1544 const struct nls_table *nls_codepage)
1545{
1546 struct smb_hdr *smb_buffer;
1547 struct smb_hdr *smb_buffer_response;
1548 SESSION_SETUP_ANDX *pSMB;
1549 SESSION_SETUP_ANDX *pSMBr;
1550 char *bcc_ptr;
1551 char *user;
1552 char *domain;
1553 int rc = 0;
1554 int remaining_words = 0;
1555 int bytes_returned = 0;
1556 int len;
1557 __u32 capabilities;
1558 __u16 count;
1559
1560 cFYI(1, ("In sesssetup "));
1561 if(ses == NULL)
1562 return -EINVAL;
1563 user = ses->userName;
1564 domain = ses->domainName;
1565 smb_buffer = cifs_buf_get();
1566 if (smb_buffer == NULL) {
1567 return -ENOMEM;
1568 }
1569 smb_buffer_response = smb_buffer;
1570 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1571
1572 /* send SMBsessionSetup here */
1573 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1574 NULL /* no tCon exists yet */ , 13 /* wct */ );
1575
1576 pSMB->req_no_secext.AndXCommand = 0xFF;
1577 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1578 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1579
1580 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1581 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1582
1583 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1584 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1585 if (ses->capabilities & CAP_UNICODE) {
1586 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1587 capabilities |= CAP_UNICODE;
1588 }
1589 if (ses->capabilities & CAP_STATUS32) {
1590 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1591 capabilities |= CAP_STATUS32;
1592 }
1593 if (ses->capabilities & CAP_DFS) {
1594 smb_buffer->Flags2 |= SMBFLG2_DFS;
1595 capabilities |= CAP_DFS;
1596 }
1597 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1598
1599 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1600 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1601
1602 pSMB->req_no_secext.CaseSensitivePasswordLength =
1603 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1604 bcc_ptr = pByteArea(smb_buffer);
1605 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1606 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1607 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1608 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1609
1610 if (ses->capabilities & CAP_UNICODE) {
1611 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1612 *bcc_ptr = 0;
1613 bcc_ptr++;
1614 }
1615 if(user == NULL)
1616 bytes_returned = 0; /* skill null user */
1617 else
1618 bytes_returned =
1619 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1620 nls_codepage);
1621 /* convert number of 16 bit words to bytes */
1622 bcc_ptr += 2 * bytes_returned;
1623 bcc_ptr += 2; /* trailing null */
1624 if (domain == NULL)
1625 bytes_returned =
1626 cifs_strtoUCS((wchar_t *) bcc_ptr,
1627 "CIFS_LINUX_DOM", 32, nls_codepage);
1628 else
1629 bytes_returned =
1630 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1631 nls_codepage);
1632 bcc_ptr += 2 * bytes_returned;
1633 bcc_ptr += 2;
1634 bytes_returned =
1635 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1636 32, nls_codepage);
1637 bcc_ptr += 2 * bytes_returned;
1638 bytes_returned =
1639 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1640 32, nls_codepage);
1641 bcc_ptr += 2 * bytes_returned;
1642 bcc_ptr += 2;
1643 bytes_returned =
1644 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1645 64, nls_codepage);
1646 bcc_ptr += 2 * bytes_returned;
1647 bcc_ptr += 2;
1648 } else {
1649 if(user != NULL) {
1650 strncpy(bcc_ptr, user, 200);
1651 bcc_ptr += strnlen(user, 200);
1652 }
1653 *bcc_ptr = 0;
1654 bcc_ptr++;
1655 if (domain == NULL) {
1656 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1657 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1658 } else {
1659 strncpy(bcc_ptr, domain, 64);
1660 bcc_ptr += strnlen(domain, 64);
1661 *bcc_ptr = 0;
1662 bcc_ptr++;
1663 }
1664 strcpy(bcc_ptr, "Linux version ");
1665 bcc_ptr += strlen("Linux version ");
1666 strcpy(bcc_ptr, system_utsname.release);
1667 bcc_ptr += strlen(system_utsname.release) + 1;
1668 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1669 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1670 }
1671 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1672 smb_buffer->smb_buf_length += count;
1673 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1674
1675 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1676 &bytes_returned, 1);
1677 if (rc) {
1678/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1679 } else if ((smb_buffer_response->WordCount == 3)
1680 || (smb_buffer_response->WordCount == 4)) {
1681 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1682 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1683 if (action & GUEST_LOGIN)
1684 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1685 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1686 cFYI(1, ("UID = %d ", ses->Suid));
1687 /* response can have either 3 or 4 word count - Samba sends 3 */
1688 bcc_ptr = pByteArea(smb_buffer_response);
1689 if ((pSMBr->resp.hdr.WordCount == 3)
1690 || ((pSMBr->resp.hdr.WordCount == 4)
1691 && (blob_len < pSMBr->resp.ByteCount))) {
1692 if (pSMBr->resp.hdr.WordCount == 4)
1693 bcc_ptr += blob_len;
1694
1695 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1696 if ((long) (bcc_ptr) % 2) {
1697 remaining_words =
1698 (BCC(smb_buffer_response) - 1) /2;
1699 bcc_ptr++; /* Unicode strings must be word aligned */
1700 } else {
1701 remaining_words =
1702 BCC(smb_buffer_response) / 2;
1703 }
1704 len =
1705 UniStrnlen((wchar_t *) bcc_ptr,
1706 remaining_words - 1);
1707/* We look for obvious messed up bcc or strings in response so we do not go off
1708 the end since (at least) WIN2K and Windows XP have a major bug in not null
1709 terminating last Unicode string in response */
1710 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1711 cifs_strfromUCS_le(ses->serverOS,
1712 (wchar_t *)bcc_ptr, len,nls_codepage);
1713 bcc_ptr += 2 * (len + 1);
1714 remaining_words -= len + 1;
1715 ses->serverOS[2 * len] = 0;
1716 ses->serverOS[1 + (2 * len)] = 0;
1717 if (remaining_words > 0) {
1718 len = UniStrnlen((wchar_t *)bcc_ptr,
1719 remaining_words-1);
1720 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1721 cifs_strfromUCS_le(ses->serverNOS,
1722 (wchar_t *)bcc_ptr,len,nls_codepage);
1723 bcc_ptr += 2 * (len + 1);
1724 ses->serverNOS[2 * len] = 0;
1725 ses->serverNOS[1 + (2 * len)] = 0;
1726 if(strncmp(ses->serverNOS,
1727 "NT LAN Manager 4",16) == 0) {
1728 cFYI(1,("NT4 server"));
1729 ses->flags |= CIFS_SES_NT4;
1730 }
1731 remaining_words -= len + 1;
1732 if (remaining_words > 0) {
1733 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1734 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1735 ses->serverDomain =
1736 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1737 cifs_strfromUCS_le(ses->serverDomain,
1738 (wchar_t *)bcc_ptr,len,nls_codepage);
1739 bcc_ptr += 2 * (len + 1);
1740 ses->serverDomain[2*len] = 0;
1741 ses->serverDomain[1+(2*len)] = 0;
1742 } /* else no more room so create dummy domain string */
1743 else
1744 ses->serverDomain =
1745 cifs_kcalloc(2,
1746 GFP_KERNEL);
1747 } else { /* no room so create dummy domain and NOS string */
1748 ses->serverDomain =
1749 cifs_kcalloc(2, GFP_KERNEL);
1750 ses->serverNOS =
1751 cifs_kcalloc(2, GFP_KERNEL);
1752 }
1753 } else { /* ASCII */
1754 len = strnlen(bcc_ptr, 1024);
1755 if (((long) bcc_ptr + len) - (long)
1756 pByteArea(smb_buffer_response)
1757 <= BCC(smb_buffer_response)) {
1758 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1759 strncpy(ses->serverOS,bcc_ptr, len);
1760
1761 bcc_ptr += len;
1762 bcc_ptr[0] = 0; /* null terminate the string */
1763 bcc_ptr++;
1764
1765 len = strnlen(bcc_ptr, 1024);
1766 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1767 strncpy(ses->serverNOS, bcc_ptr, len);
1768 bcc_ptr += len;
1769 bcc_ptr[0] = 0;
1770 bcc_ptr++;
1771
1772 len = strnlen(bcc_ptr, 1024);
1773 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1774 strncpy(ses->serverDomain, bcc_ptr, len);
1775 bcc_ptr += len;
1776 bcc_ptr[0] = 0;
1777 bcc_ptr++;
1778 } else
1779 cFYI(1,
1780 ("Variable field of length %d extends beyond end of smb ",
1781 len));
1782 }
1783 } else {
1784 cERROR(1,
1785 (" Security Blob Length extends beyond end of SMB"));
1786 }
1787 } else {
1788 cERROR(1,
1789 (" Invalid Word count %d: ",
1790 smb_buffer_response->WordCount));
1791 rc = -EIO;
1792 }
1793
1794 if (smb_buffer)
1795 cifs_buf_release(smb_buffer);
1796
1797 return rc;
1798}
1799
1800static int
1801CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1802 char *SecurityBlob,int SecurityBlobLength,
1803 const struct nls_table *nls_codepage)
1804{
1805 struct smb_hdr *smb_buffer;
1806 struct smb_hdr *smb_buffer_response;
1807 SESSION_SETUP_ANDX *pSMB;
1808 SESSION_SETUP_ANDX *pSMBr;
1809 char *bcc_ptr;
1810 char *user;
1811 char *domain;
1812 int rc = 0;
1813 int remaining_words = 0;
1814 int bytes_returned = 0;
1815 int len;
1816 __u32 capabilities;
1817 __u16 count;
1818
1819 cFYI(1, ("In spnego sesssetup "));
1820 if(ses == NULL)
1821 return -EINVAL;
1822 user = ses->userName;
1823 domain = ses->domainName;
1824
1825 smb_buffer = cifs_buf_get();
1826 if (smb_buffer == NULL) {
1827 return -ENOMEM;
1828 }
1829 smb_buffer_response = smb_buffer;
1830 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1831
1832 /* send SMBsessionSetup here */
1833 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1834 NULL /* no tCon exists yet */ , 12 /* wct */ );
1835 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1836 pSMB->req.AndXCommand = 0xFF;
1837 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1838 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1839
1840 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1841 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1842
1843 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1844 CAP_EXTENDED_SECURITY;
1845 if (ses->capabilities & CAP_UNICODE) {
1846 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1847 capabilities |= CAP_UNICODE;
1848 }
1849 if (ses->capabilities & CAP_STATUS32) {
1850 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1851 capabilities |= CAP_STATUS32;
1852 }
1853 if (ses->capabilities & CAP_DFS) {
1854 smb_buffer->Flags2 |= SMBFLG2_DFS;
1855 capabilities |= CAP_DFS;
1856 }
1857 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1858
1859 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1860 bcc_ptr = pByteArea(smb_buffer);
1861 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1862 bcc_ptr += SecurityBlobLength;
1863
1864 if (ses->capabilities & CAP_UNICODE) {
1865 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1866 *bcc_ptr = 0;
1867 bcc_ptr++;
1868 }
1869 bytes_returned =
1870 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1871 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1872 bcc_ptr += 2; /* trailing null */
1873 if (domain == NULL)
1874 bytes_returned =
1875 cifs_strtoUCS((wchar_t *) bcc_ptr,
1876 "CIFS_LINUX_DOM", 32, nls_codepage);
1877 else
1878 bytes_returned =
1879 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1880 nls_codepage);
1881 bcc_ptr += 2 * bytes_returned;
1882 bcc_ptr += 2;
1883 bytes_returned =
1884 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1885 32, nls_codepage);
1886 bcc_ptr += 2 * bytes_returned;
1887 bytes_returned =
1888 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1889 nls_codepage);
1890 bcc_ptr += 2 * bytes_returned;
1891 bcc_ptr += 2;
1892 bytes_returned =
1893 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1894 64, nls_codepage);
1895 bcc_ptr += 2 * bytes_returned;
1896 bcc_ptr += 2;
1897 } else {
1898 strncpy(bcc_ptr, user, 200);
1899 bcc_ptr += strnlen(user, 200);
1900 *bcc_ptr = 0;
1901 bcc_ptr++;
1902 if (domain == NULL) {
1903 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1904 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1905 } else {
1906 strncpy(bcc_ptr, domain, 64);
1907 bcc_ptr += strnlen(domain, 64);
1908 *bcc_ptr = 0;
1909 bcc_ptr++;
1910 }
1911 strcpy(bcc_ptr, "Linux version ");
1912 bcc_ptr += strlen("Linux version ");
1913 strcpy(bcc_ptr, system_utsname.release);
1914 bcc_ptr += strlen(system_utsname.release) + 1;
1915 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1916 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1917 }
1918 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1919 smb_buffer->smb_buf_length += count;
1920 pSMB->req.ByteCount = cpu_to_le16(count);
1921
1922 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1923 &bytes_returned, 1);
1924 if (rc) {
1925/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1926 } else if ((smb_buffer_response->WordCount == 3)
1927 || (smb_buffer_response->WordCount == 4)) {
1928 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1929 __u16 blob_len =
1930 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1931 if (action & GUEST_LOGIN)
1932 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1933 if (ses) {
1934 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1935 cFYI(1, ("UID = %d ", ses->Suid));
1936 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1937
1938 /* BB Fix below to make endian neutral !! */
1939
1940 if ((pSMBr->resp.hdr.WordCount == 3)
1941 || ((pSMBr->resp.hdr.WordCount == 4)
1942 && (blob_len <
1943 pSMBr->resp.ByteCount))) {
1944 if (pSMBr->resp.hdr.WordCount == 4) {
1945 bcc_ptr +=
1946 blob_len;
1947 cFYI(1,
1948 ("Security Blob Length %d ",
1949 blob_len));
1950 }
1951
1952 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1953 if ((long) (bcc_ptr) % 2) {
1954 remaining_words =
1955 (BCC(smb_buffer_response)
1956 - 1) / 2;
1957 bcc_ptr++; /* Unicode strings must be word aligned */
1958 } else {
1959 remaining_words =
1960 BCC
1961 (smb_buffer_response) / 2;
1962 }
1963 len =
1964 UniStrnlen((wchar_t *) bcc_ptr,
1965 remaining_words - 1);
1966/* We look for obvious messed up bcc or strings in response so we do not go off
1967 the end since (at least) WIN2K and Windows XP have a major bug in not null
1968 terminating last Unicode string in response */
1969 ses->serverOS =
1970 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1971 cifs_strfromUCS_le(ses->serverOS,
1972 (wchar_t *)
1973 bcc_ptr, len,
1974 nls_codepage);
1975 bcc_ptr += 2 * (len + 1);
1976 remaining_words -= len + 1;
1977 ses->serverOS[2 * len] = 0;
1978 ses->serverOS[1 + (2 * len)] = 0;
1979 if (remaining_words > 0) {
1980 len = UniStrnlen((wchar_t *)bcc_ptr,
1981 remaining_words
1982 - 1);
1983 ses->serverNOS =
1984 cifs_kcalloc(2 * (len + 1),
1985 GFP_KERNEL);
1986 cifs_strfromUCS_le(ses->serverNOS,
1987 (wchar_t *)bcc_ptr,
1988 len,
1989 nls_codepage);
1990 bcc_ptr += 2 * (len + 1);
1991 ses->serverNOS[2 * len] = 0;
1992 ses->serverNOS[1 + (2 * len)] = 0;
1993 remaining_words -= len + 1;
1994 if (remaining_words > 0) {
1995 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1996 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1997 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
1998 cifs_strfromUCS_le(ses->serverDomain,
1999 (wchar_t *)bcc_ptr,
2000 len,
2001 nls_codepage);
2002 bcc_ptr += 2*(len+1);
2003 ses->serverDomain[2*len] = 0;
2004 ses->serverDomain[1+(2*len)] = 0;
2005 } /* else no more room so create dummy domain string */
2006 else
2007 ses->serverDomain =
2008 cifs_kcalloc(2,GFP_KERNEL);
2009 } else { /* no room so create dummy domain and NOS string */
2010 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2011 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2012 }
2013 } else { /* ASCII */
2014
2015 len = strnlen(bcc_ptr, 1024);
2016 if (((long) bcc_ptr + len) - (long)
2017 pByteArea(smb_buffer_response)
2018 <= BCC(smb_buffer_response)) {
2019 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
2020 strncpy(ses->serverOS, bcc_ptr, len);
2021
2022 bcc_ptr += len;
2023 bcc_ptr[0] = 0; /* null terminate the string */
2024 bcc_ptr++;
2025
2026 len = strnlen(bcc_ptr, 1024);
2027 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2028 strncpy(ses->serverNOS, bcc_ptr, len);
2029 bcc_ptr += len;
2030 bcc_ptr[0] = 0;
2031 bcc_ptr++;
2032
2033 len = strnlen(bcc_ptr, 1024);
2034 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
2035 strncpy(ses->serverDomain, bcc_ptr, len);
2036 bcc_ptr += len;
2037 bcc_ptr[0] = 0;
2038 bcc_ptr++;
2039 } else
2040 cFYI(1,
2041 ("Variable field of length %d extends beyond end of smb ",
2042 len));
2043 }
2044 } else {
2045 cERROR(1,
2046 (" Security Blob Length extends beyond end of SMB"));
2047 }
2048 } else {
2049 cERROR(1, ("No session structure passed in."));
2050 }
2051 } else {
2052 cERROR(1,
2053 (" Invalid Word count %d: ",
2054 smb_buffer_response->WordCount));
2055 rc = -EIO;
2056 }
2057
2058 if (smb_buffer)
2059 cifs_buf_release(smb_buffer);
2060
2061 return rc;
2062}
2063
2064static int
2065CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2066 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2067 const struct nls_table *nls_codepage)
2068{
2069 struct smb_hdr *smb_buffer;
2070 struct smb_hdr *smb_buffer_response;
2071 SESSION_SETUP_ANDX *pSMB;
2072 SESSION_SETUP_ANDX *pSMBr;
2073 char *bcc_ptr;
2074 char *domain;
2075 int rc = 0;
2076 int remaining_words = 0;
2077 int bytes_returned = 0;
2078 int len;
2079 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2080 PNEGOTIATE_MESSAGE SecurityBlob;
2081 PCHALLENGE_MESSAGE SecurityBlob2;
2082 __u32 negotiate_flags, capabilities;
2083 __u16 count;
2084
2085 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2086 if(ses == NULL)
2087 return -EINVAL;
2088 domain = ses->domainName;
2089 *pNTLMv2_flag = FALSE;
2090 smb_buffer = cifs_buf_get();
2091 if (smb_buffer == NULL) {
2092 return -ENOMEM;
2093 }
2094 smb_buffer_response = smb_buffer;
2095 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2096 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2097
2098 /* send SMBsessionSetup here */
2099 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2100 NULL /* no tCon exists yet */ , 12 /* wct */ );
2101 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2102 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2103
2104 pSMB->req.AndXCommand = 0xFF;
2105 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2106 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2107
2108 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2109 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2110
2111 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2112 CAP_EXTENDED_SECURITY;
2113 if (ses->capabilities & CAP_UNICODE) {
2114 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2115 capabilities |= CAP_UNICODE;
2116 }
2117 if (ses->capabilities & CAP_STATUS32) {
2118 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2119 capabilities |= CAP_STATUS32;
2120 }
2121 if (ses->capabilities & CAP_DFS) {
2122 smb_buffer->Flags2 |= SMBFLG2_DFS;
2123 capabilities |= CAP_DFS;
2124 }
2125 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2126
2127 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2128 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2129 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2130 SecurityBlob->MessageType = NtLmNegotiate;
2131 negotiate_flags =
2132 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2133 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2134 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2135 if(sign_CIFS_PDUs)
2136 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2137 if(ntlmv2_support)
2138 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2139 /* setup pointers to domain name and workstation name */
2140 bcc_ptr += SecurityBlobLength;
2141
2142 SecurityBlob->WorkstationName.Buffer = 0;
2143 SecurityBlob->WorkstationName.Length = 0;
2144 SecurityBlob->WorkstationName.MaximumLength = 0;
2145
2146 if (domain == NULL) {
2147 SecurityBlob->DomainName.Buffer = 0;
2148 SecurityBlob->DomainName.Length = 0;
2149 SecurityBlob->DomainName.MaximumLength = 0;
2150 } else {
2151 __u16 len;
2152 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2153 strncpy(bcc_ptr, domain, 63);
2154 len = strnlen(domain, 64);
2155 SecurityBlob->DomainName.MaximumLength =
2156 cpu_to_le16(len);
2157 SecurityBlob->DomainName.Buffer =
2158 cpu_to_le32((long) &SecurityBlob->
2159 DomainString -
2160 (long) &SecurityBlob->Signature);
2161 bcc_ptr += len;
2162 SecurityBlobLength += len;
2163 SecurityBlob->DomainName.Length =
2164 cpu_to_le16(len);
2165 }
2166 if (ses->capabilities & CAP_UNICODE) {
2167 if ((long) bcc_ptr % 2) {
2168 *bcc_ptr = 0;
2169 bcc_ptr++;
2170 }
2171
2172 bytes_returned =
2173 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2174 32, nls_codepage);
2175 bcc_ptr += 2 * bytes_returned;
2176 bytes_returned =
2177 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2178 nls_codepage);
2179 bcc_ptr += 2 * bytes_returned;
2180 bcc_ptr += 2; /* null terminate Linux version */
2181 bytes_returned =
2182 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2183 64, nls_codepage);
2184 bcc_ptr += 2 * bytes_returned;
2185 *(bcc_ptr + 1) = 0;
2186 *(bcc_ptr + 2) = 0;
2187 bcc_ptr += 2; /* null terminate network opsys string */
2188 *(bcc_ptr + 1) = 0;
2189 *(bcc_ptr + 2) = 0;
2190 bcc_ptr += 2; /* null domain */
2191 } else { /* ASCII */
2192 strcpy(bcc_ptr, "Linux version ");
2193 bcc_ptr += strlen("Linux version ");
2194 strcpy(bcc_ptr, system_utsname.release);
2195 bcc_ptr += strlen(system_utsname.release) + 1;
2196 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2197 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2198 bcc_ptr++; /* empty domain field */
2199 *bcc_ptr = 0;
2200 }
2201 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2202 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2203 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2204 smb_buffer->smb_buf_length += count;
2205 pSMB->req.ByteCount = cpu_to_le16(count);
2206
2207 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2208 &bytes_returned, 1);
2209
2210 if (smb_buffer_response->Status.CifsError ==
2211 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2212 rc = 0;
2213
2214 if (rc) {
2215/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2216 } else if ((smb_buffer_response->WordCount == 3)
2217 || (smb_buffer_response->WordCount == 4)) {
2218 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2219 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2220
2221 if (action & GUEST_LOGIN)
2222 cFYI(1, (" Guest login"));
2223 /* Do we want to set anything in SesInfo struct when guest login? */
2224
2225 bcc_ptr = pByteArea(smb_buffer_response);
2226 /* response can have either 3 or 4 word count - Samba sends 3 */
2227
2228 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2229 if (SecurityBlob2->MessageType != NtLmChallenge) {
2230 cFYI(1,
2231 ("Unexpected NTLMSSP message type received %d",
2232 SecurityBlob2->MessageType));
2233 } else if (ses) {
2234 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2235 cFYI(1, ("UID = %d ", ses->Suid));
2236 if ((pSMBr->resp.hdr.WordCount == 3)
2237 || ((pSMBr->resp.hdr.WordCount == 4)
2238 && (blob_len <
2239 pSMBr->resp.ByteCount))) {
2240
2241 if (pSMBr->resp.hdr.WordCount == 4) {
2242 bcc_ptr += blob_len;
2243 cFYI(1,
2244 ("Security Blob Length %d ",
2245 blob_len));
2246 }
2247
2248 cFYI(1, ("NTLMSSP Challenge rcvd "));
2249
2250 memcpy(ses->server->cryptKey,
2251 SecurityBlob2->Challenge,
2252 CIFS_CRYPTO_KEY_SIZE);
2253 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2254 *pNTLMv2_flag = TRUE;
2255
2256 if((SecurityBlob2->NegotiateFlags &
2257 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2258 || (sign_CIFS_PDUs > 1))
2259 ses->server->secMode |=
2260 SECMODE_SIGN_REQUIRED;
2261 if ((SecurityBlob2->NegotiateFlags &
2262 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2263 ses->server->secMode |=
2264 SECMODE_SIGN_ENABLED;
2265
2266 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2267 if ((long) (bcc_ptr) % 2) {
2268 remaining_words =
2269 (BCC(smb_buffer_response)
2270 - 1) / 2;
2271 bcc_ptr++; /* Unicode strings must be word aligned */
2272 } else {
2273 remaining_words =
2274 BCC
2275 (smb_buffer_response) / 2;
2276 }
2277 len =
2278 UniStrnlen((wchar_t *) bcc_ptr,
2279 remaining_words - 1);
2280/* We look for obvious messed up bcc or strings in response so we do not go off
2281 the end since (at least) WIN2K and Windows XP have a major bug in not null
2282 terminating last Unicode string in response */
2283 ses->serverOS =
2284 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2285 cifs_strfromUCS_le(ses->serverOS,
2286 (wchar_t *)
2287 bcc_ptr, len,
2288 nls_codepage);
2289 bcc_ptr += 2 * (len + 1);
2290 remaining_words -= len + 1;
2291 ses->serverOS[2 * len] = 0;
2292 ses->serverOS[1 + (2 * len)] = 0;
2293 if (remaining_words > 0) {
2294 len = UniStrnlen((wchar_t *)
2295 bcc_ptr,
2296 remaining_words
2297 - 1);
2298 ses->serverNOS =
2299 cifs_kcalloc(2 * (len + 1),
2300 GFP_KERNEL);
2301 cifs_strfromUCS_le(ses->
2302 serverNOS,
2303 (wchar_t *)
2304 bcc_ptr,
2305 len,
2306 nls_codepage);
2307 bcc_ptr += 2 * (len + 1);
2308 ses->serverNOS[2 * len] = 0;
2309 ses->serverNOS[1 +
2310 (2 * len)] = 0;
2311 remaining_words -= len + 1;
2312 if (remaining_words > 0) {
2313 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2314 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2315 ses->serverDomain =
2316 cifs_kcalloc(2 *
2317 (len +
2318 1),
2319 GFP_KERNEL);
2320 cifs_strfromUCS_le
2321 (ses->
2322 serverDomain,
2323 (wchar_t *)
2324 bcc_ptr, len,
2325 nls_codepage);
2326 bcc_ptr +=
2327 2 * (len + 1);
2328 ses->
2329 serverDomain[2
2330 * len]
2331 = 0;
2332 ses->
2333 serverDomain[1
2334 +
2335 (2
2336 *
2337 len)]
2338 = 0;
2339 } /* else no more room so create dummy domain string */
2340 else
2341 ses->serverDomain =
2342 cifs_kcalloc(2,
2343 GFP_KERNEL);
2344 } else { /* no room so create dummy domain and NOS string */
2345 ses->serverDomain =
2346 cifs_kcalloc(2, GFP_KERNEL);
2347 ses->serverNOS =
2348 cifs_kcalloc(2, GFP_KERNEL);
2349 }
2350 } else { /* ASCII */
2351 len = strnlen(bcc_ptr, 1024);
2352 if (((long) bcc_ptr + len) - (long)
2353 pByteArea(smb_buffer_response)
2354 <= BCC(smb_buffer_response)) {
2355 ses->serverOS =
2356 cifs_kcalloc(len + 1,
2357 GFP_KERNEL);
2358 strncpy(ses->serverOS,
2359 bcc_ptr, len);
2360
2361 bcc_ptr += len;
2362 bcc_ptr[0] = 0; /* null terminate string */
2363 bcc_ptr++;
2364
2365 len = strnlen(bcc_ptr, 1024);
2366 ses->serverNOS =
2367 cifs_kcalloc(len + 1,
2368 GFP_KERNEL);
2369 strncpy(ses->serverNOS, bcc_ptr, len);
2370 bcc_ptr += len;
2371 bcc_ptr[0] = 0;
2372 bcc_ptr++;
2373
2374 len = strnlen(bcc_ptr, 1024);
2375 ses->serverDomain =
2376 cifs_kcalloc(len + 1,
2377 GFP_KERNEL);
2378 strncpy(ses->serverDomain, bcc_ptr, len);
2379 bcc_ptr += len;
2380 bcc_ptr[0] = 0;
2381 bcc_ptr++;
2382 } else
2383 cFYI(1,
2384 ("Variable field of length %d extends beyond end of smb ",
2385 len));
2386 }
2387 } else {
2388 cERROR(1,
2389 (" Security Blob Length extends beyond end of SMB"));
2390 }
2391 } else {
2392 cERROR(1, ("No session structure passed in."));
2393 }
2394 } else {
2395 cERROR(1,
2396 (" Invalid Word count %d: ",
2397 smb_buffer_response->WordCount));
2398 rc = -EIO;
2399 }
2400
2401 if (smb_buffer)
2402 cifs_buf_release(smb_buffer);
2403
2404 return rc;
2405}
2406static int
2407CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2408 char *ntlm_session_key, int ntlmv2_flag,
2409 const struct nls_table *nls_codepage)
2410{
2411 struct smb_hdr *smb_buffer;
2412 struct smb_hdr *smb_buffer_response;
2413 SESSION_SETUP_ANDX *pSMB;
2414 SESSION_SETUP_ANDX *pSMBr;
2415 char *bcc_ptr;
2416 char *user;
2417 char *domain;
2418 int rc = 0;
2419 int remaining_words = 0;
2420 int bytes_returned = 0;
2421 int len;
2422 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2423 PAUTHENTICATE_MESSAGE SecurityBlob;
2424 __u32 negotiate_flags, capabilities;
2425 __u16 count;
2426
2427 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2428 if(ses == NULL)
2429 return -EINVAL;
2430 user = ses->userName;
2431 domain = ses->domainName;
2432 smb_buffer = cifs_buf_get();
2433 if (smb_buffer == NULL) {
2434 return -ENOMEM;
2435 }
2436 smb_buffer_response = smb_buffer;
2437 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2438 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2439
2440 /* send SMBsessionSetup here */
2441 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2442 NULL /* no tCon exists yet */ , 12 /* wct */ );
2443 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2444 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2445 pSMB->req.AndXCommand = 0xFF;
2446 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2447 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2448
2449 pSMB->req.hdr.Uid = ses->Suid;
2450
2451 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2452 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2453
2454 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2455 CAP_EXTENDED_SECURITY;
2456 if (ses->capabilities & CAP_UNICODE) {
2457 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2458 capabilities |= CAP_UNICODE;
2459 }
2460 if (ses->capabilities & CAP_STATUS32) {
2461 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2462 capabilities |= CAP_STATUS32;
2463 }
2464 if (ses->capabilities & CAP_DFS) {
2465 smb_buffer->Flags2 |= SMBFLG2_DFS;
2466 capabilities |= CAP_DFS;
2467 }
2468 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2469
2470 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2471 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2472 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2473 SecurityBlob->MessageType = NtLmAuthenticate;
2474 bcc_ptr += SecurityBlobLength;
2475 negotiate_flags =
2476 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2477 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2478 0x80000000 | NTLMSSP_NEGOTIATE_128;
2479 if(sign_CIFS_PDUs)
2480 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2481 if(ntlmv2_flag)
2482 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2483
2484/* setup pointers to domain name and workstation name */
2485
2486 SecurityBlob->WorkstationName.Buffer = 0;
2487 SecurityBlob->WorkstationName.Length = 0;
2488 SecurityBlob->WorkstationName.MaximumLength = 0;
2489 SecurityBlob->SessionKey.Length = 0;
2490 SecurityBlob->SessionKey.MaximumLength = 0;
2491 SecurityBlob->SessionKey.Buffer = 0;
2492
2493 SecurityBlob->LmChallengeResponse.Length = 0;
2494 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2495 SecurityBlob->LmChallengeResponse.Buffer = 0;
2496
2497 SecurityBlob->NtChallengeResponse.Length =
2498 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2499 SecurityBlob->NtChallengeResponse.MaximumLength =
2500 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2501 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2502 SecurityBlob->NtChallengeResponse.Buffer =
2503 cpu_to_le32(SecurityBlobLength);
2504 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2505 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2506
2507 if (ses->capabilities & CAP_UNICODE) {
2508 if (domain == NULL) {
2509 SecurityBlob->DomainName.Buffer = 0;
2510 SecurityBlob->DomainName.Length = 0;
2511 SecurityBlob->DomainName.MaximumLength = 0;
2512 } else {
2513 __u16 len =
2514 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2515 nls_codepage);
2516 len *= 2;
2517 SecurityBlob->DomainName.MaximumLength =
2518 cpu_to_le16(len);
2519 SecurityBlob->DomainName.Buffer =
2520 cpu_to_le32(SecurityBlobLength);
2521 bcc_ptr += len;
2522 SecurityBlobLength += len;
2523 SecurityBlob->DomainName.Length =
2524 cpu_to_le16(len);
2525 }
2526 if (user == NULL) {
2527 SecurityBlob->UserName.Buffer = 0;
2528 SecurityBlob->UserName.Length = 0;
2529 SecurityBlob->UserName.MaximumLength = 0;
2530 } else {
2531 __u16 len =
2532 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2533 nls_codepage);
2534 len *= 2;
2535 SecurityBlob->UserName.MaximumLength =
2536 cpu_to_le16(len);
2537 SecurityBlob->UserName.Buffer =
2538 cpu_to_le32(SecurityBlobLength);
2539 bcc_ptr += len;
2540 SecurityBlobLength += len;
2541 SecurityBlob->UserName.Length =
2542 cpu_to_le16(len);
2543 }
2544
2545 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2546 SecurityBlob->WorkstationName.Length *= 2;
2547 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2548 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2549 bcc_ptr += SecurityBlob->WorkstationName.Length;
2550 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2551 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2552
2553 if ((long) bcc_ptr % 2) {
2554 *bcc_ptr = 0;
2555 bcc_ptr++;
2556 }
2557 bytes_returned =
2558 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2559 32, nls_codepage);
2560 bcc_ptr += 2 * bytes_returned;
2561 bytes_returned =
2562 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2563 nls_codepage);
2564 bcc_ptr += 2 * bytes_returned;
2565 bcc_ptr += 2; /* null term version string */
2566 bytes_returned =
2567 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2568 64, nls_codepage);
2569 bcc_ptr += 2 * bytes_returned;
2570 *(bcc_ptr + 1) = 0;
2571 *(bcc_ptr + 2) = 0;
2572 bcc_ptr += 2; /* null terminate network opsys string */
2573 *(bcc_ptr + 1) = 0;
2574 *(bcc_ptr + 2) = 0;
2575 bcc_ptr += 2; /* null domain */
2576 } else { /* ASCII */
2577 if (domain == NULL) {
2578 SecurityBlob->DomainName.Buffer = 0;
2579 SecurityBlob->DomainName.Length = 0;
2580 SecurityBlob->DomainName.MaximumLength = 0;
2581 } else {
2582 __u16 len;
2583 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2584 strncpy(bcc_ptr, domain, 63);
2585 len = strnlen(domain, 64);
2586 SecurityBlob->DomainName.MaximumLength =
2587 cpu_to_le16(len);
2588 SecurityBlob->DomainName.Buffer =
2589 cpu_to_le32(SecurityBlobLength);
2590 bcc_ptr += len;
2591 SecurityBlobLength += len;
2592 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2593 }
2594 if (user == NULL) {
2595 SecurityBlob->UserName.Buffer = 0;
2596 SecurityBlob->UserName.Length = 0;
2597 SecurityBlob->UserName.MaximumLength = 0;
2598 } else {
2599 __u16 len;
2600 strncpy(bcc_ptr, user, 63);
2601 len = strnlen(user, 64);
2602 SecurityBlob->UserName.MaximumLength =
2603 cpu_to_le16(len);
2604 SecurityBlob->UserName.Buffer =
2605 cpu_to_le32(SecurityBlobLength);
2606 bcc_ptr += len;
2607 SecurityBlobLength += len;
2608 SecurityBlob->UserName.Length = cpu_to_le16(len);
2609 }
2610 /* BB fill in our workstation name if known BB */
2611
2612 strcpy(bcc_ptr, "Linux version ");
2613 bcc_ptr += strlen("Linux version ");
2614 strcpy(bcc_ptr, system_utsname.release);
2615 bcc_ptr += strlen(system_utsname.release) + 1;
2616 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2617 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2618 bcc_ptr++; /* null domain */
2619 *bcc_ptr = 0;
2620 }
2621 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2622 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2623 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2624 smb_buffer->smb_buf_length += count;
2625 pSMB->req.ByteCount = cpu_to_le16(count);
2626
2627 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2628 &bytes_returned, 1);
2629 if (rc) {
2630/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2631 } else if ((smb_buffer_response->WordCount == 3)
2632 || (smb_buffer_response->WordCount == 4)) {
2633 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2634 __u16 blob_len =
2635 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2636 if (action & GUEST_LOGIN)
2637 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2638/* if(SecurityBlob2->MessageType != NtLm??){
2639 cFYI("Unexpected message type on auth response is %d "));
2640 } */
2641 if (ses) {
2642 cFYI(1,
2643 ("Does UID on challenge %d match auth response UID %d ",
2644 ses->Suid, smb_buffer_response->Uid));
2645 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2646 bcc_ptr = pByteArea(smb_buffer_response);
2647 /* response can have either 3 or 4 word count - Samba sends 3 */
2648 if ((pSMBr->resp.hdr.WordCount == 3)
2649 || ((pSMBr->resp.hdr.WordCount == 4)
2650 && (blob_len <
2651 pSMBr->resp.ByteCount))) {
2652 if (pSMBr->resp.hdr.WordCount == 4) {
2653 bcc_ptr +=
2654 blob_len;
2655 cFYI(1,
2656 ("Security Blob Length %d ",
2657 blob_len));
2658 }
2659
2660 cFYI(1,
2661 ("NTLMSSP response to Authenticate "));
2662
2663 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2664 if ((long) (bcc_ptr) % 2) {
2665 remaining_words =
2666 (BCC(smb_buffer_response)
2667 - 1) / 2;
2668 bcc_ptr++; /* Unicode strings must be word aligned */
2669 } else {
2670 remaining_words = BCC(smb_buffer_response) / 2;
2671 }
2672 len =
2673 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2674/* We look for obvious messed up bcc or strings in response so we do not go off
2675 the end since (at least) WIN2K and Windows XP have a major bug in not null
2676 terminating last Unicode string in response */
2677 ses->serverOS =
2678 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2679 cifs_strfromUCS_le(ses->serverOS,
2680 (wchar_t *)
2681 bcc_ptr, len,
2682 nls_codepage);
2683 bcc_ptr += 2 * (len + 1);
2684 remaining_words -= len + 1;
2685 ses->serverOS[2 * len] = 0;
2686 ses->serverOS[1 + (2 * len)] = 0;
2687 if (remaining_words > 0) {
2688 len = UniStrnlen((wchar_t *)
2689 bcc_ptr,
2690 remaining_words
2691 - 1);
2692 ses->serverNOS =
2693 cifs_kcalloc(2 * (len + 1),
2694 GFP_KERNEL);
2695 cifs_strfromUCS_le(ses->
2696 serverNOS,
2697 (wchar_t *)
2698 bcc_ptr,
2699 len,
2700 nls_codepage);
2701 bcc_ptr += 2 * (len + 1);
2702 ses->serverNOS[2 * len] = 0;
2703 ses->serverNOS[1+(2*len)] = 0;
2704 remaining_words -= len + 1;
2705 if (remaining_words > 0) {
2706 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2707 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2708 ses->serverDomain =
2709 cifs_kcalloc(2 *
2710 (len +
2711 1),
2712 GFP_KERNEL);
2713 cifs_strfromUCS_le
2714 (ses->
2715 serverDomain,
2716 (wchar_t *)
2717 bcc_ptr, len,
2718 nls_codepage);
2719 bcc_ptr +=
2720 2 * (len + 1);
2721 ses->
2722 serverDomain[2
2723 * len]
2724 = 0;
2725 ses->
2726 serverDomain[1
2727 +
2728 (2
2729 *
2730 len)]
2731 = 0;
2732 } /* else no more room so create dummy domain string */
2733 else
2734 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2735 } else { /* no room so create dummy domain and NOS string */
2736 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2737 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2738 }
2739 } else { /* ASCII */
2740 len = strnlen(bcc_ptr, 1024);
2741 if (((long) bcc_ptr + len) -
2742 (long) pByteArea(smb_buffer_response)
2743 <= BCC(smb_buffer_response)) {
2744 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2745 strncpy(ses->serverOS,bcc_ptr, len);
2746
2747 bcc_ptr += len;
2748 bcc_ptr[0] = 0; /* null terminate the string */
2749 bcc_ptr++;
2750
2751 len = strnlen(bcc_ptr, 1024);
2752 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2753 strncpy(ses->serverNOS, bcc_ptr, len);
2754 bcc_ptr += len;
2755 bcc_ptr[0] = 0;
2756 bcc_ptr++;
2757
2758 len = strnlen(bcc_ptr, 1024);
2759 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2760 strncpy(ses->serverDomain, bcc_ptr, len);
2761 bcc_ptr += len;
2762 bcc_ptr[0] = 0;
2763 bcc_ptr++;
2764 } else
2765 cFYI(1,
2766 ("Variable field of length %d extends beyond end of smb ",
2767 len));
2768 }
2769 } else {
2770 cERROR(1,
2771 (" Security Blob Length extends beyond end of SMB"));
2772 }
2773 } else {
2774 cERROR(1, ("No session structure passed in."));
2775 }
2776 } else {
2777 cERROR(1,
2778 (" Invalid Word count %d: ",
2779 smb_buffer_response->WordCount));
2780 rc = -EIO;
2781 }
2782
2783 if (smb_buffer)
2784 cifs_buf_release(smb_buffer);
2785
2786 return rc;
2787}
2788
2789int
2790CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2791 const char *tree, struct cifsTconInfo *tcon,
2792 const struct nls_table *nls_codepage)
2793{
2794 struct smb_hdr *smb_buffer;
2795 struct smb_hdr *smb_buffer_response;
2796 TCONX_REQ *pSMB;
2797 TCONX_RSP *pSMBr;
2798 unsigned char *bcc_ptr;
2799 int rc = 0;
2800 int length;
2801 __u16 count;
2802
2803 if (ses == NULL)
2804 return -EIO;
2805
2806 smb_buffer = cifs_buf_get();
2807 if (smb_buffer == NULL) {
2808 return -ENOMEM;
2809 }
2810 smb_buffer_response = smb_buffer;
2811
2812 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2813 NULL /*no tid */ , 4 /*wct */ );
2814 smb_buffer->Uid = ses->Suid;
2815 pSMB = (TCONX_REQ *) smb_buffer;
2816 pSMBr = (TCONX_RSP *) smb_buffer_response;
2817
2818 pSMB->AndXCommand = 0xFF;
2819 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2820 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2821 bcc_ptr = &pSMB->Password[0];
2822 bcc_ptr++; /* skip password */
2823
2824 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2825 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2826
2827 if (ses->capabilities & CAP_STATUS32) {
2828 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2829 }
2830 if (ses->capabilities & CAP_DFS) {
2831 smb_buffer->Flags2 |= SMBFLG2_DFS;
2832 }
2833 if (ses->capabilities & CAP_UNICODE) {
2834 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2835 length =
2836 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2837 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2838 bcc_ptr += 2; /* skip trailing null */
2839 } else { /* ASCII */
2840
2841 strcpy(bcc_ptr, tree);
2842 bcc_ptr += strlen(tree) + 1;
2843 }
2844 strcpy(bcc_ptr, "?????");
2845 bcc_ptr += strlen("?????");
2846 bcc_ptr += 1;
2847 count = bcc_ptr - &pSMB->Password[0];
2848 pSMB->hdr.smb_buf_length += count;
2849 pSMB->ByteCount = cpu_to_le16(count);
2850
2851 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2852
2853 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2854 /* above now done in SendReceive */
2855 if ((rc == 0) && (tcon != NULL)) {
2856 tcon->tidStatus = CifsGood;
2857 tcon->tid = smb_buffer_response->Tid;
2858 bcc_ptr = pByteArea(smb_buffer_response);
2859 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2860 /* skip service field (NB: this field is always ASCII) */
2861 bcc_ptr += length + 1;
2862 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2863 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2864 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2865 if ((bcc_ptr + (2 * length)) -
2866 pByteArea(smb_buffer_response) <=
2867 BCC(smb_buffer_response)) {
2868 if(tcon->nativeFileSystem)
2869 kfree(tcon->nativeFileSystem);
2870 tcon->nativeFileSystem =
2871 cifs_kcalloc(length + 2, GFP_KERNEL);
2872 cifs_strfromUCS_le(tcon->nativeFileSystem,
2873 (wchar_t *) bcc_ptr,
2874 length, nls_codepage);
2875 bcc_ptr += 2 * length;
2876 bcc_ptr[0] = 0; /* null terminate the string */
2877 bcc_ptr[1] = 0;
2878 bcc_ptr += 2;
2879 }
2880 /* else do not bother copying these informational fields */
2881 } else {
2882 length = strnlen(bcc_ptr, 1024);
2883 if ((bcc_ptr + length) -
2884 pByteArea(smb_buffer_response) <=
2885 BCC(smb_buffer_response)) {
2886 if(tcon->nativeFileSystem)
2887 kfree(tcon->nativeFileSystem);
2888 tcon->nativeFileSystem =
2889 cifs_kcalloc(length + 1, GFP_KERNEL);
2890 strncpy(tcon->nativeFileSystem, bcc_ptr,
2891 length);
2892 }
2893 /* else do not bother copying these informational fields */
2894 }
2895 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2896 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2897 } else if ((rc == 0) && tcon == NULL) {
2898 /* all we need to save for IPC$ connection */
2899 ses->ipc_tid = smb_buffer_response->Tid;
2900 }
2901
2902 if (smb_buffer)
2903 cifs_buf_release(smb_buffer);
2904 return rc;
2905}
2906
2907int
2908cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2909{
2910 int rc = 0;
2911 int xid;
2912 struct cifsSesInfo *ses = NULL;
2913 struct task_struct *cifsd_task;
2914
2915 xid = GetXid();
2916
2917 if (cifs_sb->tcon) {
2918 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2919 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2920 if (rc == -EBUSY) {
2921 FreeXid(xid);
2922 return 0;
2923 }
2924 tconInfoFree(cifs_sb->tcon);
2925 if ((ses) && (ses->server)) {
2926 /* save off task so we do not refer to ses later */
2927 cifsd_task = ses->server->tsk;
2928 cFYI(1, ("About to do SMBLogoff "));
2929 rc = CIFSSMBLogoff(xid, ses);
2930 if (rc == -EBUSY) {
2931 FreeXid(xid);
2932 return 0;
2933 } else if (rc == -ESHUTDOWN) {
2934 cFYI(1,("Waking up socket by sending it signal"));
2935 if(cifsd_task)
2936 send_sig(SIGKILL,cifsd_task,1);
2937 rc = 0;
2938 } /* else - we have an smb session
2939 left on this socket do not kill cifsd */
2940 } else
2941 cFYI(1, ("No session or bad tcon"));
2942 }
2943
2944 cifs_sb->tcon = NULL;
2945 if (ses) {
2946 set_current_state(TASK_INTERRUPTIBLE);
2947 schedule_timeout(HZ / 2);
2948 }
2949 if (ses)
2950 sesInfoFree(ses);
2951
2952 FreeXid(xid);
2953 return rc; /* BB check if we should always return zero here */
2954}
2955
2956int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2957 struct nls_table * nls_info)
2958{
2959 int rc = 0;
2960 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2961 int ntlmv2_flag = FALSE;
2962
2963 /* what if server changes its buffer size after dropping the session? */
2964 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2965 rc = CIFSSMBNegotiate(xid, pSesInfo);
2966 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2967 rc = CIFSSMBNegotiate(xid, pSesInfo);
2968 if(rc == -EAGAIN)
2969 rc = -EHOSTDOWN;
2970 }
2971 if(rc == 0) {
2972 spin_lock(&GlobalMid_Lock);
2973 if(pSesInfo->server->tcpStatus != CifsExiting)
2974 pSesInfo->server->tcpStatus = CifsGood;
2975 else
2976 rc = -EHOSTDOWN;
2977 spin_unlock(&GlobalMid_Lock);
2978
2979 }
2980 }
2981 if (!rc) {
2982 pSesInfo->capabilities = pSesInfo->server->capabilities;
2983 if(linuxExtEnabled == 0)
2984 pSesInfo->capabilities &= (~CAP_UNIX);
2985 pSesInfo->sequence_number = 0;
2986 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2987 pSesInfo->server->secMode,
2988 pSesInfo->server->capabilities,
2989 pSesInfo->server->timeZone));
2990 if (extended_security
2991 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2992 && (pSesInfo->server->secType == NTLMSSP)) {
2993 cFYI(1, ("New style sesssetup "));
2994 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
2995 NULL /* security blob */,
2996 0 /* blob length */,
2997 nls_info);
2998 } else if (extended_security
2999 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3000 && (pSesInfo->server->secType == RawNTLMSSP)) {
3001 cFYI(1, ("NTLMSSP sesssetup "));
3002 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3003 pSesInfo,
3004 &ntlmv2_flag,
3005 nls_info);
3006 if (!rc) {
3007 if(ntlmv2_flag) {
3008 char * v2_response;
3009 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3010 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3011 nls_info)) {
3012 rc = -ENOMEM;
3013 goto ss_err_exit;
3014 } else
3015 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3016 if(v2_response) {
3017 CalcNTLMv2_response(pSesInfo,v2_response);
3018/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
3019 kfree(v2_response);
3020 /* BB Put dummy sig in SessSetup PDU? */
3021 } else {
3022 rc = -ENOMEM;
3023 goto ss_err_exit;
3024 }
3025
3026 } else {
3027 SMBNTencrypt(pSesInfo->password,
3028 pSesInfo->server->cryptKey,
3029 ntlm_session_key);
3030
3031 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
3032 ntlm_session_key,
3033 pSesInfo->password);
3034 }
3035 /* for better security the weaker lanman hash not sent
3036 in AuthSessSetup so we no longer calculate it */
3037
3038 rc = CIFSNTLMSSPAuthSessSetup(xid,
3039 pSesInfo,
3040 ntlm_session_key,
3041 ntlmv2_flag,
3042 nls_info);
3043 }
3044 } else { /* old style NTLM 0.12 session setup */
3045 SMBNTencrypt(pSesInfo->password,
3046 pSesInfo->server->cryptKey,
3047 ntlm_session_key);
3048
3049 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
3050 ntlm_session_key, pSesInfo->password);
3051 rc = CIFSSessSetup(xid, pSesInfo,
3052 ntlm_session_key, nls_info);
3053 }
3054 if (rc) {
3055 cERROR(1,("Send error in SessSetup = %d",rc));
3056 } else {
3057 cFYI(1,("CIFS Session Established successfully"));
3058 pSesInfo->status = CifsGood;
3059 }
3060 }
3061ss_err_exit:
3062 return rc;
3063}
3064
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
new file mode 100644
index 000000000000..f54e1866f0f4
--- /dev/null
+++ b/fs/cifs/dir.c
@@ -0,0 +1,523 @@
1/*
2 * fs/cifs/dir.c
3 *
4 * vfs operations that deal with dentries
5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/slab.h>
26#include <linux/namei.h>
27#include "cifsfs.h"
28#include "cifspdu.h"
29#include "cifsglob.h"
30#include "cifsproto.h"
31#include "cifs_debug.h"
32#include "cifs_fs_sb.h"
33
34void
35renew_parental_timestamps(struct dentry *direntry)
36{
37 /* BB check if there is a way to get the kernel to do this or if we really need this */
38 do {
39 direntry->d_time = jiffies;
40 direntry = direntry->d_parent;
41 } while (!IS_ROOT(direntry));
42}
43
44/* Note: caller must free return buffer */
45char *
46build_path_from_dentry(struct dentry *direntry)
47{
48 struct dentry *temp;
49 int namelen = 0;
50 char *full_path;
51
52 if(direntry == NULL)
53 return NULL; /* not much we can do if dentry is freed and
54 we need to reopen the file after it was closed implicitly
55 when the server crashed */
56
57cifs_bp_rename_retry:
58 for (temp = direntry; !IS_ROOT(temp);) {
59 namelen += (1 + temp->d_name.len);
60 temp = temp->d_parent;
61 if(temp == NULL) {
62 cERROR(1,("corrupt dentry"));
63 return NULL;
64 }
65 }
66
67 full_path = kmalloc(namelen+1, GFP_KERNEL);
68 if(full_path == NULL)
69 return full_path;
70 full_path[namelen] = 0; /* trailing null */
71
72 for (temp = direntry; !IS_ROOT(temp);) {
73 namelen -= 1 + temp->d_name.len;
74 if (namelen < 0) {
75 break;
76 } else {
77 full_path[namelen] = '\\';
78 strncpy(full_path + namelen + 1, temp->d_name.name,
79 temp->d_name.len);
80 cFYI(0, (" name: %s ", full_path + namelen));
81 }
82 temp = temp->d_parent;
83 if(temp == NULL) {
84 cERROR(1,("corrupt dentry"));
85 kfree(full_path);
86 return NULL;
87 }
88 }
89 if (namelen != 0) {
90 cERROR(1,
91 ("We did not end path lookup where we expected namelen is %d",
92 namelen));
93 /* presumably this is only possible if we were racing with a rename
94 of one of the parent directories (we can not lock the dentries
95 above us to prevent this, but retrying should be harmless) */
96 kfree(full_path);
97 namelen = 0;
98 goto cifs_bp_rename_retry;
99 }
100
101 return full_path;
102}
103
104/* Note: caller must free return buffer */
105char *
106build_wildcard_path_from_dentry(struct dentry *direntry)
107{
108 struct dentry *temp;
109 int namelen = 0;
110 char *full_path;
111
112 if(direntry == NULL)
113 return NULL; /* not much we can do if dentry is freed and
114 we need to reopen the file after it was closed implicitly
115 when the server crashed */
116
117cifs_bwp_rename_retry:
118 for (temp = direntry; !IS_ROOT(temp);) {
119 namelen += (1 + temp->d_name.len);
120 temp = temp->d_parent;
121 if(temp == NULL) {
122 cERROR(1,("corrupt dentry"));
123 return NULL;
124 }
125 }
126
127 full_path = kmalloc(namelen+3, GFP_KERNEL);
128 if(full_path == NULL)
129 return full_path;
130
131 full_path[namelen] = '\\';
132 full_path[namelen+1] = '*';
133 full_path[namelen+2] = 0; /* trailing null */
134
135 for (temp = direntry; !IS_ROOT(temp);) {
136 namelen -= 1 + temp->d_name.len;
137 if (namelen < 0) {
138 break;
139 } else {
140 full_path[namelen] = '\\';
141 strncpy(full_path + namelen + 1, temp->d_name.name,
142 temp->d_name.len);
143 cFYI(0, (" name: %s ", full_path + namelen));
144 }
145 temp = temp->d_parent;
146 if(temp == NULL) {
147 cERROR(1,("corrupt dentry"));
148 kfree(full_path);
149 return NULL;
150 }
151 }
152 if (namelen != 0) {
153 cERROR(1,
154 ("We did not end path lookup where we expected namelen is %d",
155 namelen));
156 /* presumably this is only possible if we were racing with a rename
157 of one of the parent directories (we can not lock the dentries
158 above us to prevent this, but retrying should be harmless) */
159 kfree(full_path);
160 namelen = 0;
161 goto cifs_bwp_rename_retry;
162 }
163
164 return full_path;
165}
166
167/* Inode operations in similar order to how they appear in the Linux file fs.h */
168
169int
170cifs_create(struct inode *inode, struct dentry *direntry, int mode,
171 struct nameidata *nd)
172{
173 int rc = -ENOENT;
174 int xid;
175 int oplock = 0;
176 int desiredAccess = GENERIC_READ | GENERIC_WRITE;
177 __u16 fileHandle;
178 struct cifs_sb_info *cifs_sb;
179 struct cifsTconInfo *pTcon;
180 char *full_path = NULL;
181 FILE_ALL_INFO * buf = NULL;
182 struct inode *newinode = NULL;
183 struct cifsFileInfo * pCifsFile = NULL;
184 struct cifsInodeInfo * pCifsInode;
185 int disposition = FILE_OVERWRITE_IF;
186 int write_only = FALSE;
187
188 xid = GetXid();
189
190 cifs_sb = CIFS_SB(inode->i_sb);
191 pTcon = cifs_sb->tcon;
192
193 down(&direntry->d_sb->s_vfs_rename_sem);
194 full_path = build_path_from_dentry(direntry);
195 up(&direntry->d_sb->s_vfs_rename_sem);
196 if(full_path == NULL) {
197 FreeXid(xid);
198 return -ENOMEM;
199 }
200
201 if(nd) {
202 if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
203 desiredAccess = GENERIC_READ;
204 else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) {
205 desiredAccess = GENERIC_WRITE;
206 write_only = TRUE;
207 } else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) {
208 /* GENERIC_ALL is too much permission to request */
209 /* can cause unnecessary access denied on create */
210 /* desiredAccess = GENERIC_ALL; */
211 desiredAccess = GENERIC_READ | GENERIC_WRITE;
212 }
213
214 if((nd->intent.open.flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
215 disposition = FILE_CREATE;
216 else if((nd->intent.open.flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
217 disposition = FILE_OVERWRITE_IF;
218 else if((nd->intent.open.flags & O_CREAT) == O_CREAT)
219 disposition = FILE_OPEN_IF;
220 else {
221 cFYI(1,("Create flag not set in create function"));
222 }
223 }
224
225 /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
226 if (oplockEnabled)
227 oplock = REQ_OPLOCK;
228
229 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
230 if(buf == NULL) {
231 kfree(full_path);
232 FreeXid(xid);
233 return -ENOMEM;
234 }
235
236 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
237 desiredAccess, CREATE_NOT_DIR,
238 &fileHandle, &oplock, buf, cifs_sb->local_nls);
239 if (rc) {
240 cFYI(1, ("cifs_create returned 0x%x ", rc));
241 } else {
242 /* If Open reported that we actually created a file
243 then we now have to set the mode if possible */
244 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
245 (oplock & CIFS_CREATE_ACTION))
246 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
247 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
248 (__u64)current->euid,
249 (__u64)current->egid,
250 0 /* dev */,
251 cifs_sb->local_nls);
252 } else {
253 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
254 (__u64)-1,
255 (__u64)-1,
256 0 /* dev */,
257 cifs_sb->local_nls);
258 }
259 else {
260 /* BB implement via Windows security descriptors */
261 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
262 /* could set r/o dos attribute if mode & 0222 == 0 */
263 }
264
265 /* BB server might mask mode so we have to query for Unix case*/
266 if (pTcon->ses->capabilities & CAP_UNIX)
267 rc = cifs_get_inode_info_unix(&newinode, full_path,
268 inode->i_sb,xid);
269 else {
270 rc = cifs_get_inode_info(&newinode, full_path,
271 buf, inode->i_sb,xid);
272 if(newinode)
273 newinode->i_mode = mode;
274 }
275
276 if (rc != 0) {
277 cFYI(1,("Create worked but get_inode_info failed with rc = %d",
278 rc));
279 } else {
280 direntry->d_op = &cifs_dentry_ops;
281 d_instantiate(direntry, newinode);
282 }
283 if((nd->flags & LOOKUP_OPEN) == FALSE) {
284 /* mknod case - do not leave file open */
285 CIFSSMBClose(xid, pTcon, fileHandle);
286 } else if(newinode) {
287 pCifsFile = (struct cifsFileInfo *)
288 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
289
290 if (pCifsFile) {
291 memset((char *)pCifsFile, 0,
292 sizeof (struct cifsFileInfo));
293 pCifsFile->netfid = fileHandle;
294 pCifsFile->pid = current->tgid;
295 pCifsFile->pInode = newinode;
296 pCifsFile->invalidHandle = FALSE;
297 pCifsFile->closePend = FALSE;
298 init_MUTEX(&pCifsFile->fh_sem);
299 /* put the following in at open now */
300 /* pCifsFile->pfile = file; */
301 write_lock(&GlobalSMBSeslock);
302 list_add(&pCifsFile->tlist,&pTcon->openFileList);
303 pCifsInode = CIFS_I(newinode);
304 if(pCifsInode) {
305 /* if readable file instance put first in list*/
306 if (write_only == TRUE) {
307 list_add_tail(&pCifsFile->flist,
308 &pCifsInode->openFileList);
309 } else {
310 list_add(&pCifsFile->flist,
311 &pCifsInode->openFileList);
312 }
313 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
314 pCifsInode->clientCanCacheAll = TRUE;
315 pCifsInode->clientCanCacheRead = TRUE;
316 cFYI(1,("Exclusive Oplock granted on inode %p",
317 newinode));
318 } else if((oplock & 0xF) == OPLOCK_READ)
319 pCifsInode->clientCanCacheRead = TRUE;
320 }
321 write_unlock(&GlobalSMBSeslock);
322 }
323 }
324 }
325
326 if (buf)
327 kfree(buf);
328 if (full_path)
329 kfree(full_path);
330 FreeXid(xid);
331
332 return rc;
333}
334
335int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number)
336{
337 int rc = -EPERM;
338 int xid;
339 struct cifs_sb_info *cifs_sb;
340 struct cifsTconInfo *pTcon;
341 char *full_path = NULL;
342 struct inode * newinode = NULL;
343
344 if (!old_valid_dev(device_number))
345 return -EINVAL;
346
347 xid = GetXid();
348
349 cifs_sb = CIFS_SB(inode->i_sb);
350 pTcon = cifs_sb->tcon;
351
352 down(&direntry->d_sb->s_vfs_rename_sem);
353 full_path = build_path_from_dentry(direntry);
354 up(&direntry->d_sb->s_vfs_rename_sem);
355 if(full_path == NULL)
356 rc = -ENOMEM;
357
358 if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
359 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
360 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
361 mode,(__u64)current->euid,(__u64)current->egid,
362 device_number, cifs_sb->local_nls);
363 } else {
364 rc = CIFSSMBUnixSetPerms(xid, pTcon,
365 full_path, mode, (__u64)-1, (__u64)-1,
366 device_number, cifs_sb->local_nls);
367 }
368
369 if(!rc) {
370 rc = cifs_get_inode_info_unix(&newinode, full_path,
371 inode->i_sb,xid);
372 direntry->d_op = &cifs_dentry_ops;
373 if(rc == 0)
374 d_instantiate(direntry, newinode);
375 }
376 }
377
378 if (full_path)
379 kfree(full_path);
380 FreeXid(xid);
381
382 return rc;
383}
384
385
386struct dentry *
387cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
388{
389 int xid;
390 int rc = 0; /* to get around spurious gcc warning, set to zero here */
391 struct cifs_sb_info *cifs_sb;
392 struct cifsTconInfo *pTcon;
393 struct inode *newInode = NULL;
394 char *full_path = NULL;
395
396 xid = GetXid();
397
398 cFYI(1,
399 (" parent inode = 0x%p name is: %s and dentry = 0x%p",
400 parent_dir_inode, direntry->d_name.name, direntry));
401
402 /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
403
404 /* check whether path exists */
405
406 cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
407 pTcon = cifs_sb->tcon;
408
409 /* can not grab the rename sem here since it would
410 deadlock in the cases (beginning of sys_rename itself)
411 in which we already have the sb rename sem */
412 full_path = build_path_from_dentry(direntry);
413 if(full_path == NULL) {
414 FreeXid(xid);
415 return ERR_PTR(-ENOMEM);
416 }
417
418 if (direntry->d_inode != NULL) {
419 cFYI(1, (" non-NULL inode in lookup"));
420 } else {
421 cFYI(1, (" NULL inode in lookup"));
422 }
423 cFYI(1,
424 (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
425
426 if (pTcon->ses->capabilities & CAP_UNIX)
427 rc = cifs_get_inode_info_unix(&newInode, full_path,
428 parent_dir_inode->i_sb,xid);
429 else
430 rc = cifs_get_inode_info(&newInode, full_path, NULL,
431 parent_dir_inode->i_sb,xid);
432
433 if ((rc == 0) && (newInode != NULL)) {
434 direntry->d_op = &cifs_dentry_ops;
435 d_add(direntry, newInode);
436
437 /* since paths are not looked up by component - the parent directories are presumed to be good here */
438 renew_parental_timestamps(direntry);
439
440 } else if (rc == -ENOENT) {
441 rc = 0;
442 d_add(direntry, NULL);
443 } else {
444 cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
445 /* BB special case check for Access Denied - watch security
446 exposure of returning dir info implicitly via different rc
447 if file exists or not but no access BB */
448 }
449
450 if (full_path)
451 kfree(full_path);
452 FreeXid(xid);
453 return ERR_PTR(rc);
454}
455
456int
457cifs_dir_open(struct inode *inode, struct file *file)
458{ /* NB: currently unused since searches are opened in readdir */
459 int rc = 0;
460 int xid;
461 struct cifs_sb_info *cifs_sb;
462 struct cifsTconInfo *pTcon;
463 char *full_path = NULL;
464
465 xid = GetXid();
466
467 cifs_sb = CIFS_SB(inode->i_sb);
468 pTcon = cifs_sb->tcon;
469
470 if(file->f_dentry) {
471 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
472 full_path = build_wildcard_path_from_dentry(file->f_dentry);
473 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
474 } else {
475 FreeXid(xid);
476 return -EIO;
477 }
478
479 cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
480
481 if (full_path)
482 kfree(full_path);
483 FreeXid(xid);
484 return rc;
485}
486
487static int
488cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
489{
490 int isValid = 1;
491
492/* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
493
494 if (direntry->d_inode) {
495 if (cifs_revalidate(direntry)) {
496 /* unlock_kernel(); */
497 return 0;
498 }
499 } else {
500 cFYI(1,
501 ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
502 direntry->d_name.name, direntry));
503 }
504
505/* unlock_kernel(); */
506
507 return isValid;
508}
509
510/* static int cifs_d_delete(struct dentry *direntry)
511{
512 int rc = 0;
513
514 cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
515
516 return rc;
517} */
518
519struct dentry_operations cifs_dentry_ops = {
520 .d_revalidate = cifs_d_revalidate,
521/* d_delete: cifs_d_delete, *//* not needed except for debugging */
522 /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
523};
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
new file mode 100644
index 000000000000..9d24c40f1967
--- /dev/null
+++ b/fs/cifs/fcntl.c
@@ -0,0 +1,117 @@
1/*
2 * fs/cifs/fcntl.c
3 *
4 * vfs operations that deal with the file control API
5 *
6 * Copyright (C) International Business Machines Corp., 2003,2004
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/fcntl.h>
26#include "cifsglob.h"
27#include "cifsproto.h"
28#include "cifs_unicode.h"
29#include "cifs_debug.h"
30#include "cifsfs.h"
31
32static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
33{
34 __u32 cifs_ntfy_flags = 0;
35
36 /* No way on Linux VFS to ask to monitor xattr
37 changes (and no stream support either */
38 if(fcntl_notify_flags & DN_ACCESS) {
39 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
40 }
41 if(fcntl_notify_flags & DN_MODIFY) {
42 /* What does this mean on directories? */
43 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
44 FILE_NOTIFY_CHANGE_SIZE;
45 }
46 if(fcntl_notify_flags & DN_CREATE) {
47 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
48 FILE_NOTIFY_CHANGE_LAST_WRITE;
49 }
50 if(fcntl_notify_flags & DN_DELETE) {
51 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
52 }
53 if(fcntl_notify_flags & DN_RENAME) {
54 /* BB review this - checking various server behaviors */
55 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
56 FILE_NOTIFY_CHANGE_FILE_NAME;
57 }
58 if(fcntl_notify_flags & DN_ATTRIB) {
59 cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
60 FILE_NOTIFY_CHANGE_ATTRIBUTES;
61 }
62/* if(fcntl_notify_flags & DN_MULTISHOT) {
63 cifs_ntfy_flags |= ;
64 } */ /* BB fixme - not sure how to handle this with CIFS yet */
65
66
67 return cifs_ntfy_flags;
68}
69
70int cifs_dir_notify(struct file * file, unsigned long arg)
71{
72 int xid;
73 int rc = -EINVAL;
74 int oplock = FALSE;
75 struct cifs_sb_info *cifs_sb;
76 struct cifsTconInfo *pTcon;
77 char *full_path = NULL;
78 __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
79 __u16 netfid;
80
81 xid = GetXid();
82 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
83 pTcon = cifs_sb->tcon;
84
85 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
86 full_path = build_path_from_dentry(file->f_dentry);
87 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
88
89 if(full_path == NULL) {
90 rc = -ENOMEM;
91 } else {
92 cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */
93 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
94 GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
95 &netfid, &oplock,NULL, cifs_sb->local_nls);
96 /* BB fixme - add this handle to a notify handle list */
97 if(rc) {
98 cERROR(1,("Could not open directory for notify")); /* BB remove BB */
99 } else {
100 filter = convert_to_cifs_notify_flags(arg);
101 if(filter != 0) {
102 rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid,
103 filter, cifs_sb->local_nls);
104 } else {
105 rc = -EINVAL;
106 }
107 /* BB add code to close file eventually (at unmount
108 it would close automatically but may be a way
109 to do it easily when inode freed or when
110 notify info is cleared/changed */
111 cERROR(1,("notify rc %d",rc));
112 }
113 }
114
115 FreeXid(xid);
116 return rc;
117}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
new file mode 100644
index 000000000000..dcab7cf1b53b
--- /dev/null
+++ b/fs/cifs/file.c
@@ -0,0 +1,1675 @@
1/*
2 * fs/cifs/file.c
3 *
4 * vfs operations that deal with files
5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/fcntl.h>
26#include <linux/pagemap.h>
27#include <linux/pagevec.h>
28#include <linux/smp_lock.h>
29#include <asm/div64.h>
30#include "cifsfs.h"
31#include "cifspdu.h"
32#include "cifsglob.h"
33#include "cifsproto.h"
34#include "cifs_unicode.h"
35#include "cifs_debug.h"
36#include "cifs_fs_sb.h"
37
38static inline struct cifsFileInfo *cifs_init_private(
39 struct cifsFileInfo *private_data, struct inode *inode,
40 struct file *file, __u16 netfid)
41{
42 memset(private_data, 0, sizeof(struct cifsFileInfo));
43 private_data->netfid = netfid;
44 private_data->pid = current->tgid;
45 init_MUTEX(&private_data->fh_sem);
46 private_data->pfile = file; /* needed for writepage */
47 private_data->pInode = inode;
48 private_data->invalidHandle = FALSE;
49 private_data->closePend = FALSE;
50
51 return private_data;
52}
53
54static inline int cifs_convert_flags(unsigned int flags)
55{
56 if ((flags & O_ACCMODE) == O_RDONLY)
57 return GENERIC_READ;
58 else if ((flags & O_ACCMODE) == O_WRONLY)
59 return GENERIC_WRITE;
60 else if ((flags & O_ACCMODE) == O_RDWR) {
61 /* GENERIC_ALL is too much permission to request
62 can cause unnecessary access denied on create */
63 /* return GENERIC_ALL; */
64 return (GENERIC_READ | GENERIC_WRITE);
65 }
66
67 return 0x20197;
68}
69
70static inline int cifs_get_disposition(unsigned int flags)
71{
72 if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
73 return FILE_CREATE;
74 else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
75 return FILE_OVERWRITE_IF;
76 else if ((flags & O_CREAT) == O_CREAT)
77 return FILE_OPEN_IF;
78 else
79 return FILE_OPEN;
80}
81
82/* all arguments to this function must be checked for validity in caller */
83static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
84 struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
85 struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
86 char *full_path, int xid)
87{
88 struct timespec temp;
89 int rc;
90
91 /* want handles we can use to read with first
92 in the list so we do not have to walk the
93 list to search for one in prepare_write */
94 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
95 list_add_tail(&pCifsFile->flist,
96 &pCifsInode->openFileList);
97 } else {
98 list_add(&pCifsFile->flist,
99 &pCifsInode->openFileList);
100 }
101 write_unlock(&GlobalSMBSeslock);
102 write_unlock(&file->f_owner.lock);
103 if (pCifsInode->clientCanCacheRead) {
104 /* we have the inode open somewhere else
105 no need to discard cache data */
106 goto client_can_cache;
107 }
108
109 /* BB need same check in cifs_create too? */
110 /* if not oplocked, invalidate inode pages if mtime or file
111 size changed */
112 temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
113 if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) &&
114 (file->f_dentry->d_inode->i_size ==
115 (loff_t)le64_to_cpu(buf->EndOfFile))) {
116 cFYI(1, ("inode unchanged on server"));
117 } else {
118 if (file->f_dentry->d_inode->i_mapping) {
119 /* BB no need to lock inode until after invalidate
120 since namei code should already have it locked? */
121 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
122 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
123 }
124 cFYI(1, ("invalidating remote inode since open detected it "
125 "changed"));
126 invalidate_remote_inode(file->f_dentry->d_inode);
127 }
128
129client_can_cache:
130 if (pTcon->ses->capabilities & CAP_UNIX)
131 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
132 full_path, inode->i_sb, xid);
133 else
134 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
135 full_path, buf, inode->i_sb, xid);
136
137 if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
138 pCifsInode->clientCanCacheAll = TRUE;
139 pCifsInode->clientCanCacheRead = TRUE;
140 cFYI(1, ("Exclusive Oplock granted on inode %p",
141 file->f_dentry->d_inode));
142 } else if ((*oplock & 0xF) == OPLOCK_READ)
143 pCifsInode->clientCanCacheRead = TRUE;
144
145 return rc;
146}
147
148int cifs_open(struct inode *inode, struct file *file)
149{
150 int rc = -EACCES;
151 int xid, oplock;
152 struct cifs_sb_info *cifs_sb;
153 struct cifsTconInfo *pTcon;
154 struct cifsFileInfo *pCifsFile;
155 struct cifsInodeInfo *pCifsInode;
156 struct list_head *tmp;
157 char *full_path = NULL;
158 int desiredAccess;
159 int disposition;
160 __u16 netfid;
161 FILE_ALL_INFO *buf = NULL;
162
163 xid = GetXid();
164
165 cifs_sb = CIFS_SB(inode->i_sb);
166 pTcon = cifs_sb->tcon;
167
168 if (file->f_flags & O_CREAT) {
169 /* search inode for this file and fill in file->private_data */
170 pCifsInode = CIFS_I(file->f_dentry->d_inode);
171 read_lock(&GlobalSMBSeslock);
172 list_for_each(tmp, &pCifsInode->openFileList) {
173 pCifsFile = list_entry(tmp, struct cifsFileInfo,
174 flist);
175 if ((pCifsFile->pfile == NULL) &&
176 (pCifsFile->pid == current->tgid)) {
177 /* mode set in cifs_create */
178
179 /* needed for writepage */
180 pCifsFile->pfile = file;
181
182 file->private_data = pCifsFile;
183 break;
184 }
185 }
186 read_unlock(&GlobalSMBSeslock);
187 if (file->private_data != NULL) {
188 rc = 0;
189 FreeXid(xid);
190 return rc;
191 } else {
192 if (file->f_flags & O_EXCL)
193 cERROR(1, ("could not find file instance for "
194 "new file %p ", file));
195 }
196 }
197
198 down(&inode->i_sb->s_vfs_rename_sem);
199 full_path = build_path_from_dentry(file->f_dentry);
200 up(&inode->i_sb->s_vfs_rename_sem);
201 if (full_path == NULL) {
202 FreeXid(xid);
203 return -ENOMEM;
204 }
205
206 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
207 inode, file->f_flags, full_path));
208 desiredAccess = cifs_convert_flags(file->f_flags);
209
210/*********************************************************************
211 * open flag mapping table:
212 *
213 * POSIX Flag CIFS Disposition
214 * ---------- ----------------
215 * O_CREAT FILE_OPEN_IF
216 * O_CREAT | O_EXCL FILE_CREATE
217 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
218 * O_TRUNC FILE_OVERWRITE
219 * none of the above FILE_OPEN
220 *
221 * Note that there is not a direct match between disposition
222 * FILE_SUPERSEDE (ie create whether or not file exists although
223 * O_CREAT | O_TRUNC is similar but truncates the existing
224 * file rather than creating a new file as FILE_SUPERSEDE does
225 * (which uses the attributes / metadata passed in on open call)
226 *?
227 *? O_SYNC is a reasonable match to CIFS writethrough flag
228 *? and the read write flags match reasonably. O_LARGEFILE
229 *? is irrelevant because largefile support is always used
230 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
231 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
232 *********************************************************************/
233
234 disposition = cifs_get_disposition(file->f_flags);
235
236 if (oplockEnabled)
237 oplock = REQ_OPLOCK;
238 else
239 oplock = FALSE;
240
241 /* BB pass O_SYNC flag through on file attributes .. BB */
242
243 /* Also refresh inode by passing in file_info buf returned by SMBOpen
244 and calling get_inode_info with returned buf (at least helps
245 non-Unix server case) */
246
247 /* BB we can not do this if this is the second open of a file
248 and the first handle has writebehind data, we might be
249 able to simply do a filemap_fdatawrite/filemap_fdatawait first */
250 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
251 if (!buf) {
252 rc = -ENOMEM;
253 goto out;
254 }
255 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
256 CREATE_NOT_DIR, &netfid, &oplock, buf,
257 cifs_sb->local_nls);
258 if (rc) {
259 cFYI(1, ("cifs_open returned 0x%x ", rc));
260 goto out;
261 }
262 file->private_data =
263 kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
264 if (file->private_data == NULL) {
265 rc = -ENOMEM;
266 goto out;
267 }
268 pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
269 write_lock(&file->f_owner.lock);
270 write_lock(&GlobalSMBSeslock);
271 list_add(&pCifsFile->tlist, &pTcon->openFileList);
272
273 pCifsInode = CIFS_I(file->f_dentry->d_inode);
274 if (pCifsInode) {
275 rc = cifs_open_inode_helper(inode, file, pCifsInode,
276 pCifsFile, pTcon,
277 &oplock, buf, full_path, xid);
278 } else {
279 write_unlock(&GlobalSMBSeslock);
280 write_unlock(&file->f_owner.lock);
281 }
282
283 if (oplock & CIFS_CREATE_ACTION) {
284 /* time to set mode which we can not set earlier due to
285 problems creating new read-only files */
286 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
287 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
288 inode->i_mode,
289 (__u64)-1, (__u64)-1, 0 /* dev */,
290 cifs_sb->local_nls);
291 } else {
292 /* BB implement via Windows security descriptors eg
293 CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
294 -1, -1, local_nls);
295 in the meantime could set r/o dos attribute when
296 perms are eg: mode & 0222 == 0 */
297 }
298 }
299
300out:
301 kfree(buf);
302 kfree(full_path);
303 FreeXid(xid);
304 return rc;
305}
306
307/* Try to reaquire byte range locks that were released when session */
308/* to server was lost */
309static int cifs_relock_file(struct cifsFileInfo *cifsFile)
310{
311 int rc = 0;
312
313/* BB list all locks open on this file and relock */
314
315 return rc;
316}
317
318static int cifs_reopen_file(struct inode *inode, struct file *file,
319 int can_flush)
320{
321 int rc = -EACCES;
322 int xid, oplock;
323 struct cifs_sb_info *cifs_sb;
324 struct cifsTconInfo *pTcon;
325 struct cifsFileInfo *pCifsFile;
326 struct cifsInodeInfo *pCifsInode;
327 char *full_path = NULL;
328 int desiredAccess;
329 int disposition = FILE_OPEN;
330 __u16 netfid;
331
332 if (inode == NULL)
333 return -EBADF;
334 if (file->private_data) {
335 pCifsFile = (struct cifsFileInfo *)file->private_data;
336 } else
337 return -EBADF;
338
339 xid = GetXid();
340 down(&pCifsFile->fh_sem);
341 if (pCifsFile->invalidHandle == FALSE) {
342 up(&pCifsFile->fh_sem);
343 FreeXid(xid);
344 return 0;
345 }
346
347 if (file->f_dentry == NULL) {
348 up(&pCifsFile->fh_sem);
349 cFYI(1, ("failed file reopen, no valid name if dentry freed"));
350 FreeXid(xid);
351 return -EBADF;
352 }
353 cifs_sb = CIFS_SB(inode->i_sb);
354 pTcon = cifs_sb->tcon;
355/* can not grab rename sem here because various ops, including
356 those that already have the rename sem can end up causing writepage
357 to get called and if the server was down that means we end up here,
358 and we can never tell if the caller already has the rename_sem */
359 full_path = build_path_from_dentry(file->f_dentry);
360 if (full_path == NULL) {
361 up(&pCifsFile->fh_sem);
362 FreeXid(xid);
363 return -ENOMEM;
364 }
365
366 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
367 inode, file->f_flags,full_path));
368 desiredAccess = cifs_convert_flags(file->f_flags);
369
370 if (oplockEnabled)
371 oplock = REQ_OPLOCK;
372 else
373 oplock = FALSE;
374
375 /* Can not refresh inode by passing in file_info buf to be returned
376 by SMBOpen and then calling get_inode_info with returned buf
377 since file might have write behind data that needs to be flushed
378 and server version of file size can be stale. If we knew for sure
379 that inode was not dirty locally we could do this */
380
381/* buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
382 if (buf == 0) {
383 up(&pCifsFile->fh_sem);
384 kfree(full_path);
385 FreeXid(xid);
386 return -ENOMEM;
387 } */
388 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
389 CREATE_NOT_DIR, &netfid, &oplock, NULL,
390 cifs_sb->local_nls);
391 if (rc) {
392 up(&pCifsFile->fh_sem);
393 cFYI(1, ("cifs_open returned 0x%x ", rc));
394 cFYI(1, ("oplock: %d ", oplock));
395 } else {
396 pCifsFile->netfid = netfid;
397 pCifsFile->invalidHandle = FALSE;
398 up(&pCifsFile->fh_sem);
399 pCifsInode = CIFS_I(inode);
400 if (pCifsInode) {
401 if (can_flush) {
402 filemap_fdatawrite(inode->i_mapping);
403 filemap_fdatawait(inode->i_mapping);
404 /* temporarily disable caching while we
405 go to server to get inode info */
406 pCifsInode->clientCanCacheAll = FALSE;
407 pCifsInode->clientCanCacheRead = FALSE;
408 if (pTcon->ses->capabilities & CAP_UNIX)
409 rc = cifs_get_inode_info_unix(&inode,
410 full_path, inode->i_sb, xid);
411 else
412 rc = cifs_get_inode_info(&inode,
413 full_path, NULL, inode->i_sb,
414 xid);
415 } /* else we are writing out data to server already
416 and could deadlock if we tried to flush data, and
417 since we do not know if we have data that would
418 invalidate the current end of file on the server
419 we can not go to the server to get the new inod
420 info */
421 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
422 pCifsInode->clientCanCacheAll = TRUE;
423 pCifsInode->clientCanCacheRead = TRUE;
424 cFYI(1, ("Exclusive Oplock granted on inode %p",
425 file->f_dentry->d_inode));
426 } else if ((oplock & 0xF) == OPLOCK_READ) {
427 pCifsInode->clientCanCacheRead = TRUE;
428 pCifsInode->clientCanCacheAll = FALSE;
429 } else {
430 pCifsInode->clientCanCacheRead = FALSE;
431 pCifsInode->clientCanCacheAll = FALSE;
432 }
433 cifs_relock_file(pCifsFile);
434 }
435 }
436
437 kfree(full_path);
438 FreeXid(xid);
439 return rc;
440}
441
442int cifs_close(struct inode *inode, struct file *file)
443{
444 int rc = 0;
445 int xid;
446 struct cifs_sb_info *cifs_sb;
447 struct cifsTconInfo *pTcon;
448 struct cifsFileInfo *pSMBFile =
449 (struct cifsFileInfo *)file->private_data;
450
451 xid = GetXid();
452
453 cifs_sb = CIFS_SB(inode->i_sb);
454 pTcon = cifs_sb->tcon;
455 if (pSMBFile) {
456 pSMBFile->closePend = TRUE;
457 write_lock(&file->f_owner.lock);
458 if (pTcon) {
459 /* no sense reconnecting to close a file that is
460 already closed */
461 if (pTcon->tidStatus != CifsNeedReconnect) {
462 write_unlock(&file->f_owner.lock);
463 rc = CIFSSMBClose(xid, pTcon,
464 pSMBFile->netfid);
465 write_lock(&file->f_owner.lock);
466 }
467 }
468 list_del(&pSMBFile->flist);
469 list_del(&pSMBFile->tlist);
470 write_unlock(&file->f_owner.lock);
471 kfree(pSMBFile->search_resume_name);
472 kfree(file->private_data);
473 file->private_data = NULL;
474 } else
475 rc = -EBADF;
476
477 if (list_empty(&(CIFS_I(inode)->openFileList))) {
478 cFYI(1, ("closing last open instance for inode %p", inode));
479 /* if the file is not open we do not know if we can cache info
480 on this inode, much less write behind and read ahead */
481 CIFS_I(inode)->clientCanCacheRead = FALSE;
482 CIFS_I(inode)->clientCanCacheAll = FALSE;
483 }
484 if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
485 rc = CIFS_I(inode)->write_behind_rc;
486 FreeXid(xid);
487 return rc;
488}
489
490int cifs_closedir(struct inode *inode, struct file *file)
491{
492 int rc = 0;
493 int xid;
494 struct cifsFileInfo *pCFileStruct =
495 (struct cifsFileInfo *)file->private_data;
496 char *ptmp;
497
498 cFYI(1, ("Closedir inode = 0x%p with ", inode));
499
500 xid = GetXid();
501
502 if (pCFileStruct) {
503 struct cifsTconInfo *pTcon;
504 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
505
506 pTcon = cifs_sb->tcon;
507
508 cFYI(1, ("Freeing private data in close dir"));
509 if (pCFileStruct->srch_inf.endOfSearch == FALSE) {
510 pCFileStruct->invalidHandle = TRUE;
511 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
512 cFYI(1, ("Closing uncompleted readdir with rc %d",
513 rc));
514 /* not much we can do if it fails anyway, ignore rc */
515 rc = 0;
516 }
517 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
518 if (ptmp) {
519 /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
520 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
521 cifs_buf_release(ptmp);
522 }
523 ptmp = pCFileStruct->search_resume_name;
524 if (ptmp) {
525 /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
526 pCFileStruct->search_resume_name = NULL;
527 kfree(ptmp);
528 }
529 kfree(file->private_data);
530 file->private_data = NULL;
531 }
532 /* BB can we lock the filestruct while this is going on? */
533 FreeXid(xid);
534 return rc;
535}
536
537int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
538{
539 int rc, xid;
540 __u32 lockType = LOCKING_ANDX_LARGE_FILES;
541 __u32 numLock = 0;
542 __u32 numUnlock = 0;
543 __u64 length;
544 int wait_flag = FALSE;
545 struct cifs_sb_info *cifs_sb;
546 struct cifsTconInfo *pTcon;
547
548 length = 1 + pfLock->fl_end - pfLock->fl_start;
549 rc = -EACCES;
550 xid = GetXid();
551
552 cFYI(1, ("Lock parm: 0x%x flockflags: "
553 "0x%x flocktype: 0x%x start: %lld end: %lld",
554 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
555 pfLock->fl_end));
556
557 if (pfLock->fl_flags & FL_POSIX)
558 cFYI(1, ("Posix "));
559 if (pfLock->fl_flags & FL_FLOCK)
560 cFYI(1, ("Flock "));
561 if (pfLock->fl_flags & FL_SLEEP) {
562 cFYI(1, ("Blocking lock "));
563 wait_flag = TRUE;
564 }
565 if (pfLock->fl_flags & FL_ACCESS)
566 cFYI(1, ("Process suspended by mandatory locking - "
567 "not implemented yet "));
568 if (pfLock->fl_flags & FL_LEASE)
569 cFYI(1, ("Lease on file - not implemented yet"));
570 if (pfLock->fl_flags &
571 (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
572 cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
573
574 if (pfLock->fl_type == F_WRLCK) {
575 cFYI(1, ("F_WRLCK "));
576 numLock = 1;
577 } else if (pfLock->fl_type == F_UNLCK) {
578 cFYI(1, ("F_UNLCK "));
579 numUnlock = 1;
580 } else if (pfLock->fl_type == F_RDLCK) {
581 cFYI(1, ("F_RDLCK "));
582 lockType |= LOCKING_ANDX_SHARED_LOCK;
583 numLock = 1;
584 } else if (pfLock->fl_type == F_EXLCK) {
585 cFYI(1, ("F_EXLCK "));
586 numLock = 1;
587 } else if (pfLock->fl_type == F_SHLCK) {
588 cFYI(1, ("F_SHLCK "));
589 lockType |= LOCKING_ANDX_SHARED_LOCK;
590 numLock = 1;
591 } else
592 cFYI(1, ("Unknown type of lock "));
593
594 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
595 pTcon = cifs_sb->tcon;
596
597 if (file->private_data == NULL) {
598 FreeXid(xid);
599 return -EBADF;
600 }
601
602 if (IS_GETLK(cmd)) {
603 rc = CIFSSMBLock(xid, pTcon,
604 ((struct cifsFileInfo *)file->
605 private_data)->netfid,
606 length,
607 pfLock->fl_start, 0, 1, lockType,
608 0 /* wait flag */ );
609 if (rc == 0) {
610 rc = CIFSSMBLock(xid, pTcon,
611 ((struct cifsFileInfo *) file->
612 private_data)->netfid,
613 length,
614 pfLock->fl_start, 1 /* numUnlock */ ,
615 0 /* numLock */ , lockType,
616 0 /* wait flag */ );
617 pfLock->fl_type = F_UNLCK;
618 if (rc != 0)
619 cERROR(1, ("Error unlocking previously locked "
620 "range %d during test of lock ",
621 rc));
622 rc = 0;
623
624 } else {
625 /* if rc == ERR_SHARING_VIOLATION ? */
626 rc = 0; /* do not change lock type to unlock
627 since range in use */
628 }
629
630 FreeXid(xid);
631 return rc;
632 }
633
634 rc = CIFSSMBLock(xid, pTcon,
635 ((struct cifsFileInfo *) file->private_data)->
636 netfid, length,
637 pfLock->fl_start, numUnlock, numLock, lockType,
638 wait_flag);
639 if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
640 posix_lock_file_wait(file, pfLock);
641 FreeXid(xid);
642 return rc;
643}
644
645ssize_t cifs_user_write(struct file *file, const char __user *write_data,
646 size_t write_size, loff_t *poffset)
647{
648 int rc = 0;
649 unsigned int bytes_written = 0;
650 unsigned int total_written;
651 struct cifs_sb_info *cifs_sb;
652 struct cifsTconInfo *pTcon;
653 int xid, long_op;
654 struct cifsFileInfo *open_file;
655
656 if (file->f_dentry == NULL)
657 return -EBADF;
658
659 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
660 if (cifs_sb == NULL)
661 return -EBADF;
662
663 pTcon = cifs_sb->tcon;
664
665 /* cFYI(1,
666 (" write %d bytes to offset %lld of %s", write_size,
667 *poffset, file->f_dentry->d_name.name)); */
668
669 if (file->private_data == NULL)
670 return -EBADF;
671 else
672 open_file = (struct cifsFileInfo *) file->private_data;
673
674 xid = GetXid();
675 if (file->f_dentry->d_inode == NULL) {
676 FreeXid(xid);
677 return -EBADF;
678 }
679
680 if (*poffset > file->f_dentry->d_inode->i_size)
681 long_op = 2; /* writes past end of file can take a long time */
682 else
683 long_op = 1;
684
685 for (total_written = 0; write_size > total_written;
686 total_written += bytes_written) {
687 rc = -EAGAIN;
688 while (rc == -EAGAIN) {
689 if (file->private_data == NULL) {
690 /* file has been closed on us */
691 FreeXid(xid);
692 /* if we have gotten here we have written some data
693 and blocked, and the file has been freed on us while
694 we blocked so return what we managed to write */
695 return total_written;
696 }
697 if (open_file->closePend) {
698 FreeXid(xid);
699 if (total_written)
700 return total_written;
701 else
702 return -EBADF;
703 }
704 if (open_file->invalidHandle) {
705 if ((file->f_dentry == NULL) ||
706 (file->f_dentry->d_inode == NULL)) {
707 FreeXid(xid);
708 return total_written;
709 }
710 /* we could deadlock if we called
711 filemap_fdatawait from here so tell
712 reopen_file not to flush data to server
713 now */
714 rc = cifs_reopen_file(file->f_dentry->d_inode,
715 file, FALSE);
716 if (rc != 0)
717 break;
718 }
719
720 rc = CIFSSMBWrite(xid, pTcon,
721 open_file->netfid,
722 min_t(const int, cifs_sb->wsize,
723 write_size - total_written),
724 *poffset, &bytes_written,
725 NULL, write_data + total_written, long_op);
726 }
727 if (rc || (bytes_written == 0)) {
728 if (total_written)
729 break;
730 else {
731 FreeXid(xid);
732 return rc;
733 }
734 } else
735 *poffset += bytes_written;
736 long_op = FALSE; /* subsequent writes fast -
737 15 seconds is plenty */
738 }
739
740#ifdef CONFIG_CIFS_STATS
741 if (total_written > 0) {
742 atomic_inc(&pTcon->num_writes);
743 spin_lock(&pTcon->stat_lock);
744 pTcon->bytes_written += total_written;
745 spin_unlock(&pTcon->stat_lock);
746 }
747#endif
748
749 /* since the write may have blocked check these pointers again */
750 if (file->f_dentry) {
751 if (file->f_dentry->d_inode) {
752 struct inode *inode = file->f_dentry->d_inode;
753 inode->i_ctime = inode->i_mtime =
754 current_fs_time(inode->i_sb);
755 if (total_written > 0) {
756 if (*poffset > file->f_dentry->d_inode->i_size)
757 i_size_write(file->f_dentry->d_inode,
758 *poffset);
759 }
760 mark_inode_dirty_sync(file->f_dentry->d_inode);
761 }
762 }
763 FreeXid(xid);
764 return total_written;
765}
766
767static ssize_t cifs_write(struct file *file, const char *write_data,
768 size_t write_size, loff_t *poffset)
769{
770 int rc = 0;
771 unsigned int bytes_written = 0;
772 unsigned int total_written;
773 struct cifs_sb_info *cifs_sb;
774 struct cifsTconInfo *pTcon;
775 int xid, long_op;
776 struct cifsFileInfo *open_file;
777
778 if (file->f_dentry == NULL)
779 return -EBADF;
780
781 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
782 if (cifs_sb == NULL)
783 return -EBADF;
784
785 pTcon = cifs_sb->tcon;
786
787 /* cFYI(1,
788 (" write %d bytes to offset %lld of %s", write_size,
789 *poffset, file->f_dentry->d_name.name)); */
790
791 if (file->private_data == NULL)
792 return -EBADF;
793 else
794 open_file = (struct cifsFileInfo *)file->private_data;
795
796 xid = GetXid();
797 if (file->f_dentry->d_inode == NULL) {
798 FreeXid(xid);
799 return -EBADF;
800 }
801
802 if (*poffset > file->f_dentry->d_inode->i_size)
803 long_op = 2; /* writes past end of file can take a long time */
804 else
805 long_op = 1;
806
807 for (total_written = 0; write_size > total_written;
808 total_written += bytes_written) {
809 rc = -EAGAIN;
810 while (rc == -EAGAIN) {
811 if (file->private_data == NULL) {
812 /* file has been closed on us */
813 FreeXid(xid);
814 /* if we have gotten here we have written some data
815 and blocked, and the file has been freed on us
816 while we blocked so return what we managed to
817 write */
818 return total_written;
819 }
820 if (open_file->closePend) {
821 FreeXid(xid);
822 if (total_written)
823 return total_written;
824 else
825 return -EBADF;
826 }
827 if (open_file->invalidHandle) {
828 if ((file->f_dentry == NULL) ||
829 (file->f_dentry->d_inode == NULL)) {
830 FreeXid(xid);
831 return total_written;
832 }
833 /* we could deadlock if we called
834 filemap_fdatawait from here so tell
835 reopen_file not to flush data to
836 server now */
837 rc = cifs_reopen_file(file->f_dentry->d_inode,
838 file, FALSE);
839 if (rc != 0)
840 break;
841 }
842
843 rc = CIFSSMBWrite(xid, pTcon,
844 open_file->netfid,
845 min_t(const int, cifs_sb->wsize,
846 write_size - total_written),
847 *poffset, &bytes_written,
848 write_data + total_written, NULL, long_op);
849 }
850 if (rc || (bytes_written == 0)) {
851 if (total_written)
852 break;
853 else {
854 FreeXid(xid);
855 return rc;
856 }
857 } else
858 *poffset += bytes_written;
859 long_op = FALSE; /* subsequent writes fast -
860 15 seconds is plenty */
861 }
862
863#ifdef CONFIG_CIFS_STATS
864 if (total_written > 0) {
865 atomic_inc(&pTcon->num_writes);
866 spin_lock(&pTcon->stat_lock);
867 pTcon->bytes_written += total_written;
868 spin_unlock(&pTcon->stat_lock);
869 }
870#endif
871
872 /* since the write may have blocked check these pointers again */
873 if (file->f_dentry) {
874 if (file->f_dentry->d_inode) {
875 file->f_dentry->d_inode->i_ctime =
876 file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
877 if (total_written > 0) {
878 if (*poffset > file->f_dentry->d_inode->i_size)
879 i_size_write(file->f_dentry->d_inode,
880 *poffset);
881 }
882 mark_inode_dirty_sync(file->f_dentry->d_inode);
883 }
884 }
885 FreeXid(xid);
886 return total_written;
887}
888
889static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
890{
891 struct address_space *mapping = page->mapping;
892 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
893 char *write_data;
894 int rc = -EFAULT;
895 int bytes_written = 0;
896 struct cifs_sb_info *cifs_sb;
897 struct cifsTconInfo *pTcon;
898 struct inode *inode;
899 struct cifsInodeInfo *cifsInode;
900 struct cifsFileInfo *open_file = NULL;
901 struct list_head *tmp;
902 struct list_head *tmp1;
903
904 if (!mapping || !mapping->host)
905 return -EFAULT;
906
907 inode = page->mapping->host;
908 cifs_sb = CIFS_SB(inode->i_sb);
909 pTcon = cifs_sb->tcon;
910
911 offset += (loff_t)from;
912 write_data = kmap(page);
913 write_data += from;
914
915 if ((to > PAGE_CACHE_SIZE) || (from > to)) {
916 kunmap(page);
917 return -EIO;
918 }
919
920 /* racing with truncate? */
921 if (offset > mapping->host->i_size) {
922 kunmap(page);
923 return 0; /* don't care */
924 }
925
926 /* check to make sure that we are not extending the file */
927 if (mapping->host->i_size - offset < (loff_t)to)
928 to = (unsigned)(mapping->host->i_size - offset);
929
930 cifsInode = CIFS_I(mapping->host);
931 read_lock(&GlobalSMBSeslock);
932 /* BB we should start at the end */
933 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
934 open_file = list_entry(tmp, struct cifsFileInfo, flist);
935 if (open_file->closePend)
936 continue;
937 /* We check if file is open for writing first */
938 if ((open_file->pfile) &&
939 ((open_file->pfile->f_flags & O_RDWR) ||
940 (open_file->pfile->f_flags & O_WRONLY))) {
941 read_unlock(&GlobalSMBSeslock);
942 bytes_written = cifs_write(open_file->pfile,
943 write_data, to-from,
944 &offset);
945 read_lock(&GlobalSMBSeslock);
946 /* Does mm or vfs already set times? */
947 inode->i_atime =
948 inode->i_mtime = current_fs_time(inode->i_sb);
949 if ((bytes_written > 0) && (offset)) {
950 rc = 0;
951 } else if (bytes_written < 0) {
952 if (rc == -EBADF) {
953 /* have seen a case in which kernel seemed to
954 have closed/freed a file even with writes
955 active so we might as well see if there are
956 other file structs to try for the same
957 inode before giving up */
958 continue;
959 } else
960 rc = bytes_written;
961 }
962 break; /* now that we found a valid file handle and
963 tried to write to it we are done, no sense
964 continuing to loop looking for another */
965 }
966 if (tmp->next == NULL) {
967 cFYI(1, ("File instance %p removed", tmp));
968 break;
969 }
970 }
971 read_unlock(&GlobalSMBSeslock);
972 if (open_file == NULL) {
973 cFYI(1, ("No writeable filehandles for inode"));
974 rc = -EIO;
975 }
976
977 kunmap(page);
978 return rc;
979}
980
981#if 0
982static int cifs_writepages(struct address_space *mapping,
983 struct writeback_control *wbc)
984{
985 int rc = -EFAULT;
986 int xid;
987
988 xid = GetXid();
989
990 /* Find contiguous pages then iterate through repeating
991 call 16K write then Setpageuptodate or if LARGE_WRITE_X
992 support then send larger writes via kevec so as to eliminate
993 a memcpy */
994 FreeXid(xid);
995 return rc;
996}
997#endif
998
999static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1000{
1001 int rc = -EFAULT;
1002 int xid;
1003
1004 xid = GetXid();
1005/* BB add check for wbc flags */
1006 page_cache_get(page);
1007 if (!PageUptodate(page)) {
1008 cFYI(1, ("ppw - page not up to date"));
1009 }
1010
1011 rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1012 SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1013 unlock_page(page);
1014 page_cache_release(page);
1015 FreeXid(xid);
1016 return rc;
1017}
1018
1019static int cifs_commit_write(struct file *file, struct page *page,
1020 unsigned offset, unsigned to)
1021{
1022 int xid;
1023 int rc = 0;
1024 struct inode *inode = page->mapping->host;
1025 loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1026 char *page_data;
1027
1028 xid = GetXid();
1029 cFYI(1, ("commit write for page %p up to position %lld for %d",
1030 page, position, to));
1031 if (position > inode->i_size) {
1032 i_size_write(inode, position);
1033 /* if (file->private_data == NULL) {
1034 rc = -EBADF;
1035 } else {
1036 open_file = (struct cifsFileInfo *)file->private_data;
1037 cifs_sb = CIFS_SB(inode->i_sb);
1038 rc = -EAGAIN;
1039 while (rc == -EAGAIN) {
1040 if ((open_file->invalidHandle) &&
1041 (!open_file->closePend)) {
1042 rc = cifs_reopen_file(
1043 file->f_dentry->d_inode, file);
1044 if (rc != 0)
1045 break;
1046 }
1047 if (!open_file->closePend) {
1048 rc = CIFSSMBSetFileSize(xid,
1049 cifs_sb->tcon, position,
1050 open_file->netfid,
1051 open_file->pid, FALSE);
1052 } else {
1053 rc = -EBADF;
1054 break;
1055 }
1056 }
1057 cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1058 } */
1059 }
1060 if (!PageUptodate(page)) {
1061 position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1062 /* can not rely on (or let) writepage write this data */
1063 if (to < offset) {
1064 cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1065 offset, to));
1066 FreeXid(xid);
1067 return rc;
1068 }
1069 /* this is probably better than directly calling
1070 partialpage_write since in this function the file handle is
1071 known which we might as well leverage */
1072 /* BB check if anything else missing out of ppw
1073 such as updating last write time */
1074 page_data = kmap(page);
1075 rc = cifs_write(file, page_data + offset, to-offset,
1076 &position);
1077 if (rc > 0)
1078 rc = 0;
1079 /* else if (rc < 0) should we set writebehind rc? */
1080 kunmap(page);
1081 } else {
1082 set_page_dirty(page);
1083 }
1084
1085 FreeXid(xid);
1086 return rc;
1087}
1088
1089int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1090{
1091 int xid;
1092 int rc = 0;
1093 struct inode *inode = file->f_dentry->d_inode;
1094
1095 xid = GetXid();
1096
1097 cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
1098 dentry->d_name.name, datasync));
1099
1100 rc = filemap_fdatawrite(inode->i_mapping);
1101 if (rc == 0)
1102 CIFS_I(inode)->write_behind_rc = 0;
1103 FreeXid(xid);
1104 return rc;
1105}
1106
1107/* static int cifs_sync_page(struct page *page)
1108{
1109 struct address_space *mapping;
1110 struct inode *inode;
1111 unsigned long index = page->index;
1112 unsigned int rpages = 0;
1113 int rc = 0;
1114
1115 cFYI(1, ("sync page %p",page));
1116 mapping = page->mapping;
1117 if (!mapping)
1118 return 0;
1119 inode = mapping->host;
1120 if (!inode)
1121 return 0; */
1122
1123/* fill in rpages then
1124 result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1125
1126/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1127
1128 if (rc < 0)
1129 return rc;
1130 return 0;
1131} */
1132
1133/*
1134 * As file closes, flush all cached write data for this inode checking
1135 * for write behind errors.
1136 */
1137int cifs_flush(struct file *file)
1138{
1139 struct inode * inode = file->f_dentry->d_inode;
1140 int rc = 0;
1141
1142 /* Rather than do the steps manually:
1143 lock the inode for writing
1144 loop through pages looking for write behind data (dirty pages)
1145 coalesce into contiguous 16K (or smaller) chunks to write to server
1146 send to server (prefer in parallel)
1147 deal with writebehind errors
1148 unlock inode for writing
1149 filemapfdatawrite appears easier for the time being */
1150
1151 rc = filemap_fdatawrite(inode->i_mapping);
1152 if (!rc) /* reset wb rc if we were able to write out dirty pages */
1153 CIFS_I(inode)->write_behind_rc = 0;
1154
1155 cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1156
1157 return rc;
1158}
1159
1160ssize_t cifs_user_read(struct file *file, char __user *read_data,
1161 size_t read_size, loff_t *poffset)
1162{
1163 int rc = -EACCES;
1164 unsigned int bytes_read = 0;
1165 unsigned int total_read = 0;
1166 unsigned int current_read_size;
1167 struct cifs_sb_info *cifs_sb;
1168 struct cifsTconInfo *pTcon;
1169 int xid;
1170 struct cifsFileInfo *open_file;
1171 char *smb_read_data;
1172 char __user *current_offset;
1173 struct smb_com_read_rsp *pSMBr;
1174
1175 xid = GetXid();
1176 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1177 pTcon = cifs_sb->tcon;
1178
1179 if (file->private_data == NULL) {
1180 FreeXid(xid);
1181 return -EBADF;
1182 }
1183 open_file = (struct cifsFileInfo *)file->private_data;
1184
1185 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1186 cFYI(1, ("attempting read on write only file instance"));
1187 }
1188 for (total_read = 0, current_offset = read_data;
1189 read_size > total_read;
1190 total_read += bytes_read, current_offset += bytes_read) {
1191 current_read_size = min_t(const int, read_size - total_read,
1192 cifs_sb->rsize);
1193 rc = -EAGAIN;
1194 smb_read_data = NULL;
1195 while (rc == -EAGAIN) {
1196 if ((open_file->invalidHandle) &&
1197 (!open_file->closePend)) {
1198 rc = cifs_reopen_file(file->f_dentry->d_inode,
1199 file, TRUE);
1200 if (rc != 0)
1201 break;
1202 }
1203
1204 rc = CIFSSMBRead(xid, pTcon,
1205 open_file->netfid,
1206 current_read_size, *poffset,
1207 &bytes_read, &smb_read_data);
1208
1209 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1210 if (copy_to_user(current_offset,
1211 smb_read_data + 4 /* RFC1001 hdr */
1212 + le16_to_cpu(pSMBr->DataOffset),
1213 bytes_read)) {
1214 rc = -EFAULT;
1215 FreeXid(xid);
1216 return rc;
1217 }
1218 if (smb_read_data) {
1219 cifs_buf_release(smb_read_data);
1220 smb_read_data = NULL;
1221 }
1222 }
1223 if (rc || (bytes_read == 0)) {
1224 if (total_read) {
1225 break;
1226 } else {
1227 FreeXid(xid);
1228 return rc;
1229 }
1230 } else {
1231#ifdef CONFIG_CIFS_STATS
1232 atomic_inc(&pTcon->num_reads);
1233 spin_lock(&pTcon->stat_lock);
1234 pTcon->bytes_read += total_read;
1235 spin_unlock(&pTcon->stat_lock);
1236#endif
1237 *poffset += bytes_read;
1238 }
1239 }
1240 FreeXid(xid);
1241 return total_read;
1242}
1243
1244
1245static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1246 loff_t *poffset)
1247{
1248 int rc = -EACCES;
1249 unsigned int bytes_read = 0;
1250 unsigned int total_read;
1251 unsigned int current_read_size;
1252 struct cifs_sb_info *cifs_sb;
1253 struct cifsTconInfo *pTcon;
1254 int xid;
1255 char *current_offset;
1256 struct cifsFileInfo *open_file;
1257
1258 xid = GetXid();
1259 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1260 pTcon = cifs_sb->tcon;
1261
1262 if (file->private_data == NULL) {
1263 FreeXid(xid);
1264 return -EBADF;
1265 }
1266 open_file = (struct cifsFileInfo *)file->private_data;
1267
1268 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1269 cFYI(1, ("attempting read on write only file instance"));
1270
1271 for (total_read = 0, current_offset = read_data;
1272 read_size > total_read;
1273 total_read += bytes_read, current_offset += bytes_read) {
1274 current_read_size = min_t(const int, read_size - total_read,
1275 cifs_sb->rsize);
1276 rc = -EAGAIN;
1277 while (rc == -EAGAIN) {
1278 if ((open_file->invalidHandle) &&
1279 (!open_file->closePend)) {
1280 rc = cifs_reopen_file(file->f_dentry->d_inode,
1281 file, TRUE);
1282 if (rc != 0)
1283 break;
1284 }
1285
1286 rc = CIFSSMBRead(xid, pTcon,
1287 open_file->netfid,
1288 current_read_size, *poffset,
1289 &bytes_read, &current_offset);
1290 }
1291 if (rc || (bytes_read == 0)) {
1292 if (total_read) {
1293 break;
1294 } else {
1295 FreeXid(xid);
1296 return rc;
1297 }
1298 } else {
1299#ifdef CONFIG_CIFS_STATS
1300 atomic_inc(&pTcon->num_reads);
1301 spin_lock(&pTcon->stat_lock);
1302 pTcon->bytes_read += total_read;
1303 spin_unlock(&pTcon->stat_lock);
1304#endif
1305 *poffset += bytes_read;
1306 }
1307 }
1308 FreeXid(xid);
1309 return total_read;
1310}
1311
1312int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1313{
1314 struct dentry *dentry = file->f_dentry;
1315 int rc, xid;
1316
1317 xid = GetXid();
1318 rc = cifs_revalidate(dentry);
1319 if (rc) {
1320 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1321 FreeXid(xid);
1322 return rc;
1323 }
1324 rc = generic_file_mmap(file, vma);
1325 FreeXid(xid);
1326 return rc;
1327}
1328
1329
1330static void cifs_copy_cache_pages(struct address_space *mapping,
1331 struct list_head *pages, int bytes_read, char *data,
1332 struct pagevec *plru_pvec)
1333{
1334 struct page *page;
1335 char *target;
1336
1337 while (bytes_read > 0) {
1338 if (list_empty(pages))
1339 break;
1340
1341 page = list_entry(pages->prev, struct page, lru);
1342 list_del(&page->lru);
1343
1344 if (add_to_page_cache(page, mapping, page->index,
1345 GFP_KERNEL)) {
1346 page_cache_release(page);
1347 cFYI(1, ("Add page cache failed"));
1348 continue;
1349 }
1350
1351 target = kmap_atomic(page,KM_USER0);
1352
1353 if (PAGE_CACHE_SIZE > bytes_read) {
1354 memcpy(target, data, bytes_read);
1355 /* zero the tail end of this partial page */
1356 memset(target + bytes_read, 0,
1357 PAGE_CACHE_SIZE - bytes_read);
1358 bytes_read = 0;
1359 } else {
1360 memcpy(target, data, PAGE_CACHE_SIZE);
1361 bytes_read -= PAGE_CACHE_SIZE;
1362 }
1363 kunmap_atomic(target, KM_USER0);
1364
1365 flush_dcache_page(page);
1366 SetPageUptodate(page);
1367 unlock_page(page);
1368 if (!pagevec_add(plru_pvec, page))
1369 __pagevec_lru_add(plru_pvec);
1370 data += PAGE_CACHE_SIZE;
1371 }
1372 return;
1373}
1374
1375static int cifs_readpages(struct file *file, struct address_space *mapping,
1376 struct list_head *page_list, unsigned num_pages)
1377{
1378 int rc = -EACCES;
1379 int xid;
1380 loff_t offset;
1381 struct page *page;
1382 struct cifs_sb_info *cifs_sb;
1383 struct cifsTconInfo *pTcon;
1384 int bytes_read = 0;
1385 unsigned int read_size,i;
1386 char *smb_read_data = NULL;
1387 struct smb_com_read_rsp *pSMBr;
1388 struct pagevec lru_pvec;
1389 struct cifsFileInfo *open_file;
1390
1391 xid = GetXid();
1392 if (file->private_data == NULL) {
1393 FreeXid(xid);
1394 return -EBADF;
1395 }
1396 open_file = (struct cifsFileInfo *)file->private_data;
1397 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1398 pTcon = cifs_sb->tcon;
1399
1400 pagevec_init(&lru_pvec, 0);
1401
1402 for (i = 0; i < num_pages; ) {
1403 unsigned contig_pages;
1404 struct page *tmp_page;
1405 unsigned long expected_index;
1406
1407 if (list_empty(page_list))
1408 break;
1409
1410 page = list_entry(page_list->prev, struct page, lru);
1411 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1412
1413 /* count adjacent pages that we will read into */
1414 contig_pages = 0;
1415 expected_index =
1416 list_entry(page_list->prev, struct page, lru)->index;
1417 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1418 if (tmp_page->index == expected_index) {
1419 contig_pages++;
1420 expected_index++;
1421 } else
1422 break;
1423 }
1424 if (contig_pages + i > num_pages)
1425 contig_pages = num_pages - i;
1426
1427 /* for reads over a certain size could initiate async
1428 read ahead */
1429
1430 read_size = contig_pages * PAGE_CACHE_SIZE;
1431 /* Read size needs to be in multiples of one page */
1432 read_size = min_t(const unsigned int, read_size,
1433 cifs_sb->rsize & PAGE_CACHE_MASK);
1434
1435 rc = -EAGAIN;
1436 while (rc == -EAGAIN) {
1437 if ((open_file->invalidHandle) &&
1438 (!open_file->closePend)) {
1439 rc = cifs_reopen_file(file->f_dentry->d_inode,
1440 file, TRUE);
1441 if (rc != 0)
1442 break;
1443 }
1444
1445 rc = CIFSSMBRead(xid, pTcon,
1446 open_file->netfid,
1447 read_size, offset,
1448 &bytes_read, &smb_read_data);
1449 /* BB need to check return code here */
1450 if (rc== -EAGAIN) {
1451 if (smb_read_data) {
1452 cifs_buf_release(smb_read_data);
1453 smb_read_data = NULL;
1454 }
1455 }
1456 }
1457 if ((rc < 0) || (smb_read_data == NULL)) {
1458 cFYI(1, ("Read error in readpages: %d", rc));
1459 /* clean up remaing pages off list */
1460 while (!list_empty(page_list) && (i < num_pages)) {
1461 page = list_entry(page_list->prev, struct page,
1462 lru);
1463 list_del(&page->lru);
1464 page_cache_release(page);
1465 }
1466 break;
1467 } else if (bytes_read > 0) {
1468 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1469 cifs_copy_cache_pages(mapping, page_list, bytes_read,
1470 smb_read_data + 4 /* RFC1001 hdr */ +
1471 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1472
1473 i += bytes_read >> PAGE_CACHE_SHIFT;
1474#ifdef CONFIG_CIFS_STATS
1475 atomic_inc(&pTcon->num_reads);
1476 spin_lock(&pTcon->stat_lock);
1477 pTcon->bytes_read += bytes_read;
1478 spin_unlock(&pTcon->stat_lock);
1479#endif
1480 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1481 i++; /* account for partial page */
1482
1483 /* server copy of file can have smaller size
1484 than client */
1485 /* BB do we need to verify this common case ?
1486 this case is ok - if we are at server EOF
1487 we will hit it on next read */
1488
1489 /* while (!list_empty(page_list) && (i < num_pages)) {
1490 page = list_entry(page_list->prev,
1491 struct page, list);
1492 list_del(&page->list);
1493 page_cache_release(page);
1494 }
1495 break; */
1496 }
1497 } else {
1498 cFYI(1, ("No bytes read (%d) at offset %lld . "
1499 "Cleaning remaining pages from readahead list",
1500 bytes_read, offset));
1501 /* BB turn off caching and do new lookup on
1502 file size at server? */
1503 while (!list_empty(page_list) && (i < num_pages)) {
1504 page = list_entry(page_list->prev, struct page,
1505 lru);
1506 list_del(&page->lru);
1507
1508 /* BB removeme - replace with zero of page? */
1509 page_cache_release(page);
1510 }
1511 break;
1512 }
1513 if (smb_read_data) {
1514 cifs_buf_release(smb_read_data);
1515 smb_read_data = NULL;
1516 }
1517 bytes_read = 0;
1518 }
1519
1520 pagevec_lru_add(&lru_pvec);
1521
1522/* need to free smb_read_data buf before exit */
1523 if (smb_read_data) {
1524 cifs_buf_release(smb_read_data);
1525 smb_read_data = NULL;
1526 }
1527
1528 FreeXid(xid);
1529 return rc;
1530}
1531
1532static int cifs_readpage_worker(struct file *file, struct page *page,
1533 loff_t *poffset)
1534{
1535 char *read_data;
1536 int rc;
1537
1538 page_cache_get(page);
1539 read_data = kmap(page);
1540 /* for reads over a certain size could initiate async read ahead */
1541
1542 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1543
1544 if (rc < 0)
1545 goto io_error;
1546 else
1547 cFYI(1, ("Bytes read %d ",rc));
1548
1549 file->f_dentry->d_inode->i_atime =
1550 current_fs_time(file->f_dentry->d_inode->i_sb);
1551
1552 if (PAGE_CACHE_SIZE > rc)
1553 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1554
1555 flush_dcache_page(page);
1556 SetPageUptodate(page);
1557 rc = 0;
1558
1559io_error:
1560 kunmap(page);
1561 page_cache_release(page);
1562 return rc;
1563}
1564
1565static int cifs_readpage(struct file *file, struct page *page)
1566{
1567 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1568 int rc = -EACCES;
1569 int xid;
1570
1571 xid = GetXid();
1572
1573 if (file->private_data == NULL) {
1574 FreeXid(xid);
1575 return -EBADF;
1576 }
1577
1578 cFYI(1, ("readpage %p at offset %d 0x%x\n",
1579 page, (int)offset, (int)offset));
1580
1581 rc = cifs_readpage_worker(file, page, &offset);
1582
1583 unlock_page(page);
1584
1585 FreeXid(xid);
1586 return rc;
1587}
1588
1589/* We do not want to update the file size from server for inodes
1590 open for write - to avoid races with writepage extending
1591 the file - in the future we could consider allowing
1592 refreshing the inode only on increases in the file size
1593 but this is tricky to do without racing with writebehind
1594 page caching in the current Linux kernel design */
1595int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1596{
1597 struct list_head *tmp;
1598 struct list_head *tmp1;
1599 struct cifsFileInfo *open_file = NULL;
1600 int rc = TRUE;
1601
1602 if (cifsInode == NULL)
1603 return rc;
1604
1605 read_lock(&GlobalSMBSeslock);
1606 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
1607 open_file = list_entry(tmp, struct cifsFileInfo, flist);
1608 if (open_file == NULL)
1609 break;
1610 if (open_file->closePend)
1611 continue;
1612 /* We check if file is open for writing,
1613 BB we could supplement this with a check to see if file size
1614 changes have been flushed to server - ie inode metadata dirty */
1615 if ((open_file->pfile) &&
1616 ((open_file->pfile->f_flags & O_RDWR) ||
1617 (open_file->pfile->f_flags & O_WRONLY))) {
1618 rc = FALSE;
1619 break;
1620 }
1621 if (tmp->next == NULL) {
1622 cFYI(1, ("File instance %p removed", tmp));
1623 break;
1624 }
1625 }
1626 read_unlock(&GlobalSMBSeslock);
1627 return rc;
1628}
1629
1630
1631static int cifs_prepare_write(struct file *file, struct page *page,
1632 unsigned from, unsigned to)
1633{
1634 int rc = 0;
1635 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1636 cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1637 if (!PageUptodate(page)) {
1638 /* if (to - from != PAGE_CACHE_SIZE) {
1639 void *kaddr = kmap_atomic(page, KM_USER0);
1640 memset(kaddr, 0, from);
1641 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1642 flush_dcache_page(page);
1643 kunmap_atomic(kaddr, KM_USER0);
1644 } */
1645 /* If we are writing a full page it will be up to date,
1646 no need to read from the server */
1647 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1648 SetPageUptodate(page);
1649
1650 /* might as well read a page, it is fast enough */
1651 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1652 rc = cifs_readpage_worker(file, page, &offset);
1653 } else {
1654 /* should we try using another file handle if there is one -
1655 how would we lock it to prevent close of that handle
1656 racing with this read?
1657 In any case this will be written out by commit_write */
1658 }
1659 }
1660
1661 /* BB should we pass any errors back?
1662 e.g. if we do not have read access to the file */
1663 return 0;
1664}
1665
1666struct address_space_operations cifs_addr_ops = {
1667 .readpage = cifs_readpage,
1668 .readpages = cifs_readpages,
1669 .writepage = cifs_writepage,
1670 .prepare_write = cifs_prepare_write,
1671 .commit_write = cifs_commit_write,
1672 .set_page_dirty = __set_page_dirty_nobuffers,
1673 /* .sync_page = cifs_sync_page, */
1674 /* .direct_IO = */
1675};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
new file mode 100644
index 000000000000..d73b0aa86775
--- /dev/null
+++ b/fs/cifs/inode.c
@@ -0,0 +1,1096 @@
1/*
2 * fs/cifs/inode.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
22#include <linux/buffer_head.h>
23#include <linux/stat.h>
24#include <linux/pagemap.h>
25#include <asm/div64.h>
26#include "cifsfs.h"
27#include "cifspdu.h"
28#include "cifsglob.h"
29#include "cifsproto.h"
30#include "cifs_debug.h"
31#include "cifs_fs_sb.h"
32
33int cifs_get_inode_info_unix(struct inode **pinode,
34 const unsigned char *search_path, struct super_block *sb, int xid)
35{
36 int rc = 0;
37 FILE_UNIX_BASIC_INFO findData;
38 struct cifsTconInfo *pTcon;
39 struct inode *inode;
40 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
41 char *tmp_path;
42
43 pTcon = cifs_sb->tcon;
44 cFYI(1, (" Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls);
48/* dump_mem("\nUnixQPathInfo return data", &findData,
49 sizeof(findData)); */
50 if (rc) {
51 if (rc == -EREMOTE) {
52 tmp_path =
53 kmalloc(strnlen(pTcon->treeName,
54 MAX_TREE_SIZE + 1) +
55 strnlen(search_path, MAX_PATHCONF) + 1,
56 GFP_KERNEL);
57 if (tmp_path == NULL) {
58 return -ENOMEM;
59 }
60 /* have to skip first of the double backslash of
61 UNC name */
62 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
63 strncat(tmp_path, search_path, MAX_PATHCONF);
64 rc = connect_to_dfs_path(xid, pTcon->ses,
65 /* treename + */ tmp_path,
66 cifs_sb->local_nls);
67 kfree(tmp_path);
68
69 /* BB fix up inode etc. */
70 } else if (rc) {
71 return rc;
72 }
73 } else {
74 struct cifsInodeInfo *cifsInfo;
75 __u32 type = le32_to_cpu(findData.Type);
76 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
77 __u64 end_of_file = le64_to_cpu(findData.EndOfFile);
78
79 /* get new inode */
80 if (*pinode == NULL) {
81 *pinode = new_inode(sb);
82 if(*pinode == NULL)
83 return -ENOMEM;
84 /* Is an i_ino of zero legal? */
85 /* Are there sanity checks we can use to ensure that
86 the server is really filling in that field? */
87 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
88 (*pinode)->i_ino =
89 (unsigned long)findData.UniqueId;
90 } /* note ino incremented to unique num in new_inode */
91 insert_inode_hash(*pinode);
92 }
93
94 inode = *pinode;
95 cifsInfo = CIFS_I(inode);
96
97 cFYI(1, (" Old time %ld ", cifsInfo->time));
98 cifsInfo->time = jiffies;
99 cFYI(1, (" New time %ld ", cifsInfo->time));
100 /* this is ok to set on every inode revalidate */
101 atomic_set(&cifsInfo->inUse,1);
102
103 inode->i_atime =
104 cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
105 inode->i_mtime =
106 cifs_NTtimeToUnix(le64_to_cpu
107 (findData.LastModificationTime));
108 inode->i_ctime =
109 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
110 inode->i_mode = le64_to_cpu(findData.Permissions);
111 if (type == UNIX_FILE) {
112 inode->i_mode |= S_IFREG;
113 } else if (type == UNIX_SYMLINK) {
114 inode->i_mode |= S_IFLNK;
115 } else if (type == UNIX_DIR) {
116 inode->i_mode |= S_IFDIR;
117 } else if (type == UNIX_CHARDEV) {
118 inode->i_mode |= S_IFCHR;
119 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
120 le64_to_cpu(findData.DevMinor) & MINORMASK);
121 } else if (type == UNIX_BLOCKDEV) {
122 inode->i_mode |= S_IFBLK;
123 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
124 le64_to_cpu(findData.DevMinor) & MINORMASK);
125 } else if (type == UNIX_FIFO) {
126 inode->i_mode |= S_IFIFO;
127 } else if (type == UNIX_SOCKET) {
128 inode->i_mode |= S_IFSOCK;
129 }
130 inode->i_uid = le64_to_cpu(findData.Uid);
131 inode->i_gid = le64_to_cpu(findData.Gid);
132 inode->i_nlink = le64_to_cpu(findData.Nlinks);
133
134 if(is_size_safe_to_change(cifsInfo)) {
135 /* can not safely change the file size here if the
136 client is writing to it due to potential races */
137
138 i_size_write(inode, end_of_file);
139
140 /* blksize needs to be multiple of two. So safer to default to
141 blksize and blkbits set in superblock so 2**blkbits and blksize
142 will match rather than setting to:
143 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
144
145 /* This seems incredibly stupid but it turns out that i_blocks
146 is not related to (i_size / i_blksize), instead 512 byte size
147 is required for calculating num blocks */
148
149 /* 512 bytes (2**9) is the fake blocksize that must be used */
150 /* for this calculation */
151 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
152 }
153
154 if (num_of_bytes < end_of_file)
155 cFYI(1, ("allocation size less than end of file "));
156 cFYI(1,
157 ("Size %ld and blocks %ld",
158 (unsigned long) inode->i_size, inode->i_blocks));
159 if (S_ISREG(inode->i_mode)) {
160 cFYI(1, (" File inode "));
161 inode->i_op = &cifs_file_inode_ops;
162 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
163 inode->i_fop = &cifs_file_direct_ops;
164 else
165 inode->i_fop = &cifs_file_ops;
166 inode->i_data.a_ops = &cifs_addr_ops;
167 } else if (S_ISDIR(inode->i_mode)) {
168 cFYI(1, (" Directory inode"));
169 inode->i_op = &cifs_dir_inode_ops;
170 inode->i_fop = &cifs_dir_ops;
171 } else if (S_ISLNK(inode->i_mode)) {
172 cFYI(1, (" Symbolic Link inode "));
173 inode->i_op = &cifs_symlink_inode_ops;
174 /* tmp_inode->i_fop = */ /* do not need to set to anything */
175 } else {
176 cFYI(1, (" Init special inode "));
177 init_special_inode(inode, inode->i_mode,
178 inode->i_rdev);
179 }
180 }
181 return rc;
182}
183
184int cifs_get_inode_info(struct inode **pinode,
185 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
186 struct super_block *sb, int xid)
187{
188 int rc = 0;
189 struct cifsTconInfo *pTcon;
190 struct inode *inode;
191 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
192 char *tmp_path;
193 char *buf = NULL;
194
195 pTcon = cifs_sb->tcon;
196 cFYI(1,("Getting info on %s ", search_path));
197
198 if((pfindData == NULL) && (*pinode != NULL)) {
199 if(CIFS_I(*pinode)->clientCanCacheRead) {
200 cFYI(1,("No need to revalidate cached inode sizes"));
201 return rc;
202 }
203 }
204
205 /* if file info not passed in then get it from server */
206 if(pfindData == NULL) {
207 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
208 if(buf == NULL)
209 return -ENOMEM;
210 pfindData = (FILE_ALL_INFO *)buf;
211 /* could do find first instead but this returns more info */
212 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
213 cifs_sb->local_nls);
214 }
215 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
216 if (rc) {
217 if (rc == -EREMOTE) {
218 tmp_path =
219 kmalloc(strnlen
220 (pTcon->treeName,
221 MAX_TREE_SIZE + 1) +
222 strnlen(search_path, MAX_PATHCONF) + 1,
223 GFP_KERNEL);
224 if (tmp_path == NULL) {
225 kfree(buf);
226 return -ENOMEM;
227 }
228
229 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
230 strncat(tmp_path, search_path, MAX_PATHCONF);
231 rc = connect_to_dfs_path(xid, pTcon->ses,
232 /* treename + */ tmp_path,
233 cifs_sb->local_nls);
234 kfree(tmp_path);
235 /* BB fix up inode etc. */
236 } else if (rc) {
237 kfree(buf);
238 return rc;
239 }
240 } else {
241 struct cifsInodeInfo *cifsInfo;
242 __u32 attr = le32_to_cpu(pfindData->Attributes);
243
244 /* get new inode */
245 if (*pinode == NULL) {
246 *pinode = new_inode(sb);
247 if (*pinode == NULL)
248 return -ENOMEM;
249 /* Is an i_ino of zero legal? Can we use that to check
250 if the server supports returning inode numbers? Are
251 there other sanity checks we can use to ensure that
252 the server is really filling in that field? */
253
254 /* We can not use the IndexNumber field by default from
255 Windows or Samba (in ALL_INFO buf) but we can request
256 it explicitly. It may not be unique presumably if
257 the server has multiple devices mounted under one
258 share */
259
260 /* There may be higher info levels that work but are
261 there Windows server or network appliances for which
262 IndexNumber field is not guaranteed unique? */
263
264#ifdef CONFIG_CIFS_EXPERIMENTAL
265 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
266 int rc1 = 0;
267 __u64 inode_num;
268
269 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
270 search_path, &inode_num,
271 cifs_sb->local_nls);
272 if(rc1) {
273 cFYI(1,("GetSrvInodeNum rc %d", rc1));
274 /* BB EOPNOSUPP disable SERVER_INUM? */
275 } else /* do we need cast or hash to ino? */
276 (*pinode)->i_ino = inode_num;
277 } /* else ino incremented to unique num in new_inode*/
278#endif /* CIFS_EXPERIMENTAL */
279 insert_inode_hash(*pinode);
280 }
281 inode = *pinode;
282 cifsInfo = CIFS_I(inode);
283 cifsInfo->cifsAttrs = attr;
284 cFYI(1, (" Old time %ld ", cifsInfo->time));
285 cifsInfo->time = jiffies;
286 cFYI(1, (" New time %ld ", cifsInfo->time));
287
288 /* blksize needs to be multiple of two. So safer to default to
289 blksize and blkbits set in superblock so 2**blkbits and blksize
290 will match rather than setting to:
291 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
292
293 /* Linux can not store file creation time unfortunately so we ignore it */
294 inode->i_atime =
295 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
296 inode->i_mtime =
297 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
298 inode->i_ctime =
299 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
300 cFYI(0, (" Attributes came in as 0x%x ", attr));
301
302 /* set default mode. will override for dirs below */
303 if (atomic_read(&cifsInfo->inUse) == 0)
304 /* new inode, can safely set these fields */
305 inode->i_mode = cifs_sb->mnt_file_mode;
306
307/* if (attr & ATTR_REPARSE) */
308 /* We no longer handle these as symlinks because we could not
309 follow them due to the absolute path with drive letter */
310 if (attr & ATTR_DIRECTORY) {
311 /* override default perms since we do not do byte range locking
312 on dirs */
313 inode->i_mode = cifs_sb->mnt_dir_mode;
314 inode->i_mode |= S_IFDIR;
315 } else {
316 inode->i_mode |= S_IFREG;
317 /* treat the dos attribute of read-only as read-only
318 mode e.g. 555 */
319 if (cifsInfo->cifsAttrs & ATTR_READONLY)
320 inode->i_mode &= ~(S_IWUGO);
321 /* BB add code here -
322 validate if device or weird share or device type? */
323 }
324 if (is_size_safe_to_change(cifsInfo)) {
325 /* can not safely change the file size here if the
326 client is writing to it due to potential races */
327 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
328
329 /* 512 bytes (2**9) is the fake blocksize that must be
330 used for this calculation */
331 inode->i_blocks = (512 - 1 + le64_to_cpu(
332 pfindData->AllocationSize)) >> 9;
333 }
334
335 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
336
337 /* BB fill in uid and gid here? with help from winbind?
338 or retrieve from NTFS stream extended attribute */
339 if (atomic_read(&cifsInfo->inUse) == 0) {
340 inode->i_uid = cifs_sb->mnt_uid;
341 inode->i_gid = cifs_sb->mnt_gid;
342 /* set so we do not keep refreshing these fields with
343 bad data after user has changed them in memory */
344 atomic_set(&cifsInfo->inUse,1);
345 }
346
347 if (S_ISREG(inode->i_mode)) {
348 cFYI(1, (" File inode "));
349 inode->i_op = &cifs_file_inode_ops;
350 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
351 inode->i_fop = &cifs_file_direct_ops;
352 else
353 inode->i_fop = &cifs_file_ops;
354 inode->i_data.a_ops = &cifs_addr_ops;
355 } else if (S_ISDIR(inode->i_mode)) {
356 cFYI(1, (" Directory inode "));
357 inode->i_op = &cifs_dir_inode_ops;
358 inode->i_fop = &cifs_dir_ops;
359 } else if (S_ISLNK(inode->i_mode)) {
360 cFYI(1, (" Symbolic Link inode "));
361 inode->i_op = &cifs_symlink_inode_ops;
362 } else {
363 init_special_inode(inode, inode->i_mode,
364 inode->i_rdev);
365 }
366 }
367 kfree(buf);
368 return rc;
369}
370
371/* gets root inode */
372void cifs_read_inode(struct inode *inode)
373{
374 int xid;
375 struct cifs_sb_info *cifs_sb;
376
377 cifs_sb = CIFS_SB(inode->i_sb);
378 xid = GetXid();
379 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
380 cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
381 else
382 cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
383 /* can not call macro FreeXid here since in a void func */
384 _FreeXid(xid);
385}
386
387int cifs_unlink(struct inode *inode, struct dentry *direntry)
388{
389 int rc = 0;
390 int xid;
391 struct cifs_sb_info *cifs_sb;
392 struct cifsTconInfo *pTcon;
393 char *full_path = NULL;
394 struct cifsInodeInfo *cifsInode;
395 FILE_BASIC_INFO *pinfo_buf;
396
397 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
398
399 xid = GetXid();
400
401 cifs_sb = CIFS_SB(inode->i_sb);
402 pTcon = cifs_sb->tcon;
403
404 /* Unlink can be called from rename so we can not grab the sem here
405 since we deadlock otherwise */
406/* down(&direntry->d_sb->s_vfs_rename_sem);*/
407 full_path = build_path_from_dentry(direntry);
408/* up(&direntry->d_sb->s_vfs_rename_sem);*/
409 if (full_path == NULL) {
410 FreeXid(xid);
411 return -ENOMEM;
412 }
413 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
414
415 if (!rc) {
416 direntry->d_inode->i_nlink--;
417 } else if (rc == -ENOENT) {
418 d_drop(direntry);
419 } else if (rc == -ETXTBSY) {
420 int oplock = FALSE;
421 __u16 netfid;
422
423 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
424 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
425 &netfid, &oplock, NULL, cifs_sb->local_nls);
426 if (rc==0) {
427 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
428 cifs_sb->local_nls);
429 CIFSSMBClose(xid, pTcon, netfid);
430 direntry->d_inode->i_nlink--;
431 }
432 } else if (rc == -EACCES) {
433 /* try only if r/o attribute set in local lookup data? */
434 pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
435 if (pinfo_buf) {
436 memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
437 /* ATTRS set to normal clears r/o bit */
438 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
439 if (!(pTcon->ses->flags & CIFS_SES_NT4))
440 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
441 pinfo_buf,
442 cifs_sb->local_nls);
443 else
444 rc = -EOPNOTSUPP;
445
446 if (rc == -EOPNOTSUPP) {
447 int oplock = FALSE;
448 __u16 netfid;
449 /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
450 full_path,
451 (__u16)ATTR_NORMAL,
452 cifs_sb->local_nls);
453 For some strange reason it seems that NT4 eats the
454 old setattr call without actually setting the
455 attributes so on to the third attempted workaround
456 */
457
458 /* BB could scan to see if we already have it open
459 and pass in pid of opener to function */
460 rc = CIFSSMBOpen(xid, pTcon, full_path,
461 FILE_OPEN, SYNCHRONIZE |
462 FILE_WRITE_ATTRIBUTES, 0,
463 &netfid, &oplock, NULL,
464 cifs_sb->local_nls);
465 if (rc==0) {
466 rc = CIFSSMBSetFileTimes(xid, pTcon,
467 pinfo_buf,
468 netfid);
469 CIFSSMBClose(xid, pTcon, netfid);
470 }
471 }
472 kfree(pinfo_buf);
473 }
474 if (rc==0) {
475 rc = CIFSSMBDelFile(xid, pTcon, full_path,
476 cifs_sb->local_nls);
477 if (!rc) {
478 direntry->d_inode->i_nlink--;
479 } else if (rc == -ETXTBSY) {
480 int oplock = FALSE;
481 __u16 netfid;
482
483 rc = CIFSSMBOpen(xid, pTcon, full_path,
484 FILE_OPEN, DELETE,
485 CREATE_NOT_DIR |
486 CREATE_DELETE_ON_CLOSE,
487 &netfid, &oplock, NULL,
488 cifs_sb->local_nls);
489 if (rc==0) {
490 CIFSSMBRenameOpenFile(xid, pTcon,
491 netfid, NULL,
492 cifs_sb->local_nls);
493 CIFSSMBClose(xid, pTcon, netfid);
494 direntry->d_inode->i_nlink--;
495 }
496 /* BB if rc = -ETXTBUSY goto the rename logic BB */
497 }
498 }
499 }
500 cifsInode = CIFS_I(direntry->d_inode);
501 cifsInode->time = 0; /* will force revalidate to get info when
502 needed */
503 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
504 current_fs_time(inode->i_sb);
505 cifsInode = CIFS_I(inode);
506 cifsInode->time = 0; /* force revalidate of dir as well */
507
508 kfree(full_path);
509 FreeXid(xid);
510 return rc;
511}
512
513int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
514{
515 int rc = 0;
516 int xid;
517 struct cifs_sb_info *cifs_sb;
518 struct cifsTconInfo *pTcon;
519 char *full_path = NULL;
520 struct inode *newinode = NULL;
521
522 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
523
524 xid = GetXid();
525
526 cifs_sb = CIFS_SB(inode->i_sb);
527 pTcon = cifs_sb->tcon;
528
529 down(&inode->i_sb->s_vfs_rename_sem);
530 full_path = build_path_from_dentry(direntry);
531 up(&inode->i_sb->s_vfs_rename_sem);
532 if (full_path == NULL) {
533 FreeXid(xid);
534 return -ENOMEM;
535 }
536 /* BB add setting the equivalent of mode via CreateX w/ACLs */
537 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
538 if (rc) {
539 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
540 d_drop(direntry);
541 } else {
542 inode->i_nlink++;
543 if (pTcon->ses->capabilities & CAP_UNIX)
544 rc = cifs_get_inode_info_unix(&newinode, full_path,
545 inode->i_sb,xid);
546 else
547 rc = cifs_get_inode_info(&newinode, full_path, NULL,
548 inode->i_sb,xid);
549
550 direntry->d_op = &cifs_dentry_ops;
551 d_instantiate(direntry, newinode);
552 if (direntry->d_inode)
553 direntry->d_inode->i_nlink = 2;
554 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
555 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
556 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
557 mode,
558 (__u64)current->euid,
559 (__u64)current->egid,
560 0 /* dev_t */,
561 cifs_sb->local_nls);
562 } else {
563 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
564 mode, (__u64)-1,
565 (__u64)-1, 0 /* dev_t */,
566 cifs_sb->local_nls);
567 }
568 else {
569 /* BB to be implemented via Windows secrty descriptors
570 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
571 -1, -1, local_nls); */
572 }
573 }
574 kfree(full_path);
575 FreeXid(xid);
576 return rc;
577}
578
579int cifs_rmdir(struct inode *inode, struct dentry *direntry)
580{
581 int rc = 0;
582 int xid;
583 struct cifs_sb_info *cifs_sb;
584 struct cifsTconInfo *pTcon;
585 char *full_path = NULL;
586 struct cifsInodeInfo *cifsInode;
587
588 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
589
590 xid = GetXid();
591
592 cifs_sb = CIFS_SB(inode->i_sb);
593 pTcon = cifs_sb->tcon;
594
595 down(&inode->i_sb->s_vfs_rename_sem);
596 full_path = build_path_from_dentry(direntry);
597 up(&inode->i_sb->s_vfs_rename_sem);
598 if (full_path == NULL) {
599 FreeXid(xid);
600 return -ENOMEM;
601 }
602
603 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
604
605 if (!rc) {
606 inode->i_nlink--;
607 i_size_write(direntry->d_inode,0);
608 direntry->d_inode->i_nlink = 0;
609 }
610
611 cifsInode = CIFS_I(direntry->d_inode);
612 cifsInode->time = 0; /* force revalidate to go get info when
613 needed */
614 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
615 current_fs_time(inode->i_sb);
616
617 kfree(full_path);
618 FreeXid(xid);
619 return rc;
620}
621
622int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
623 struct inode *target_inode, struct dentry *target_direntry)
624{
625 char *fromName;
626 char *toName;
627 struct cifs_sb_info *cifs_sb_source;
628 struct cifs_sb_info *cifs_sb_target;
629 struct cifsTconInfo *pTcon;
630 int xid;
631 int rc = 0;
632
633 xid = GetXid();
634
635 cifs_sb_target = CIFS_SB(target_inode->i_sb);
636 cifs_sb_source = CIFS_SB(source_inode->i_sb);
637 pTcon = cifs_sb_source->tcon;
638
639 if (pTcon != cifs_sb_target->tcon) {
640 FreeXid(xid);
641 return -EXDEV; /* BB actually could be allowed if same server,
642 but different share.
643 Might eventually add support for this */
644 }
645
646 /* we already have the rename sem so we do not need to grab it again
647 here to protect the path integrity */
648 fromName = build_path_from_dentry(source_direntry);
649 toName = build_path_from_dentry(target_direntry);
650 if ((fromName == NULL) || (toName == NULL)) {
651 rc = -ENOMEM;
652 goto cifs_rename_exit;
653 }
654
655 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
656 cifs_sb_source->local_nls);
657 if (rc == -EEXIST) {
658 /* check if they are the same file because rename of hardlinked
659 files is a noop */
660 FILE_UNIX_BASIC_INFO *info_buf_source;
661 FILE_UNIX_BASIC_INFO *info_buf_target;
662
663 info_buf_source =
664 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
665 if (info_buf_source != NULL) {
666 info_buf_target = info_buf_source + 1;
667 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
668 info_buf_source, cifs_sb_source->local_nls);
669 if (rc == 0) {
670 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
671 info_buf_target,
672 cifs_sb_target->local_nls);
673 }
674 if ((rc == 0) &&
675 (info_buf_source->UniqueId ==
676 info_buf_target->UniqueId)) {
677 /* do not rename since the files are hardlinked which
678 is a noop */
679 } else {
680 /* we either can not tell the files are hardlinked
681 (as with Windows servers) or files are not
682 hardlinked so delete the target manually before
683 renaming to follow POSIX rather than Windows
684 semantics */
685 cifs_unlink(target_inode, target_direntry);
686 rc = CIFSSMBRename(xid, pTcon, fromName,
687 toName,
688 cifs_sb_source->local_nls);
689 }
690 kfree(info_buf_source);
691 } /* if we can not get memory just leave rc as EEXIST */
692 }
693
694 if (rc) {
695 cFYI(1, ("rename rc %d", rc));
696 }
697
698 if ((rc == -EIO) || (rc == -EEXIST)) {
699 int oplock = FALSE;
700 __u16 netfid;
701
702 /* BB FIXME Is Generic Read correct for rename? */
703 /* if renaming directory - we should not say CREATE_NOT_DIR,
704 need to test renaming open directory, also GENERIC_READ
705 might not right be right access to request */
706 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
707 CREATE_NOT_DIR, &netfid, &oplock, NULL,
708 cifs_sb_source->local_nls);
709 if (rc==0) {
710 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
711 cifs_sb_source->local_nls);
712 CIFSSMBClose(xid, pTcon, netfid);
713 }
714 }
715
716cifs_rename_exit:
717 kfree(fromName);
718 kfree(toName);
719 FreeXid(xid);
720 return rc;
721}
722
723int cifs_revalidate(struct dentry *direntry)
724{
725 int xid;
726 int rc = 0;
727 char *full_path;
728 struct cifs_sb_info *cifs_sb;
729 struct cifsInodeInfo *cifsInode;
730 loff_t local_size;
731 struct timespec local_mtime;
732 int invalidate_inode = FALSE;
733
734 if (direntry->d_inode == NULL)
735 return -ENOENT;
736
737 cifsInode = CIFS_I(direntry->d_inode);
738
739 if (cifsInode == NULL)
740 return -ENOENT;
741
742 /* no sense revalidating inode info on file that no one can write */
743 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
744 return rc;
745
746 xid = GetXid();
747
748 cifs_sb = CIFS_SB(direntry->d_sb);
749
750 /* can not safely grab the rename sem here if rename calls revalidate
751 since that would deadlock */
752 full_path = build_path_from_dentry(direntry);
753 if (full_path == NULL) {
754 FreeXid(xid);
755 return -ENOMEM;
756 }
757 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
758 "jiffies %ld", full_path, direntry->d_inode,
759 direntry->d_inode->i_count.counter, direntry,
760 direntry->d_time, jiffies));
761
762 if (cifsInode->time == 0) {
763 /* was set to zero previously to force revalidate */
764 } else if (time_before(jiffies, cifsInode->time + HZ) &&
765 lookupCacheEnabled) {
766 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
767 (direntry->d_inode->i_nlink == 1)) {
768 kfree(full_path);
769 FreeXid(xid);
770 return rc;
771 } else {
772 cFYI(1, ("Have to revalidate file due to hardlinks"));
773 }
774 }
775
776 /* save mtime and size */
777 local_mtime = direntry->d_inode->i_mtime;
778 local_size = direntry->d_inode->i_size;
779
780 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
781 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
782 direntry->d_sb,xid);
783 if (rc) {
784 cFYI(1, ("error on getting revalidate info %d", rc));
785/* if (rc != -ENOENT)
786 rc = 0; */ /* BB should we cache info on
787 certain errors? */
788 }
789 } else {
790 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
791 direntry->d_sb,xid);
792 if (rc) {
793 cFYI(1, ("error on getting revalidate info %d", rc));
794/* if (rc != -ENOENT)
795 rc = 0; */ /* BB should we cache info on
796 certain errors? */
797 }
798 }
799 /* should we remap certain errors, access denied?, to zero */
800
801 /* if not oplocked, we invalidate inode pages if mtime or file size
802 had changed on server */
803
804 if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
805 (local_size == direntry->d_inode->i_size)) {
806 cFYI(1, ("cifs_revalidate - inode unchanged"));
807 } else {
808 /* file may have changed on server */
809 if (cifsInode->clientCanCacheRead) {
810 /* no need to invalidate inode pages since we were the
811 only ones who could have modified the file and the
812 server copy is staler than ours */
813 } else {
814 invalidate_inode = TRUE;
815 }
816 }
817
818 /* can not grab this sem since kernel filesys locking documentation
819 indicates i_sem may be taken by the kernel on lookup and rename
820 which could deadlock if we grab the i_sem here as well */
821/* down(&direntry->d_inode->i_sem);*/
822 /* need to write out dirty pages here */
823 if (direntry->d_inode->i_mapping) {
824 /* do we need to lock inode until after invalidate completes
825 below? */
826 filemap_fdatawrite(direntry->d_inode->i_mapping);
827 }
828 if (invalidate_inode) {
829 if (direntry->d_inode->i_mapping)
830 filemap_fdatawait(direntry->d_inode->i_mapping);
831 /* may eventually have to do this for open files too */
832 if (list_empty(&(cifsInode->openFileList))) {
833 /* Has changed on server - flush read ahead pages */
834 cFYI(1, ("Invalidating read ahead data on "
835 "closed file"));
836 invalidate_remote_inode(direntry->d_inode);
837 }
838 }
839/* up(&direntry->d_inode->i_sem); */
840
841 kfree(full_path);
842 FreeXid(xid);
843 return rc;
844}
845
846int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
847 struct kstat *stat)
848{
849 int err = cifs_revalidate(dentry);
850 if (!err)
851 generic_fillattr(dentry->d_inode, stat);
852 return err;
853}
854
855static int cifs_truncate_page(struct address_space *mapping, loff_t from)
856{
857 pgoff_t index = from >> PAGE_CACHE_SHIFT;
858 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
859 struct page *page;
860 char *kaddr;
861 int rc = 0;
862
863 page = grab_cache_page(mapping, index);
864 if (!page)
865 return -ENOMEM;
866
867 kaddr = kmap_atomic(page, KM_USER0);
868 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
869 flush_dcache_page(page);
870 kunmap_atomic(kaddr, KM_USER0);
871 unlock_page(page);
872 page_cache_release(page);
873 return rc;
874}
875
876int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
877{
878 int xid;
879 struct cifs_sb_info *cifs_sb;
880 struct cifsTconInfo *pTcon;
881 char *full_path = NULL;
882 int rc = -EACCES;
883 int found = FALSE;
884 struct cifsFileInfo *open_file = NULL;
885 FILE_BASIC_INFO time_buf;
886 int set_time = FALSE;
887 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
888 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
889 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
890 struct cifsInodeInfo *cifsInode;
891 struct list_head *tmp;
892
893 xid = GetXid();
894
895 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
896 direntry->d_name.name, attrs->ia_valid));
897 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
898 pTcon = cifs_sb->tcon;
899
900 down(&direntry->d_sb->s_vfs_rename_sem);
901 full_path = build_path_from_dentry(direntry);
902 up(&direntry->d_sb->s_vfs_rename_sem);
903 if (full_path == NULL) {
904 FreeXid(xid);
905 return -ENOMEM;
906 }
907 cifsInode = CIFS_I(direntry->d_inode);
908
909 /* BB check if we need to refresh inode from server now ? BB */
910
911 /* need to flush data before changing file size on server */
912 filemap_fdatawrite(direntry->d_inode->i_mapping);
913 filemap_fdatawait(direntry->d_inode->i_mapping);
914
915 if (attrs->ia_valid & ATTR_SIZE) {
916 read_lock(&GlobalSMBSeslock);
917 /* To avoid spurious oplock breaks from server, in the case of
918 inodes that we already have open, avoid doing path based
919 setting of file size if we can do it by handle.
920 This keeps our caching token (oplock) and avoids timeouts
921 when the local oplock break takes longer to flush
922 writebehind data than the SMB timeout for the SetPathInfo
923 request would allow */
924 list_for_each(tmp, &cifsInode->openFileList) {
925 open_file = list_entry(tmp, struct cifsFileInfo,
926 flist);
927 /* We check if file is open for writing first */
928 if ((open_file->pfile) &&
929 ((open_file->pfile->f_flags & O_RDWR) ||
930 (open_file->pfile->f_flags & O_WRONLY))) {
931 if (open_file->invalidHandle == FALSE) {
932 /* we found a valid, writeable network
933 file handle to use to try to set the
934 file size */
935 __u16 nfid = open_file->netfid;
936 __u32 npid = open_file->pid;
937 read_unlock(&GlobalSMBSeslock);
938 found = TRUE;
939 rc = CIFSSMBSetFileSize(xid, pTcon,
940 attrs->ia_size, nfid, npid,
941 FALSE);
942 cFYI(1, ("SetFileSize by handle "
943 "(setattrs) rc = %d", rc));
944 /* Do not need reopen and retry on
945 EAGAIN since we will retry by
946 pathname below */
947
948 /* now that we found one valid file
949 handle no sense continuing to loop
950 trying others, so break here */
951 break;
952 }
953 }
954 }
955 if (found == FALSE)
956 read_unlock(&GlobalSMBSeslock);
957
958 if (rc != 0) {
959 /* Set file size by pathname rather than by handle
960 either because no valid, writeable file handle for
961 it was found or because there was an error setting
962 it by handle */
963 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
964 attrs->ia_size, FALSE,
965 cifs_sb->local_nls);
966 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
967 }
968
969 /* Server is ok setting allocation size implicitly - no need
970 to call:
971 CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
972 cifs_sb->local_nls);
973 */
974
975 if (rc == 0) {
976 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
977 cifs_truncate_page(direntry->d_inode->i_mapping,
978 direntry->d_inode->i_size);
979 }
980 }
981 if (attrs->ia_valid & ATTR_UID) {
982 cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
983 uid = attrs->ia_uid;
984 /* entry->uid = cpu_to_le16(attr->ia_uid); */
985 }
986 if (attrs->ia_valid & ATTR_GID) {
987 cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
988 gid = attrs->ia_gid;
989 /* entry->gid = cpu_to_le16(attr->ia_gid); */
990 }
991
992 time_buf.Attributes = 0;
993 if (attrs->ia_valid & ATTR_MODE) {
994 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
995 mode = attrs->ia_mode;
996 /* entry->mode = cpu_to_le16(attr->ia_mode); */
997 }
998
999 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1000 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1001 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1002 0 /* dev_t */, cifs_sb->local_nls);
1003 else if (attrs->ia_valid & ATTR_MODE) {
1004 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1005 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1006 time_buf.Attributes =
1007 cpu_to_le32(cifsInode->cifsAttrs |
1008 ATTR_READONLY);
1009 } else if ((mode & S_IWUGO) == S_IWUGO) {
1010 if (cifsInode->cifsAttrs & ATTR_READONLY)
1011 time_buf.Attributes =
1012 cpu_to_le32(cifsInode->cifsAttrs &
1013 (~ATTR_READONLY));
1014 }
1015 /* BB to be implemented -
1016 via Windows security descriptors or streams */
1017 /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
1018 cifs_sb->local_nls); */
1019 }
1020
1021 if (attrs->ia_valid & ATTR_ATIME) {
1022 set_time = TRUE;
1023 time_buf.LastAccessTime =
1024 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1025 } else
1026 time_buf.LastAccessTime = 0;
1027
1028 if (attrs->ia_valid & ATTR_MTIME) {
1029 set_time = TRUE;
1030 time_buf.LastWriteTime =
1031 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1032 } else
1033 time_buf.LastWriteTime = 0;
1034
1035 if (attrs->ia_valid & ATTR_CTIME) {
1036 set_time = TRUE;
1037 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
1038 time_buf.ChangeTime =
1039 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1040 } else
1041 time_buf.ChangeTime = 0;
1042
1043 if (set_time || time_buf.Attributes) {
1044 /* BB what if setting one attribute fails (such as size) but
1045 time setting works? */
1046 time_buf.CreationTime = 0; /* do not change */
1047 /* In the future we should experiment - try setting timestamps
1048 via Handle (SetFileInfo) instead of by path */
1049 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1050 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1051 cifs_sb->local_nls);
1052 else
1053 rc = -EOPNOTSUPP;
1054
1055 if (rc == -EOPNOTSUPP) {
1056 int oplock = FALSE;
1057 __u16 netfid;
1058
1059 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1060 "times not supported by this server"));
1061 /* BB we could scan to see if we already have it open
1062 and pass in pid of opener to function */
1063 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1064 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1065 CREATE_NOT_DIR, &netfid, &oplock,
1066 NULL, cifs_sb->local_nls);
1067 if (rc==0) {
1068 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1069 netfid);
1070 CIFSSMBClose(xid, pTcon, netfid);
1071 } else {
1072 /* BB For even older servers we could convert time_buf
1073 into old DOS style which uses two second
1074 granularity */
1075
1076 /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1077 &time_buf, cifs_sb->local_nls); */
1078 }
1079 }
1080 }
1081
1082 /* do not need local check to inode_check_ok since the server does
1083 that */
1084 if (!rc)
1085 rc = inode_setattr(direntry->d_inode, attrs);
1086 kfree(full_path);
1087 FreeXid(xid);
1088 return rc;
1089}
1090
1091void cifs_delete_inode(struct inode *inode)
1092{
1093 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
1094 /* may have to add back in if and when safe distributed caching of
1095 directories added e.g. via FindNotify */
1096}
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
new file mode 100644
index 000000000000..b4b8e201d428
--- /dev/null
+++ b/fs/cifs/ioctl.c
@@ -0,0 +1,49 @@
1/*
2 * fs/cifs/ioctl.c
3 *
4 * vfs operations that deal with io control
5 *
6 * Copyright (C) International Business Machines Corp., 2005
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/ext2_fs.h>
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifsproto.h"
28#include "cifs_debug.h"
29
30int cifs_ioctl (struct inode * inode, struct file * filep,
31 unsigned int command, unsigned long arg)
32{
33 int rc = -ENOTTY; /* strange error - but the precedent */
34#ifdef CONFIG_CIFS_POSIX
35 cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
36 switch(command) {
37 case EXT2_IOC_GETFLAGS:
38 cFYI(1,("get flags not implemented yet"));
39 return -EOPNOTSUPP;
40 case EXT2_IOC_SETFLAGS:
41 cFYI(1,("set flags not implemented yet"));
42 return -EOPNOTSUPP;
43 default:
44 cFYI(1,("unsupported ioctl"));
45 return rc;
46 }
47#endif /* CONFIG_CIFS_POSIX */
48 return rc;
49}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
new file mode 100644
index 000000000000..1455810ba1cb
--- /dev/null
+++ b/fs/cifs/link.c
@@ -0,0 +1,328 @@
1/*
2 * fs/cifs/link.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2003
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
22#include <linux/stat.h>
23#include <linux/namei.h>
24#include "cifsfs.h"
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifsproto.h"
28#include "cifs_debug.h"
29#include "cifs_fs_sb.h"
30
31int
32cifs_hardlink(struct dentry *old_file, struct inode *inode,
33 struct dentry *direntry)
34{
35 int rc = -EACCES;
36 int xid;
37 char *fromName = NULL;
38 char *toName = NULL;
39 struct cifs_sb_info *cifs_sb_target;
40 struct cifsTconInfo *pTcon;
41 struct cifsInodeInfo *cifsInode;
42
43 xid = GetXid();
44
45 cifs_sb_target = CIFS_SB(inode->i_sb);
46 pTcon = cifs_sb_target->tcon;
47
48/* No need to check for cross device links since server will do that
49 BB note DFS case in future though (when we may have to check) */
50
51 down(&inode->i_sb->s_vfs_rename_sem);
52 fromName = build_path_from_dentry(old_file);
53 toName = build_path_from_dentry(direntry);
54 up(&inode->i_sb->s_vfs_rename_sem);
55 if((fromName == NULL) || (toName == NULL)) {
56 rc = -ENOMEM;
57 goto cifs_hl_exit;
58 }
59
60 if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
61 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
62 cifs_sb_target->local_nls);
63 else {
64 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
65 cifs_sb_target->local_nls);
66 if(rc == -EIO)
67 rc = -EOPNOTSUPP;
68 }
69
70/* if (!rc) */
71 {
72 /* renew_parental_timestamps(old_file);
73 inode->i_nlink++;
74 mark_inode_dirty(inode);
75 d_instantiate(direntry, inode); */
76 /* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
77 }
78 d_drop(direntry); /* force new lookup from server */
79 cifsInode = CIFS_I(old_file->d_inode);
80 cifsInode->time = 0; /* will force revalidate to go get info when needed */
81
82cifs_hl_exit:
83 if (fromName)
84 kfree(fromName);
85 if (toName)
86 kfree(toName);
87 FreeXid(xid);
88 return rc;
89}
90
91int
92cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
93{
94 struct inode *inode = direntry->d_inode;
95 int rc = -EACCES;
96 int xid;
97 char *full_path = NULL;
98 char * target_path = ERR_PTR(-ENOMEM);
99 struct cifs_sb_info *cifs_sb;
100 struct cifsTconInfo *pTcon;
101
102 xid = GetXid();
103
104 down(&direntry->d_sb->s_vfs_rename_sem);
105 full_path = build_path_from_dentry(direntry);
106 up(&direntry->d_sb->s_vfs_rename_sem);
107
108 if (!full_path)
109 goto out_no_free;
110
111 cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
112 cifs_sb = CIFS_SB(inode->i_sb);
113 pTcon = cifs_sb->tcon;
114 target_path = kmalloc(PATH_MAX, GFP_KERNEL);
115 if (!target_path) {
116 target_path = ERR_PTR(-ENOMEM);
117 goto out;
118 }
119
120/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
121 if (pTcon->ses->capabilities & CAP_UNIX)
122 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
123 target_path,
124 PATH_MAX-1,
125 cifs_sb->local_nls);
126 else {
127 /* rc = CIFSSMBQueryReparseLinkInfo */
128 /* BB Add code to Query ReparsePoint info */
129 /* BB Add MAC style xsymlink check here if enabled */
130 }
131
132 if (rc == 0) {
133
134/* BB Add special case check for Samba DFS symlinks */
135
136 target_path[PATH_MAX-1] = 0;
137 } else {
138 kfree(target_path);
139 target_path = ERR_PTR(rc);
140 }
141
142out:
143 kfree(full_path);
144out_no_free:
145 FreeXid(xid);
146 nd_set_link(nd, target_path);
147 return 0;
148}
149
150int
151cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
152{
153 int rc = -EOPNOTSUPP;
154 int xid;
155 struct cifs_sb_info *cifs_sb;
156 struct cifsTconInfo *pTcon;
157 char *full_path = NULL;
158 struct inode *newinode = NULL;
159
160 xid = GetXid();
161
162 cifs_sb = CIFS_SB(inode->i_sb);
163 pTcon = cifs_sb->tcon;
164
165 down(&inode->i_sb->s_vfs_rename_sem);
166 full_path = build_path_from_dentry(direntry);
167 up(&inode->i_sb->s_vfs_rename_sem);
168
169 if(full_path == NULL) {
170 FreeXid(xid);
171 return -ENOMEM;
172 }
173
174 cFYI(1, ("Full path: %s ", full_path));
175 cFYI(1, ("symname is %s", symname));
176
177 /* BB what if DFS and this volume is on different share? BB */
178 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
179 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
180 cifs_sb->local_nls);
181 /* else
182 rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
183
184 if (rc == 0) {
185 if (pTcon->ses->capabilities & CAP_UNIX)
186 rc = cifs_get_inode_info_unix(&newinode, full_path,
187 inode->i_sb,xid);
188 else
189 rc = cifs_get_inode_info(&newinode, full_path, NULL,
190 inode->i_sb,xid);
191
192 if (rc != 0) {
193 cFYI(1,
194 ("Create symlink worked but get_inode_info failed with rc = %d ",
195 rc));
196 } else {
197 direntry->d_op = &cifs_dentry_ops;
198 d_instantiate(direntry, newinode);
199 }
200 }
201
202 if (full_path)
203 kfree(full_path);
204 FreeXid(xid);
205 return rc;
206}
207
208int
209cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
210{
211 struct inode *inode = direntry->d_inode;
212 int rc = -EACCES;
213 int xid;
214 int oplock = FALSE;
215 struct cifs_sb_info *cifs_sb;
216 struct cifsTconInfo *pTcon;
217 char *full_path = NULL;
218 char *tmp_path = NULL;
219 char * tmpbuffer;
220 unsigned char * referrals = NULL;
221 int num_referrals = 0;
222 int len;
223 __u16 fid;
224
225 xid = GetXid();
226 cifs_sb = CIFS_SB(inode->i_sb);
227 pTcon = cifs_sb->tcon;
228
229/* BB would it be safe against deadlock to grab this sem
230 even though rename itself grabs the sem and calls lookup? */
231/* down(&inode->i_sb->s_vfs_rename_sem);*/
232 full_path = build_path_from_dentry(direntry);
233/* up(&inode->i_sb->s_vfs_rename_sem);*/
234
235 if(full_path == NULL) {
236 FreeXid(xid);
237 return -ENOMEM;
238 }
239
240 cFYI(1,
241 ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
242 full_path, inode, pBuffer, buflen));
243 if(buflen > PATH_MAX)
244 len = PATH_MAX;
245 else
246 len = buflen;
247 tmpbuffer = kmalloc(len,GFP_KERNEL);
248 if(tmpbuffer == NULL) {
249 if (full_path)
250 kfree(full_path);
251 FreeXid(xid);
252 return -ENOMEM;
253 }
254
255/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
256 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
257 rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
258 tmpbuffer,
259 len - 1,
260 cifs_sb->local_nls);
261 else {
262 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
263 OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
264 if(!rc) {
265 rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
266 tmpbuffer,
267 len - 1,
268 fid,
269 cifs_sb->local_nls);
270 if(CIFSSMBClose(xid, pTcon, fid)) {
271 cFYI(1,("Error closing junction point (open for ioctl)"));
272 }
273 if(rc == -EIO) {
274 /* Query if DFS Junction */
275 tmp_path =
276 kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
277 GFP_KERNEL);
278 if (tmp_path) {
279 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
280 strncat(tmp_path, full_path, MAX_PATHCONF);
281 rc = get_dfs_path(xid, pTcon->ses, tmp_path,
282 cifs_sb->local_nls, &num_referrals, &referrals);
283 cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
284 if((num_referrals == 0) && (rc == 0))
285 rc = -EACCES;
286 else {
287 cFYI(1,("num referral: %d",num_referrals));
288 if(referrals) {
289 cFYI(1,("referral string: %s ",referrals));
290 strncpy(tmpbuffer, referrals, len-1);
291 }
292 }
293 if(referrals)
294 kfree(referrals);
295 kfree(tmp_path);
296}
297 /* BB add code like else decode referrals then memcpy to
298 tmpbuffer and free referrals string array BB */
299 }
300 }
301 }
302 /* BB Anything else to do to handle recursive links? */
303 /* BB Should we be using page ops here? */
304
305 /* BB null terminate returned string in pBuffer? BB */
306 if (rc == 0) {
307 rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
308 cFYI(1,
309 ("vfs_readlink called from cifs_readlink returned %d",
310 rc));
311 }
312
313 if (tmpbuffer) {
314 kfree(tmpbuffer);
315 }
316 if (full_path) {
317 kfree(full_path);
318 }
319 FreeXid(xid);
320 return rc;
321}
322
323void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
324{
325 char *p = nd_get_link(nd);
326 if (!IS_ERR(p))
327 kfree(p);
328}
diff --git a/fs/cifs/md4.c b/fs/cifs/md4.c
new file mode 100644
index 000000000000..46d62c9dda0f
--- /dev/null
+++ b/fs/cifs/md4.c
@@ -0,0 +1,205 @@
1/*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 a implementation of MD4 designed for use in the SMB authentication protocol
5 Copyright (C) Andrew Tridgell 1997-1998.
6 Modified by Steve French (sfrench@us.ibm.com) 2002-2003
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 the
16 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., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22#include <linux/module.h>
23#include <linux/fs.h>
24#include "cifsencrypt.h"
25
26/* NOTE: This code makes no attempt to be fast! */
27
28static __u32
29F(__u32 X, __u32 Y, __u32 Z)
30{
31 return (X & Y) | ((~X) & Z);
32}
33
34static __u32
35G(__u32 X, __u32 Y, __u32 Z)
36{
37 return (X & Y) | (X & Z) | (Y & Z);
38}
39
40static __u32
41H(__u32 X, __u32 Y, __u32 Z)
42{
43 return X ^ Y ^ Z;
44}
45
46static __u32
47lshift(__u32 x, int s)
48{
49 x &= 0xFFFFFFFF;
50 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
51}
52
53#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
54#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
55#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
56
57/* this applies md4 to 64 byte chunks */
58static void
59mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
60{
61 int j;
62 __u32 AA, BB, CC, DD;
63 __u32 X[16];
64
65
66 for (j = 0; j < 16; j++)
67 X[j] = M[j];
68
69 AA = *A;
70 BB = *B;
71 CC = *C;
72 DD = *D;
73
74 ROUND1(A, B, C, D, 0, 3);
75 ROUND1(D, A, B, C, 1, 7);
76 ROUND1(C, D, A, B, 2, 11);
77 ROUND1(B, C, D, A, 3, 19);
78 ROUND1(A, B, C, D, 4, 3);
79 ROUND1(D, A, B, C, 5, 7);
80 ROUND1(C, D, A, B, 6, 11);
81 ROUND1(B, C, D, A, 7, 19);
82 ROUND1(A, B, C, D, 8, 3);
83 ROUND1(D, A, B, C, 9, 7);
84 ROUND1(C, D, A, B, 10, 11);
85 ROUND1(B, C, D, A, 11, 19);
86 ROUND1(A, B, C, D, 12, 3);
87 ROUND1(D, A, B, C, 13, 7);
88 ROUND1(C, D, A, B, 14, 11);
89 ROUND1(B, C, D, A, 15, 19);
90
91 ROUND2(A, B, C, D, 0, 3);
92 ROUND2(D, A, B, C, 4, 5);
93 ROUND2(C, D, A, B, 8, 9);
94 ROUND2(B, C, D, A, 12, 13);
95 ROUND2(A, B, C, D, 1, 3);
96 ROUND2(D, A, B, C, 5, 5);
97 ROUND2(C, D, A, B, 9, 9);
98 ROUND2(B, C, D, A, 13, 13);
99 ROUND2(A, B, C, D, 2, 3);
100 ROUND2(D, A, B, C, 6, 5);
101 ROUND2(C, D, A, B, 10, 9);
102 ROUND2(B, C, D, A, 14, 13);
103 ROUND2(A, B, C, D, 3, 3);
104 ROUND2(D, A, B, C, 7, 5);
105 ROUND2(C, D, A, B, 11, 9);
106 ROUND2(B, C, D, A, 15, 13);
107
108 ROUND3(A, B, C, D, 0, 3);
109 ROUND3(D, A, B, C, 8, 9);
110 ROUND3(C, D, A, B, 4, 11);
111 ROUND3(B, C, D, A, 12, 15);
112 ROUND3(A, B, C, D, 2, 3);
113 ROUND3(D, A, B, C, 10, 9);
114 ROUND3(C, D, A, B, 6, 11);
115 ROUND3(B, C, D, A, 14, 15);
116 ROUND3(A, B, C, D, 1, 3);
117 ROUND3(D, A, B, C, 9, 9);
118 ROUND3(C, D, A, B, 5, 11);
119 ROUND3(B, C, D, A, 13, 15);
120 ROUND3(A, B, C, D, 3, 3);
121 ROUND3(D, A, B, C, 11, 9);
122 ROUND3(C, D, A, B, 7, 11);
123 ROUND3(B, C, D, A, 15, 15);
124
125 *A += AA;
126 *B += BB;
127 *C += CC;
128 *D += DD;
129
130 *A &= 0xFFFFFFFF;
131 *B &= 0xFFFFFFFF;
132 *C &= 0xFFFFFFFF;
133 *D &= 0xFFFFFFFF;
134
135 for (j = 0; j < 16; j++)
136 X[j] = 0;
137}
138
139static void
140copy64(__u32 * M, unsigned char *in)
141{
142 int i;
143
144 for (i = 0; i < 16; i++)
145 M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
146 (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
147}
148
149static void
150copy4(unsigned char *out, __u32 x)
151{
152 out[0] = x & 0xFF;
153 out[1] = (x >> 8) & 0xFF;
154 out[2] = (x >> 16) & 0xFF;
155 out[3] = (x >> 24) & 0xFF;
156}
157
158/* produce a md4 message digest from data of length n bytes */
159void
160mdfour(unsigned char *out, unsigned char *in, int n)
161{
162 unsigned char buf[128];
163 __u32 M[16];
164 __u32 b = n * 8;
165 int i;
166 __u32 A = 0x67452301;
167 __u32 B = 0xefcdab89;
168 __u32 C = 0x98badcfe;
169 __u32 D = 0x10325476;
170
171 while (n > 64) {
172 copy64(M, in);
173 mdfour64(M,&A,&B, &C, &D);
174 in += 64;
175 n -= 64;
176 }
177
178 for (i = 0; i < 128; i++)
179 buf[i] = 0;
180 memcpy(buf, in, n);
181 buf[n] = 0x80;
182
183 if (n <= 55) {
184 copy4(buf + 56, b);
185 copy64(M, buf);
186 mdfour64(M, &A, &B, &C, &D);
187 } else {
188 copy4(buf + 120, b);
189 copy64(M, buf);
190 mdfour64(M, &A, &B, &C, &D);
191 copy64(M, buf + 64);
192 mdfour64(M, &A, &B, &C, &D);
193 }
194
195 for (i = 0; i < 128; i++)
196 buf[i] = 0;
197 copy64(M, buf);
198
199 copy4(out, A);
200 copy4(out + 4, B);
201 copy4(out + 8, C);
202 copy4(out + 12, D);
203
204 A = B = C = D = 0;
205}
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c
new file mode 100644
index 000000000000..7aa23490541f
--- /dev/null
+++ b/fs/cifs/md5.c
@@ -0,0 +1,363 @@
1/*
2 * This code implements the MD5 message-digest algorithm.
3 * The algorithm is due to Ron Rivest. This code was
4 * written by Colin Plumb in 1993, no copyright is claimed.
5 * This code is in the public domain; do with it what you wish.
6 *
7 * Equivalent code is available from RSA Data Security, Inc.
8 * This code has been tested against that, and is equivalent,
9 * except that you don't need to include two pages of legalese
10 * with every copy.
11 *
12 * To compute the message digest of a chunk of bytes, declare an
13 * MD5Context structure, pass it to MD5Init, call MD5Update as
14 * needed on buffers full of bytes, and then call MD5Final, which
15 * will fill a supplied 16-byte array with the digest.
16 */
17
18/* This code slightly modified to fit into Samba by
19 abartlet@samba.org Jun 2001
20 and to fit the cifs vfs by
21 Steve French sfrench@us.ibm.com */
22
23#include <linux/string.h>
24#include "md5.h"
25
26static void MD5Transform(__u32 buf[4], __u32 const in[16]);
27
28/*
29 * Note: this code is harmless on little-endian machines.
30 */
31static void
32byteReverse(unsigned char *buf, unsigned longs)
33{
34 __u32 t;
35 do {
36 t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
37 ((unsigned) buf[1] << 8 | buf[0]);
38 *(__u32 *) buf = t;
39 buf += 4;
40 } while (--longs);
41}
42
43/*
44 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
45 * initialization constants.
46 */
47void
48MD5Init(struct MD5Context *ctx)
49{
50 ctx->buf[0] = 0x67452301;
51 ctx->buf[1] = 0xefcdab89;
52 ctx->buf[2] = 0x98badcfe;
53 ctx->buf[3] = 0x10325476;
54
55 ctx->bits[0] = 0;
56 ctx->bits[1] = 0;
57}
58
59/*
60 * Update context to reflect the concatenation of another buffer full
61 * of bytes.
62 */
63void
64MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
65{
66 register __u32 t;
67
68 /* Update bitcount */
69
70 t = ctx->bits[0];
71 if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
72 ctx->bits[1]++; /* Carry from low to high */
73 ctx->bits[1] += len >> 29;
74
75 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
76
77 /* Handle any leading odd-sized chunks */
78
79 if (t) {
80 unsigned char *p = (unsigned char *) ctx->in + t;
81
82 t = 64 - t;
83 if (len < t) {
84 memmove(p, buf, len);
85 return;
86 }
87 memmove(p, buf, t);
88 byteReverse(ctx->in, 16);
89 MD5Transform(ctx->buf, (__u32 *) ctx->in);
90 buf += t;
91 len -= t;
92 }
93 /* Process data in 64-byte chunks */
94
95 while (len >= 64) {
96 memmove(ctx->in, buf, 64);
97 byteReverse(ctx->in, 16);
98 MD5Transform(ctx->buf, (__u32 *) ctx->in);
99 buf += 64;
100 len -= 64;
101 }
102
103 /* Handle any remaining bytes of data. */
104
105 memmove(ctx->in, buf, len);
106}
107
108/*
109 * Final wrapup - pad to 64-byte boundary with the bit pattern
110 * 1 0* (64-bit count of bits processed, MSB-first)
111 */
112void
113MD5Final(unsigned char digest[16], struct MD5Context *ctx)
114{
115 unsigned int count;
116 unsigned char *p;
117
118 /* Compute number of bytes mod 64 */
119 count = (ctx->bits[0] >> 3) & 0x3F;
120
121 /* Set the first char of padding to 0x80. This is safe since there is
122 always at least one byte free */
123 p = ctx->in + count;
124 *p++ = 0x80;
125
126 /* Bytes of padding needed to make 64 bytes */
127 count = 64 - 1 - count;
128
129 /* Pad out to 56 mod 64 */
130 if (count < 8) {
131 /* Two lots of padding: Pad the first block to 64 bytes */
132 memset(p, 0, count);
133 byteReverse(ctx->in, 16);
134 MD5Transform(ctx->buf, (__u32 *) ctx->in);
135
136 /* Now fill the next block with 56 bytes */
137 memset(ctx->in, 0, 56);
138 } else {
139 /* Pad block to 56 bytes */
140 memset(p, 0, count - 8);
141 }
142 byteReverse(ctx->in, 14);
143
144 /* Append length in bits and transform */
145 ((__u32 *) ctx->in)[14] = ctx->bits[0];
146 ((__u32 *) ctx->in)[15] = ctx->bits[1];
147
148 MD5Transform(ctx->buf, (__u32 *) ctx->in);
149 byteReverse((unsigned char *) ctx->buf, 4);
150 memmove(digest, ctx->buf, 16);
151 memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
152}
153
154/* The four core functions - F1 is optimized somewhat */
155
156/* #define F1(x, y, z) (x & y | ~x & z) */
157#define F1(x, y, z) (z ^ (x & (y ^ z)))
158#define F2(x, y, z) F1(z, x, y)
159#define F3(x, y, z) (x ^ y ^ z)
160#define F4(x, y, z) (y ^ (x | ~z))
161
162/* This is the central step in the MD5 algorithm. */
163#define MD5STEP(f, w, x, y, z, data, s) \
164 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
165
166/*
167 * The core of the MD5 algorithm, this alters an existing MD5 hash to
168 * reflect the addition of 16 longwords of new data. MD5Update blocks
169 * the data and converts bytes into longwords for this routine.
170 */
171static void
172MD5Transform(__u32 buf[4], __u32 const in[16])
173{
174 register __u32 a, b, c, d;
175
176 a = buf[0];
177 b = buf[1];
178 c = buf[2];
179 d = buf[3];
180
181 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
182 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
183 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
184 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
185 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
186 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
187 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
188 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
189 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
190 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
191 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
192 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
193 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
194 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
195 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
196 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
197
198 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
199 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
200 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
201 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
202 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
203 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
204 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
205 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
206 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
207 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
208 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
209 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
210 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
211 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
212 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
213 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
214
215 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
216 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
217 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
218 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
219 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
220 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
221 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
222 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
223 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
224 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
225 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
226 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
227 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
228 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
229 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
230 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
231
232 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
233 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
234 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
235 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
236 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
237 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
238 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
239 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
240 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
241 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
242 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
243 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
244 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
245 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
246 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
247 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
248
249 buf[0] += a;
250 buf[1] += b;
251 buf[2] += c;
252 buf[3] += d;
253}
254
255/***********************************************************************
256 the rfc 2104 version of hmac_md5 initialisation.
257***********************************************************************/
258void
259hmac_md5_init_rfc2104(unsigned char *key, int key_len,
260 struct HMACMD5Context *ctx)
261{
262 int i;
263
264 /* if key is longer than 64 bytes reset it to key=MD5(key) */
265 if (key_len > 64) {
266 unsigned char tk[16];
267 struct MD5Context tctx;
268
269 MD5Init(&tctx);
270 MD5Update(&tctx, key, key_len);
271 MD5Final(tk, &tctx);
272
273 key = tk;
274 key_len = 16;
275 }
276
277 /* start out by storing key in pads */
278 memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
279 memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
280 memcpy(ctx->k_ipad, key, key_len);
281 memcpy(ctx->k_opad, key, key_len);
282
283 /* XOR key with ipad and opad values */
284 for (i = 0; i < 64; i++) {
285 ctx->k_ipad[i] ^= 0x36;
286 ctx->k_opad[i] ^= 0x5c;
287 }
288
289 MD5Init(&ctx->ctx);
290 MD5Update(&ctx->ctx, ctx->k_ipad, 64);
291}
292
293/***********************************************************************
294 the microsoft version of hmac_md5 initialisation.
295***********************************************************************/
296void
297hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
298 struct HMACMD5Context *ctx)
299{
300 int i;
301
302 /* if key is longer than 64 bytes truncate it */
303 if (key_len > 64) {
304 key_len = 64;
305 }
306
307 /* start out by storing key in pads */
308 memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
309 memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
310 memcpy(ctx->k_ipad, key, key_len);
311 memcpy(ctx->k_opad, key, key_len);
312
313 /* XOR key with ipad and opad values */
314 for (i = 0; i < 64; i++) {
315 ctx->k_ipad[i] ^= 0x36;
316 ctx->k_opad[i] ^= 0x5c;
317 }
318
319 MD5Init(&ctx->ctx);
320 MD5Update(&ctx->ctx, ctx->k_ipad, 64);
321}
322
323/***********************************************************************
324 update hmac_md5 "inner" buffer
325***********************************************************************/
326void
327hmac_md5_update(const unsigned char *text, int text_len,
328 struct HMACMD5Context *ctx)
329{
330 MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
331}
332
333/***********************************************************************
334 finish off hmac_md5 "inner" buffer and generate outer one.
335***********************************************************************/
336void
337hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
338{
339 struct MD5Context ctx_o;
340
341 MD5Final(digest, &ctx->ctx);
342
343 MD5Init(&ctx_o);
344 MD5Update(&ctx_o, ctx->k_opad, 64);
345 MD5Update(&ctx_o, digest, 16);
346 MD5Final(digest, &ctx_o);
347}
348
349/***********************************************************
350 single function to calculate an HMAC MD5 digest from data.
351 use the microsoft hmacmd5 init method because the key is 16 bytes.
352************************************************************/
353void
354hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
355 unsigned char *digest)
356{
357 struct HMACMD5Context ctx;
358 hmac_md5_init_limK_to_64(key, 16, &ctx);
359 if (data_len != 0) {
360 hmac_md5_update(data, data_len, &ctx);
361 }
362 hmac_md5_final(digest, &ctx);
363}
diff --git a/fs/cifs/md5.h b/fs/cifs/md5.h
new file mode 100644
index 000000000000..00e1c5394fe1
--- /dev/null
+++ b/fs/cifs/md5.h
@@ -0,0 +1,38 @@
1#ifndef MD5_H
2#define MD5_H
3#ifndef HEADER_MD5_H
4/* Try to avoid clashes with OpenSSL */
5#define HEADER_MD5_H
6#endif
7
8struct MD5Context {
9 __u32 buf[4];
10 __u32 bits[2];
11 unsigned char in[64];
12};
13#endif /* !MD5_H */
14
15#ifndef _HMAC_MD5_H
16struct HMACMD5Context {
17 struct MD5Context ctx;
18 unsigned char k_ipad[65];
19 unsigned char k_opad[65];
20};
21#endif /* _HMAC_MD5_H */
22
23void MD5Init(struct MD5Context *context);
24void MD5Update(struct MD5Context *context, unsigned char const *buf,
25 unsigned len);
26void MD5Final(unsigned char digest[16], struct MD5Context *context);
27
28/* The following definitions come from lib/hmacmd5.c */
29
30void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
31 struct HMACMD5Context *ctx);
32void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
33 struct HMACMD5Context *ctx);
34void hmac_md5_update(const unsigned char *text, int text_len,
35 struct HMACMD5Context *ctx);
36void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
37void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
38 unsigned char *digest);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
new file mode 100644
index 000000000000..7b38d3059a83
--- /dev/null
+++ b/fs/cifs/misc.c
@@ -0,0 +1,516 @@
1/*
2 * fs/cifs/misc.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/slab.h>
23#include <linux/ctype.h>
24#include <linux/mempool.h>
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifsproto.h"
28#include "cifs_debug.h"
29#include "smberr.h"
30#include "nterr.h"
31
32extern mempool_t *cifs_sm_req_poolp;
33extern mempool_t *cifs_req_poolp;
34extern struct task_struct * oplockThread;
35
36static __u16 GlobalMid; /* multiplex id - rotating counter */
37
38/* The xid serves as a useful identifier for each incoming vfs request,
39 in a similar way to the mid which is useful to track each sent smb,
40 and CurrentXid can also provide a running counter (although it
41 will eventually wrap past zero) of the total vfs operations handled
42 since the cifs fs was mounted */
43
44unsigned int
45_GetXid(void)
46{
47 unsigned int xid;
48
49 spin_lock(&GlobalMid_Lock);
50 GlobalTotalActiveXid++;
51 if (GlobalTotalActiveXid > GlobalMaxActiveXid)
52 GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
53 xid = GlobalCurrentXid++;
54 spin_unlock(&GlobalMid_Lock);
55 return xid;
56}
57
58void
59_FreeXid(unsigned int xid)
60{
61 spin_lock(&GlobalMid_Lock);
62 /* if(GlobalTotalActiveXid == 0)
63 BUG(); */
64 GlobalTotalActiveXid--;
65 spin_unlock(&GlobalMid_Lock);
66}
67
68struct cifsSesInfo *
69sesInfoAlloc(void)
70{
71 struct cifsSesInfo *ret_buf;
72
73 ret_buf =
74 (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
75 GFP_KERNEL);
76 if (ret_buf) {
77 memset(ret_buf, 0, sizeof (struct cifsSesInfo));
78 write_lock(&GlobalSMBSeslock);
79 atomic_inc(&sesInfoAllocCount);
80 ret_buf->status = CifsNew;
81 list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
82 init_MUTEX(&ret_buf->sesSem);
83 write_unlock(&GlobalSMBSeslock);
84 }
85 return ret_buf;
86}
87
88void
89sesInfoFree(struct cifsSesInfo *buf_to_free)
90{
91 if (buf_to_free == NULL) {
92 cFYI(1, ("Null buffer passed to sesInfoFree"));
93 return;
94 }
95
96 write_lock(&GlobalSMBSeslock);
97 atomic_dec(&sesInfoAllocCount);
98 list_del(&buf_to_free->cifsSessionList);
99 write_unlock(&GlobalSMBSeslock);
100 if (buf_to_free->serverOS)
101 kfree(buf_to_free->serverOS);
102 if (buf_to_free->serverDomain)
103 kfree(buf_to_free->serverDomain);
104 if (buf_to_free->serverNOS)
105 kfree(buf_to_free->serverNOS);
106 if (buf_to_free->password)
107 kfree(buf_to_free->password);
108 kfree(buf_to_free);
109}
110
111struct cifsTconInfo *
112tconInfoAlloc(void)
113{
114 struct cifsTconInfo *ret_buf;
115 ret_buf =
116 (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
117 GFP_KERNEL);
118 if (ret_buf) {
119 memset(ret_buf, 0, sizeof (struct cifsTconInfo));
120 write_lock(&GlobalSMBSeslock);
121 atomic_inc(&tconInfoAllocCount);
122 list_add(&ret_buf->cifsConnectionList,
123 &GlobalTreeConnectionList);
124 ret_buf->tidStatus = CifsNew;
125 INIT_LIST_HEAD(&ret_buf->openFileList);
126 init_MUTEX(&ret_buf->tconSem);
127#ifdef CONFIG_CIFS_STATS
128 spin_lock_init(&ret_buf->stat_lock);
129#endif
130 write_unlock(&GlobalSMBSeslock);
131 }
132 return ret_buf;
133}
134
135void
136tconInfoFree(struct cifsTconInfo *buf_to_free)
137{
138 if (buf_to_free == NULL) {
139 cFYI(1, ("Null buffer passed to tconInfoFree"));
140 return;
141 }
142 write_lock(&GlobalSMBSeslock);
143 atomic_dec(&tconInfoAllocCount);
144 list_del(&buf_to_free->cifsConnectionList);
145 write_unlock(&GlobalSMBSeslock);
146 if (buf_to_free->nativeFileSystem)
147 kfree(buf_to_free->nativeFileSystem);
148 kfree(buf_to_free);
149}
150
151struct smb_hdr *
152cifs_buf_get(void)
153{
154 struct smb_hdr *ret_buf = NULL;
155
156/* We could use negotiated size instead of max_msgsize -
157 but it may be more efficient to always alloc same size
158 albeit slightly larger than necessary and maxbuffersize
159 defaults to this and can not be bigger */
160 ret_buf =
161 (struct smb_hdr *) mempool_alloc(cifs_req_poolp, SLAB_KERNEL | SLAB_NOFS);
162
163 /* clear the first few header bytes */
164 /* for most paths, more is cleared in header_assemble */
165 if (ret_buf) {
166 memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
167 atomic_inc(&bufAllocCount);
168 }
169
170 return ret_buf;
171}
172
173void
174cifs_buf_release(void *buf_to_free)
175{
176
177 if (buf_to_free == NULL) {
178 /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
179 return;
180 }
181 mempool_free(buf_to_free,cifs_req_poolp);
182
183 atomic_dec(&bufAllocCount);
184 return;
185}
186
187struct smb_hdr *
188cifs_small_buf_get(void)
189{
190 struct smb_hdr *ret_buf = NULL;
191
192/* We could use negotiated size instead of max_msgsize -
193 but it may be more efficient to always alloc same size
194 albeit slightly larger than necessary and maxbuffersize
195 defaults to this and can not be bigger */
196 ret_buf =
197 (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, SLAB_KERNEL | SLAB_NOFS);
198 if (ret_buf) {
199 /* No need to clear memory here, cleared in header assemble */
200 /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
201 atomic_inc(&smBufAllocCount);
202 }
203 return ret_buf;
204}
205
206void
207cifs_small_buf_release(void *buf_to_free)
208{
209
210 if (buf_to_free == NULL) {
211 cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
212 return;
213 }
214 mempool_free(buf_to_free,cifs_sm_req_poolp);
215
216 atomic_dec(&smBufAllocCount);
217 return;
218}
219
220void
221header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
222 const struct cifsTconInfo *treeCon, int word_count
223 /* length of fixed section (word count) in two byte units */)
224{
225 struct list_head* temp_item;
226 struct cifsSesInfo * ses;
227 char *temp = (char *) buffer;
228
229 memset(temp,0,MAX_CIFS_HDR_SIZE);
230
231 buffer->smb_buf_length =
232 (2 * word_count) + sizeof (struct smb_hdr) -
233 4 /* RFC 1001 length field does not count */ +
234 2 /* for bcc field itself */ ;
235 /* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */
236
237 buffer->Protocol[0] = 0xFF;
238 buffer->Protocol[1] = 'S';
239 buffer->Protocol[2] = 'M';
240 buffer->Protocol[3] = 'B';
241 buffer->Command = smb_command;
242 buffer->Flags = 0x00; /* case sensitive */
243 buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
244 buffer->Pid = cpu_to_le16((__u16)current->tgid);
245 buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
246 spin_lock(&GlobalMid_Lock);
247 GlobalMid++;
248 buffer->Mid = GlobalMid;
249 spin_unlock(&GlobalMid_Lock);
250 if (treeCon) {
251 buffer->Tid = treeCon->tid;
252 if (treeCon->ses) {
253 if (treeCon->ses->capabilities & CAP_UNICODE)
254 buffer->Flags2 |= SMBFLG2_UNICODE;
255 if (treeCon->ses->capabilities & CAP_STATUS32) {
256 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
257 }
258
259 buffer->Uid = treeCon->ses->Suid; /* always in LE format */
260 if(multiuser_mount != 0) {
261 /* For the multiuser case, there are few obvious technically */
262 /* possible mechanisms to match the local linux user (uid) */
263 /* to a valid remote smb user (smb_uid): */
264 /* 1) Query Winbind (or other local pam/nss daemon */
265 /* for userid/password/logon_domain or credential */
266 /* 2) Query Winbind for uid to sid to username mapping */
267 /* and see if we have a matching password for existing*/
268 /* session for that user perhas getting password by */
269 /* adding a new pam_cifs module that stores passwords */
270 /* so that the cifs vfs can get at that for all logged*/
271 /* on users */
272 /* 3) (Which is the mechanism we have chosen) */
273 /* Search through sessions to the same server for a */
274 /* a match on the uid that was passed in on mount */
275 /* with the current processes uid (or euid?) and use */
276 /* that smb uid. If no existing smb session for */
277 /* that uid found, use the default smb session ie */
278 /* the smb session for the volume mounted which is */
279 /* the same as would be used if the multiuser mount */
280 /* flag were disabled. */
281
282 /* BB Add support for establishing new tCon and SMB Session */
283 /* with userid/password pairs found on the smb session */
284 /* for other target tcp/ip addresses BB */
285 if(current->uid != treeCon->ses->linux_uid) {
286 cFYI(1,("Multiuser mode and UID did not match tcon uid "));
287 read_lock(&GlobalSMBSeslock);
288 list_for_each(temp_item, &GlobalSMBSessionList) {
289 ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
290 if(ses->linux_uid == current->uid) {
291 if(ses->server == treeCon->ses->server) {
292 cFYI(1,("found matching uid substitute right smb_uid"));
293 buffer->Uid = ses->Suid;
294 break;
295 } else {
296 /* BB eventually call cifs_setup_session here */
297 cFYI(1,("local UID found but smb sess with this server does not exist"));
298 }
299 }
300 }
301 read_unlock(&GlobalSMBSeslock);
302 }
303 }
304 }
305 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
306 buffer->Flags2 |= SMBFLG2_DFS;
307 if((treeCon->ses) && (treeCon->ses->server))
308 if(treeCon->ses->server->secMode &
309 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
310 buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
311 }
312
313/* endian conversion of flags is now done just before sending */
314 buffer->WordCount = (char) word_count;
315 return;
316}
317
318int
319checkSMBhdr(struct smb_hdr *smb, __u16 mid)
320{
321 /* Make sure that this really is an SMB, that it is a response,
322 and that the message ids match */
323 if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
324 (mid == smb->Mid)) {
325 if(smb->Flags & SMBFLG_RESPONSE)
326 return 0;
327 else {
328 /* only one valid case where server sends us request */
329 if(smb->Command == SMB_COM_LOCKING_ANDX)
330 return 0;
331 else
332 cERROR(1, ("Rcvd Request not response "));
333 }
334 } else { /* bad signature or mid */
335 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
336 cERROR(1,
337 ("Bad protocol string signature header %x ",
338 *(unsigned int *) smb->Protocol));
339 if (mid != smb->Mid)
340 cERROR(1, ("Mids do not match"));
341 }
342 cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
343 return 1;
344}
345
346int
347checkSMB(struct smb_hdr *smb, __u16 mid, int length)
348{
349 __u32 len = be32_to_cpu(smb->smb_buf_length);
350 cFYI(0,
351 ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
352 length, len));
353 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
354 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
355 if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
356 if (((unsigned int)length >=
357 sizeof (struct smb_hdr) - 1)
358 && (smb->Status.CifsError != 0)) {
359 smb->WordCount = 0;
360 return 0; /* some error cases do not return wct and bcc */
361 } else {
362 cERROR(1, ("Length less than smb header size"));
363 }
364
365 }
366 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
367 cERROR(1,
368 ("smb_buf_length greater than MaxBufSize"));
369 cERROR(1,
370 ("bad smb detected. Illegal length. The mid=%d",
371 smb->Mid));
372 return 1;
373 }
374
375 if (checkSMBhdr(smb, mid))
376 return 1;
377
378 if ((4 + len != smbCalcSize(smb))
379 || (4 + len != (unsigned int)length)) {
380 return 0;
381 } else {
382 cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
383 cERROR(1,
384 ("bad smb size detected. The Mid=%d", smb->Mid));
385 return 1;
386 }
387}
388int
389is_valid_oplock_break(struct smb_hdr *buf)
390{
391 struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
392 struct list_head *tmp;
393 struct list_head *tmp1;
394 struct cifsTconInfo *tcon;
395 struct cifsFileInfo *netfile;
396
397 cFYI(1,("Checking for oplock break or dnotify response"));
398 if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
399 (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
400 struct smb_com_transaction_change_notify_rsp * pSMBr =
401 (struct smb_com_transaction_change_notify_rsp *)buf;
402 struct file_notify_information * pnotify;
403 __u32 data_offset = 0;
404 if(pSMBr->ByteCount > sizeof(struct file_notify_information)) {
405 data_offset = le32_to_cpu(pSMBr->DataOffset);
406
407 pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol
408 + data_offset);
409 cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName,
410 pnotify->Action)); /* BB removeme BB */
411 /* cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */
412 return TRUE;
413 }
414 if(pSMBr->hdr.Status.CifsError) {
415 cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError));
416 return TRUE;
417 }
418 return FALSE;
419 }
420 if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
421 return FALSE;
422 if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
423 /* no sense logging error on invalid handle on oplock
424 break - harmless race between close request and oplock
425 break response is expected from time to time writing out
426 large dirty files cached on the client */
427 if ((NT_STATUS_INVALID_HANDLE) ==
428 le32_to_cpu(pSMB->hdr.Status.CifsError)) {
429 cFYI(1,("invalid handle on oplock break"));
430 return TRUE;
431 } else if (ERRbadfid ==
432 le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
433 return TRUE;
434 } else {
435 return FALSE; /* on valid oplock brk we get "request" */
436 }
437 }
438 if(pSMB->hdr.WordCount != 8)
439 return FALSE;
440
441 cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
442 if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
443 return FALSE;
444
445 /* look up tcon based on tid & uid */
446 read_lock(&GlobalSMBSeslock);
447 list_for_each(tmp, &GlobalTreeConnectionList) {
448 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
449 if (tcon->tid == buf->Tid) {
450#ifdef CONFIG_CIFS_STATS
451 atomic_inc(&tcon->num_oplock_brks);
452#endif
453 list_for_each(tmp1,&tcon->openFileList){
454 netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
455 if(pSMB->Fid == netfile->netfid) {
456 struct cifsInodeInfo *pCifsInode;
457 read_unlock(&GlobalSMBSeslock);
458 cFYI(1,("Matching file id, processing oplock break"));
459 pCifsInode =
460 CIFS_I(netfile->pInode);
461 pCifsInode->clientCanCacheAll = FALSE;
462 if(pSMB->OplockLevel == 0)
463 pCifsInode->clientCanCacheRead = FALSE;
464 pCifsInode->oplockPending = TRUE;
465 AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
466 cFYI(1,("about to wake up oplock thd"));
467 wake_up_process(oplockThread);
468 return TRUE;
469 }
470 }
471 read_unlock(&GlobalSMBSeslock);
472 cFYI(1,("No matching file for oplock break on connection"));
473 return TRUE;
474 }
475 }
476 read_unlock(&GlobalSMBSeslock);
477 cFYI(1,("Can not process oplock break for non-existent connection"));
478 return TRUE;
479}
480
481void
482dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
483{
484 int i, j;
485 char debug_line[17];
486 unsigned char *buffer;
487
488 if (traceSMB == 0)
489 return;
490
491 buffer = (unsigned char *) smb_buf;
492 for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
493 if (i % 8 == 0) { /* we have reached the beginning of line */
494 printk(KERN_DEBUG "| ");
495 j = 0;
496 }
497 printk("%0#4x ", buffer[i]);
498 debug_line[2 * j] = ' ';
499 if (isprint(buffer[i]))
500 debug_line[1 + (2 * j)] = buffer[i];
501 else
502 debug_line[1 + (2 * j)] = '_';
503
504 if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
505 debug_line[16] = 0;
506 printk(" | %s\n", debug_line);
507 }
508 }
509 for (; j < 8; j++) {
510 printk(" ");
511 debug_line[2 * j] = ' ';
512 debug_line[1 + (2 * j)] = ' ';
513 }
514 printk( " | %s\n", debug_line);
515 return;
516}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
new file mode 100644
index 000000000000..4e34c89cec5d
--- /dev/null
+++ b/fs/cifs/netmisc.c
@@ -0,0 +1,904 @@
1/*
2 * fs/cifs/netmisc.c
3 *
4 * Copyright (c) International Business Machines Corp., 2002
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Error mapping routines from Samba libsmb/errormap.c
8 * Copyright (C) Andrew Tridgell 2001
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26#include <linux/net.h>
27#include <linux/string.h>
28#include <linux/in.h>
29#include <linux/ctype.h>
30#include <linux/fs.h>
31#include <asm/div64.h>
32#include <asm/byteorder.h>
33#include "cifsfs.h"
34#include "cifspdu.h"
35#include "cifsglob.h"
36#include "cifsproto.h"
37#include "smberr.h"
38#include "cifs_debug.h"
39#include "nterr.h"
40
41struct smb_to_posix_error {
42 __u16 smb_err;
43 int posix_code;
44};
45
46static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
47 {ERRbadfunc, -EINVAL},
48 {ERRbadfile, -ENOENT},
49 {ERRbadpath, -ENOTDIR},
50 {ERRnofids, -EMFILE},
51 {ERRnoaccess, -EACCES},
52 {ERRbadfid, -EBADF},
53 {ERRbadmcb, -EIO},
54 {ERRnomem, -ENOMEM},
55 {ERRbadmem, -EFAULT},
56 {ERRbadenv, -EFAULT},
57 {ERRbadformat, -EINVAL},
58 {ERRbadaccess, -EACCES},
59 {ERRbaddata, -EIO},
60 {ERRbaddrive, -ENXIO},
61 {ERRremcd, -EACCES},
62 {ERRdiffdevice, -EXDEV},
63 {ERRnofiles, -ENOENT},
64 {ERRbadshare, -ETXTBSY},
65 {ERRlock, -EACCES},
66 {ERRunsup, -EINVAL},
67 {ERRnosuchshare,-ENXIO},
68 {ERRfilexists, -EEXIST},
69 {ERRinvparm, -EINVAL},
70 {ERRdiskfull, -ENOSPC},
71 {ERRinvname, -ENOENT},
72 {ERRinvlevel,-EOPNOTSUPP},
73 {ERRdirnotempty, -ENOTEMPTY},
74 {ERRnotlocked, -ENOLCK},
75 {ERRalreadyexists, -EEXIST},
76 {ERRmoredata, -EOVERFLOW},
77 {ERReasnotsupported,-EOPNOTSUPP},
78 {ErrQuota, -EDQUOT},
79 {ErrNotALink, -ENOLINK},
80 {ERRnetlogonNotStarted,-ENOPROTOOPT},
81 {0, 0}
82};
83
84static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
85 {ERRerror, -EIO},
86 {ERRbadpw, -EPERM},
87 {ERRbadtype, -EREMOTE},
88 {ERRaccess, -EACCES},
89 {ERRinvtid, -ENXIO},
90 {ERRinvnetname, -ENODEV},
91 {ERRinvdevice, -ENXIO},
92 {ERRqfull, -ENOSPC},
93 {ERRqtoobig, -ENOSPC},
94 {ERRqeof, -EIO},
95 {ERRinvpfid, -EBADF},
96 {ERRsmbcmd, -EBADRQC},
97 {ERRsrverror, -EIO},
98 {ERRbadBID, -EIO},
99 {ERRfilespecs, -EINVAL},
100 {ERRbadLink, -EIO},
101 {ERRbadpermits, -EINVAL},
102 {ERRbadPID, -ESRCH},
103 {ERRsetattrmode, -EINVAL},
104 {ERRpaused, -EHOSTDOWN},
105 {ERRmsgoff, -EHOSTDOWN},
106 {ERRnoroom, -ENOSPC},
107 {ERRrmuns, -EUSERS},
108 {ERRtimeout, -ETIME},
109 {ERRnoresource, -ENOBUFS},
110 {ERRtoomanyuids, -EUSERS},
111 {ERRbaduid, -EACCES},
112 {ERRusempx, -EIO},
113 {ERRusestd, -EIO},
114 {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
115 {ERRaccountexpired, -EACCES},
116 {ERRbadclient, -EACCES},
117 {ERRbadLogonTime, -EACCES},
118 {ERRpasswordExpired, -EACCES},
119 {ERRnosupport, -EINVAL},
120 {0, 0}
121};
122
123static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
124 {0, 0}
125};
126
127/* Convert string containing dotted ip address to binary form */
128/* returns 0 if invalid address */
129
130/* BB add address family, change rc to status flag and return union or for ipv6 */
131/* will need parent to call something like inet_pton to convert ipv6 address BB */
132int
133cifs_inet_pton(int address_family, char *cp,void *dst)
134{
135 struct in_addr address;
136 int value;
137 int digit;
138 int i;
139 char temp;
140 char bytes[4];
141 char *end = bytes;
142 static const int addr_class_max[4] =
143 { 0xffffffff, 0xffffff, 0xffff, 0xff };
144
145 if(address_family != AF_INET)
146 return -EAFNOSUPPORT;
147
148 for (i = 0; i < 4; i++) {
149 bytes[i] = 0;
150 }
151
152 temp = *cp;
153
154 while (TRUE) {
155 if (!isdigit(temp))
156 return 0;
157
158 value = 0;
159 digit = 0;
160 for (;;) {
161 if (isascii(temp) && isdigit(temp)) {
162 value = (value * 10) + temp - '0';
163 temp = *++cp;
164 digit = 1;
165 } else
166 break;
167 }
168
169 if (temp == '.') {
170 if ((end > bytes + 2) || (value > 255))
171 return 0;
172 *end++ = value;
173 temp = *++cp;
174 } else if (temp == ':') {
175 cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
176 return -1;
177 } else
178 break;
179 }
180
181 /* check for last characters */
182 if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
183 if (temp != '\\') {
184 if (temp != '/')
185 return 0;
186 else
187 (*cp = '\\'); /* switch the slash the expected way */
188 }
189 if (value > addr_class_max[end - bytes])
190 return 0;
191
192 address.s_addr = *((__be32 *) bytes) | htonl(value);
193 *((__be32 *)dst) = address.s_addr;
194 return 1; /* success */
195}
196
197/*****************************************************************************
198convert a NT status code to a dos class/code
199 *****************************************************************************/
200/* NT status -> dos error map */
201static const struct {
202 __u8 dos_class;
203 __u16 dos_code;
204 __u32 ntstatus;
205} ntstatus_to_dos_map[] = {
206 {
207 ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
208 ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
209 ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
210 ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
211 ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
212 ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
213 ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
214 ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
215 ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
216 ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
217 ERRDOS, 87, NT_STATUS_INVALID_CID}, {
218 ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
219 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
220 ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
221 ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
222 ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
223 ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
224 ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
225 ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
226 ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
227 ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
228/* { This NT error code was 'sqashed'
229 from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK
230 during the session setup } */
231 {
232 ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
233 ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
234 ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
235 ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
236 ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
237 ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
238 ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
239 ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
240 ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
241 ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
242 ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
243/* { This NT error code was 'sqashed'
244 from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
245 during the session setup } */
246 {
247 ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
248 ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
249 ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
250 ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
251 ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
252 ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
253 ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
254 ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
255 ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
256 ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
257 ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
258 ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
259 ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
260 ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
261 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
262 ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
263 ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
264 ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, { /* mapping changed since shell does lookup on * and expects file not found */
265 ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
266 ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
267 ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
268 ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
269 ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
270 ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
271 ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
272 ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
273 ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
274 ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
275 ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
276 ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
277 ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
278 ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
279 ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
280 ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
281 ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
282 ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
283 ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
284 ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
285 ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
286 ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
287 ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
288 ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
289 ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
290 ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
291 ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
292 ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED}, {
293 ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
294 ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
295 ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
296 ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
297 ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
298 ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
299 ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
300 ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
301 ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
302 ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
303 ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
304 ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
305 ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
306 ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
307 ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
308 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
309 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
310 ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
311 ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
312 ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
313/* { This NT error code was 'sqashed'
314 from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
315 during the session setup } */
316 {
317 ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
318 ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
319 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
320 ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
321 ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
322 ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
323/* { This NT error code was 'sqashed'
324 from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE
325 during the session setup } */
326 {
327 ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
328 ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
329 ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
330 ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
331 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
332 ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
333 ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
334 ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
335 ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
336 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
337 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
338 ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
339 ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
340 ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
341 ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
342 ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
343 ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
344 ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
345 ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
346 ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
347 ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
348 ERRDOS, 112, NT_STATUS_DISK_FULL}, {
349 ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
350 ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
351 ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
352 ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
353 ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
354 ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
355 ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
356 ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
357 ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
358 ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
359 ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
360 ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
361 ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
362 ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
363 ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
364 ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
365 ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
366 ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
367 ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
368 ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
369 ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
370 ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
371 ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
372 ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
373 ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
374 ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
375/* { This NT error code was 'sqashed'
376 from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
377 during the session setup } */
378 {
379 ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
380 ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
381 ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
382 ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
383 ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
384 ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
385 ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
386 ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
387 ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
388 ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
389 ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
390 ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
391 ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
392 ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
393 ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
394 ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
395 ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
396 ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
397 ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
398 ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
399 ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
400 ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
401 ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
402 ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
403 ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
404 ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
405 ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
406 ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
407 ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
408 ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
409 ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
410 ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
411 ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
412 ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
413 ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
414 ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
415 ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
416 ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
417 ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
418 ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
419 ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
420 ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
421 ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
422 ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
423 ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
424 ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
425 ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
426 ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
427 ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
428 ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
429 ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
430 ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
431 ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
432 ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
433 ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
434 ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
435 ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
436 ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
437 ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
438 ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
439 ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
440 ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
441 ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
442 ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
443 ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
444 ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
445 ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
446 ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
447 ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
448 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
449 ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
450 ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
451 ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
452 ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
453 ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
454 ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
455 ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
456 ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
457 ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
458 ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
459 ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
460 ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
461 ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
462 ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
463 ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
464 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
465 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
466 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
467 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
468 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
469 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
470 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
471 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
472 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
473 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
474 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
475 ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
476 ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
477 ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
478 ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
479 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
480 ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
481 ERRDOS, 203, 0xc0000100}, {
482 ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
483 ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
484 ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
485 ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
486 ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
487 ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
488 ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
489 ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
490 ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
491 ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
492 ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
493 ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
494 ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
495 ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
496 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
497 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
498 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
499 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
500 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
501 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
502 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
503 ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
504 ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
505 ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
506 ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
507 ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
508 ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
509 ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
510 ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
511 ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
512 ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
513 ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
514 ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
515 ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
516 ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
517 ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
518 ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
519 ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
520 ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
521 ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
522 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
523 ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
524 ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
525 ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
526 ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
527 ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
528 ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
529 ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
530 ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
531 ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
532 ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
533 ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
534 ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
535 ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
536 ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
537 ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
538 ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
539 ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
540 ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
541 ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
542 ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
543 ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
544 ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
545 ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
546 ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
547 ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
548 ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
549 ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
550 ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
551 ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
552 ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
553 ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
554 ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
555 ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
556 ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
557 ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
558 ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
559 ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
560 ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
561 ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
562 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
563 ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
564 ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
565 ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
566 ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
567 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
568 ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
569 ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
570 ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
571 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
572 ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
573 ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
574 ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
575 ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
576 ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
577 ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
578 ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
579 ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
580 ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
581 ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
582 ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
583 ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
584 ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
585 ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
586 ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
587 ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
588 ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
589 ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
590 ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
591 ERRHRD, ERRgeneral, 0xc000016e}, {
592 ERRHRD, ERRgeneral, 0xc000016f}, {
593 ERRHRD, ERRgeneral, 0xc0000170}, {
594 ERRHRD, ERRgeneral, 0xc0000171}, {
595 ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
596 ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
597 ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
598 ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
599 ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
600 ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
601 ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
602 ERRHRD, ERRgeneral, 0xc0000179}, {
603 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
604 ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
605 ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
606 ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
607 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
608 ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
609 ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
610 ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
611 ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
612 ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
613 ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
614 ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
615 ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
616 ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
617 ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
618 ERRDOS, 19, NT_STATUS_TOO_LATE}, {
619 ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
620/* { This NT error code was 'sqashed'
621 from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
622 during the session setup } */
623 {
624 ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
625 ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
626 ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
627 ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
628 ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
629 ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
630 ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
631 ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
632 ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
633 ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
634 ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
635 ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
636 ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
637 ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
638 ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
639 ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
640/* { This NT error code was 'sqashed'
641 from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE
642 during the session setup } */
643 {
644 ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
645 ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
646 ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
647 ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
648 ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
649 ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
650 ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
651 ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
652 ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
653 ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
654 ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
655 ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
656 ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
657 ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
658 ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
659 ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
660 ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
661 ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
662 ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
663 ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
664 ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
665 ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
666 ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
667 ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
668 ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
669 ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
670 ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
671 ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
672 ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
673 ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
674 ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
675 ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
676 ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
677 ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
678 ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
679 ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
680 ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
681 ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
682 ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
683 ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
684 ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
685 ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
686 ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
687 ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
688 ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
689 ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
690 ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
691 ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
692 ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
693 ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
694 ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
695 ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
696 ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
697 ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
698 ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
699 ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
700 ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
701 ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
702 ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
703 ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
704 ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
705 ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
706 ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
707 ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
708 ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
709 ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
710 ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
711 ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
712 ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
713 ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
714 ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
715 ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
716 ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
717 ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
718 ERRHRD, ERRgeneral, 0xc000024a}, {
719 ERRHRD, ERRgeneral, 0xc000024b}, {
720 ERRHRD, ERRgeneral, 0xc000024c}, {
721 ERRHRD, ERRgeneral, 0xc000024d}, {
722 ERRHRD, ERRgeneral, 0xc000024e}, {
723 ERRHRD, ERRgeneral, 0xc000024f}, {
724 ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
725 ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
726 ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
727 ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
728 ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
729 ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
730 ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
731 ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
732 ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
733 ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
734 ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
735 ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
736 ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
737 ERRHRD, ERRgeneral, 0xc000025d}, {
738 ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
739 ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
740 ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
741 ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
742 ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
743 ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
744 ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
745 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
746 ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
747 ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
748 ERRDOS, 21, 0xc000026e}, {
749 ERRDOS, 161, 0xc0000281}, {
750 ERRDOS, ERRnoaccess, 0xc000028a}, {
751 ERRDOS, ERRnoaccess, 0xc000028b}, {
752 ERRHRD, ERRgeneral, 0xc000028c}, {
753 ERRDOS, ERRnoaccess, 0xc000028d}, {
754 ERRDOS, ERRnoaccess, 0xc000028e}, {
755 ERRDOS, ERRnoaccess, 0xc000028f}, {
756 ERRDOS, ERRnoaccess, 0xc0000290}, {
757 ERRDOS, ERRbadfunc, 0xc000029c}, {
758 ERRDOS, ERRinvlevel, 0x007c0001}, };
759
760/*****************************************************************************
761 Print an error message from the status code
762 *****************************************************************************/
763static void
764cifs_print_status(__u32 status_code)
765{
766 int idx = 0;
767
768 while (nt_errs[idx].nt_errstr != NULL) {
769 if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
770 (status_code & 0xFFFFFF)) {
771 printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
772 status_code,nt_errs[idx].nt_errstr);
773 }
774 idx++;
775 }
776 return;
777}
778
779
780static void
781ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
782{
783 int i;
784 if (ntstatus == 0) {
785 *eclass = 0;
786 *ecode = 0;
787 return;
788 }
789 for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
790 if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
791 *eclass = ntstatus_to_dos_map[i].dos_class;
792 *ecode = ntstatus_to_dos_map[i].dos_code;
793 return;
794 }
795 }
796 *eclass = ERRHRD;
797 *ecode = ERRgeneral;
798}
799
800int
801map_smb_to_linux_error(struct smb_hdr *smb)
802{
803 unsigned int i;
804 int rc = -EIO; /* if transport error smb error may not be set */
805 __u8 smberrclass;
806 __u16 smberrcode;
807
808 /* BB if NT Status codes - map NT BB */
809
810 /* old style smb error codes */
811 if (smb->Status.CifsError == 0)
812 return 0;
813
814 if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
815 /* translate the newer STATUS codes to old style errors and then to POSIX errors */
816 __u32 err = le32_to_cpu(smb->Status.CifsError);
817 if(cifsFYI)
818 cifs_print_status(err);
819 ntstatus_to_dos(err, &smberrclass, &smberrcode);
820 } else {
821 smberrclass = smb->Status.DosError.ErrorClass;
822 smberrcode = le16_to_cpu(smb->Status.DosError.Error);
823 }
824
825 /* old style errors */
826
827 /* DOS class smb error codes - map DOS */
828 if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
829 for (i = 0;
830 i <
831 sizeof (mapping_table_ERRDOS) /
832 sizeof (struct smb_to_posix_error); i++) {
833 if (mapping_table_ERRDOS[i].smb_err == 0)
834 break;
835 else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
836 rc = mapping_table_ERRDOS[i].posix_code;
837 break;
838 }
839 /* else try the next error mapping one to see if it will match */
840 }
841 } else if (smberrclass == ERRSRV) { /* server class of error codes */
842 for (i = 0;
843 i <
844 sizeof (mapping_table_ERRSRV) /
845 sizeof (struct smb_to_posix_error); i++) {
846 if (mapping_table_ERRSRV[i].smb_err == 0)
847 break;
848 else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
849 rc = mapping_table_ERRSRV[i].posix_code;
850 break;
851 }
852 /* else try the next error mapping one to see if it will match */
853 }
854 }
855 /* else ERRHRD class errors or junk - return EIO */
856
857 cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
858
859 /* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
860
861 return rc;
862}
863
864/*
865 * calculate the size of the SMB message based on the fixed header
866 * portion, the number of word parameters and the data portion of the message
867 */
868unsigned int
869smbCalcSize(struct smb_hdr *ptr)
870{
871 return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
872 BCC(ptr));
873}
874
875/* The following are taken from fs/ntfs/util.c */
876
877#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
878
879 /*
880 * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
881 * into Unix UTC (based 1970-01-01, in seconds).
882 */
883struct timespec
884cifs_NTtimeToUnix(u64 ntutc)
885{
886 struct timespec ts;
887 /* BB what about the timezone? BB */
888
889 /* Subtract the NTFS time offset, then convert to 1s intervals. */
890 u64 t;
891
892 t = ntutc - NTFS_TIME_OFFSET;
893 ts.tv_nsec = do_div(t, 10000000) * 100;
894 ts.tv_sec = t;
895 return ts;
896}
897
898/* Convert the Unix UTC into NT UTC. */
899u64
900cifs_UnixTimeToNT(struct timespec t)
901{
902 /* Convert to 100ns intervals and then add the NTFS time offset. */
903 return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
904}
diff --git a/fs/cifs/nterr.c b/fs/cifs/nterr.c
new file mode 100644
index 000000000000..4da50cd34469
--- /dev/null
+++ b/fs/cifs/nterr.c
@@ -0,0 +1,687 @@
1/*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
4 * RPC Pipe client / server routines
5 * Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22/* NT error codes - see nterr.h */
23#include <linux/types.h>
24#include <linux/fs.h>
25#include "nterr.h"
26
27const struct nt_err_code_struct nt_errs[] = {
28 {"NT_STATUS_OK", NT_STATUS_OK},
29 {"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
30 {"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
31 {"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
32 {"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
33 {"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
34 {"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
35 {"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
36 {"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
37 {"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
38 {"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
39 {"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
40 {"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
41 {"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
42 {"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
43 {"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
44 {"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
45 {"NT_STATUS_INVALID_DEVICE_REQUEST",
46 NT_STATUS_INVALID_DEVICE_REQUEST},
47 {"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
48 {"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
49 {"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
50 {"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
51 {"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
52 {"NT_STATUS_MORE_PROCESSING_REQUIRED",
53 NT_STATUS_MORE_PROCESSING_REQUIRED},
54 {"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
55 {"NT_STATUS_CONFLICTING_ADDRESSES",
56 NT_STATUS_CONFLICTING_ADDRESSES},
57 {"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
58 {"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
59 {"NT_STATUS_UNABLE_TO_DELETE_SECTION",
60 NT_STATUS_UNABLE_TO_DELETE_SECTION},
61 {"NT_STATUS_INVALID_SYSTEM_SERVICE",
62 NT_STATUS_INVALID_SYSTEM_SERVICE},
63 {"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
64 {"NT_STATUS_INVALID_LOCK_SEQUENCE",
65 NT_STATUS_INVALID_LOCK_SEQUENCE},
66 {"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
67 {"NT_STATUS_INVALID_FILE_FOR_SECTION",
68 NT_STATUS_INVALID_FILE_FOR_SECTION},
69 {"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
70 {"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
71 {"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
72 {"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
73 {"NT_STATUS_NONCONTINUABLE_EXCEPTION",
74 NT_STATUS_NONCONTINUABLE_EXCEPTION},
75 {"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
76 {"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
77 {"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
78 {"NT_STATUS_INVALID_UNWIND_TARGET",
79 NT_STATUS_INVALID_UNWIND_TARGET},
80 {"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
81 {"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
82 {"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
83 NT_STATUS_UNABLE_TO_DECOMMIT_VM},
84 {"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
85 {"NT_STATUS_INVALID_PORT_ATTRIBUTES",
86 NT_STATUS_INVALID_PORT_ATTRIBUTES},
87 {"NT_STATUS_PORT_MESSAGE_TOO_LONG",
88 NT_STATUS_PORT_MESSAGE_TOO_LONG},
89 {"NT_STATUS_INVALID_PARAMETER_MIX",
90 NT_STATUS_INVALID_PARAMETER_MIX},
91 {"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
92 {"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
93 {"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
94 {"NT_STATUS_OBJECT_NAME_NOT_FOUND",
95 NT_STATUS_OBJECT_NAME_NOT_FOUND},
96 {"NT_STATUS_OBJECT_NAME_COLLISION",
97 NT_STATUS_OBJECT_NAME_COLLISION},
98 {"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
99 {"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
100 {"NT_STATUS_DEVICE_ALREADY_ATTACHED",
101 NT_STATUS_DEVICE_ALREADY_ATTACHED},
102 {"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
103 {"NT_STATUS_OBJECT_PATH_NOT_FOUND",
104 NT_STATUS_OBJECT_PATH_NOT_FOUND},
105 {"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
106 NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
107 {"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
108 {"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
109 {"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
110 {"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
111 {"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
112 {"NT_STATUS_PORT_CONNECTION_REFUSED",
113 NT_STATUS_PORT_CONNECTION_REFUSED},
114 {"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
115 {"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
116 {"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
117 {"NT_STATUS_INVALID_PAGE_PROTECTION",
118 NT_STATUS_INVALID_PAGE_PROTECTION},
119 {"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
120 {"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
121 NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
122 {"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
123 {"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
124 {"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
125 NT_STATUS_SUSPEND_COUNT_EXCEEDED},
126 {"NT_STATUS_THREAD_IS_TERMINATING",
127 NT_STATUS_THREAD_IS_TERMINATING},
128 {"NT_STATUS_BAD_WORKING_SET_LIMIT",
129 NT_STATUS_BAD_WORKING_SET_LIMIT},
130 {"NT_STATUS_INCOMPATIBLE_FILE_MAP",
131 NT_STATUS_INCOMPATIBLE_FILE_MAP},
132 {"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
133 {"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
134 {"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
135 {"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
136 {"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
137 {"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
138 {"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
139 {"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
140 {"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
141 {"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
142 NT_STATUS_CTL_FILE_NOT_SUPPORTED},
143 {"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
144 {"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
145 {"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
146 {"NT_STATUS_INVALID_PRIMARY_GROUP",
147 NT_STATUS_INVALID_PRIMARY_GROUP},
148 {"NT_STATUS_NO_IMPERSONATION_TOKEN",
149 NT_STATUS_NO_IMPERSONATION_TOKEN},
150 {"NT_STATUS_CANT_DISABLE_MANDATORY",
151 NT_STATUS_CANT_DISABLE_MANDATORY},
152 {"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
153 {"NT_STATUS_NO_SUCH_LOGON_SESSION",
154 NT_STATUS_NO_SUCH_LOGON_SESSION},
155 {"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
156 {"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
157 {"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
158 {"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
159 {"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
160 {"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
161 {"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
162 {"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
163 {"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
164 {"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
165 {"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
166 {"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
167 {"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
168 {"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
169 {"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
170 {"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
171 {"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
172 {"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
173 {"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
174 {"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
175 {"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
176 NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
177 {"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
178 {"NT_STATUS_INVALID_SUB_AUTHORITY",
179 NT_STATUS_INVALID_SUB_AUTHORITY},
180 {"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
181 {"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
182 {"NT_STATUS_INVALID_SECURITY_DESCR",
183 NT_STATUS_INVALID_SECURITY_DESCR},
184 {"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
185 {"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
186 {"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
187 {"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
188 {"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
189 {"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
190 {"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
191 {"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
192 {"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
193 NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
194 {"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
195 {"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
196 {"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
197 {"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
198 {"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
199 {"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
200 {"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
201 NT_STATUS_RESOURCE_DATA_NOT_FOUND},
202 {"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
203 NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
204 {"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
205 NT_STATUS_RESOURCE_NAME_NOT_FOUND},
206 {"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
207 NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
208 {"NT_STATUS_FLOAT_DENORMAL_OPERAND",
209 NT_STATUS_FLOAT_DENORMAL_OPERAND},
210 {"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
211 {"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
212 {"NT_STATUS_FLOAT_INVALID_OPERATION",
213 NT_STATUS_FLOAT_INVALID_OPERATION},
214 {"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
215 {"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
216 {"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
217 {"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
218 NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
219 {"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
220 {"NT_STATUS_PRIVILEGED_INSTRUCTION",
221 NT_STATUS_PRIVILEGED_INSTRUCTION},
222 {"NT_STATUS_TOO_MANY_PAGING_FILES",
223 NT_STATUS_TOO_MANY_PAGING_FILES},
224 {"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
225 {"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
226 NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
227 {"NT_STATUS_INSUFFICIENT_RESOURCES",
228 NT_STATUS_INSUFFICIENT_RESOURCES},
229 {"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
230 {"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
231 {"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
232 {"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
233 {"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
234 {"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
235 {"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
236 {"NT_STATUS_MEDIA_WRITE_PROTECTED",
237 NT_STATUS_MEDIA_WRITE_PROTECTED},
238 {"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
239 {"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
240 NT_STATUS_INVALID_GROUP_ATTRIBUTES},
241 {"NT_STATUS_BAD_IMPERSONATION_LEVEL",
242 NT_STATUS_BAD_IMPERSONATION_LEVEL},
243 {"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
244 {"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
245 {"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
246 {"NT_STATUS_BAD_MASTER_BOOT_RECORD",
247 NT_STATUS_BAD_MASTER_BOOT_RECORD},
248 {"NT_STATUS_INSTRUCTION_MISALIGNMENT",
249 NT_STATUS_INSTRUCTION_MISALIGNMENT},
250 {"NT_STATUS_INSTANCE_NOT_AVAILABLE",
251 NT_STATUS_INSTANCE_NOT_AVAILABLE},
252 {"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
253 {"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
254 {"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
255 {"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
256 {"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
257 {"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
258 {"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
259 {"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
260 {"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
261 {"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
262 {"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
263 {"NT_STATUS_PROFILING_NOT_STARTED",
264 NT_STATUS_PROFILING_NOT_STARTED},
265 {"NT_STATUS_PROFILING_NOT_STOPPED",
266 NT_STATUS_PROFILING_NOT_STOPPED},
267 {"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
268 {"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
269 {"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
270 {"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
271 {"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
272 {"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
273 {"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
274 {"NT_STATUS_DEVICE_DOES_NOT_EXIST",
275 NT_STATUS_DEVICE_DOES_NOT_EXIST},
276 {"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
277 {"NT_STATUS_ADAPTER_HARDWARE_ERROR",
278 NT_STATUS_ADAPTER_HARDWARE_ERROR},
279 {"NT_STATUS_INVALID_NETWORK_RESPONSE",
280 NT_STATUS_INVALID_NETWORK_RESPONSE},
281 {"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
282 NT_STATUS_UNEXPECTED_NETWORK_ERROR},
283 {"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
284 {"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
285 {"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
286 {"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
287 {"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
288 {"NT_STATUS_NETWORK_ACCESS_DENIED",
289 NT_STATUS_NETWORK_ACCESS_DENIED},
290 {"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
291 {"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
292 {"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
293 {"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
294 {"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
295 {"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
296 {"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
297 {"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
298 {"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
299 {"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
300 {"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
301 {"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
302 NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
303 {"NT_STATUS_NO_SECURITY_ON_OBJECT",
304 NT_STATUS_NO_SECURITY_ON_OBJECT},
305 {"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
306 {"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
307 {"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
308 NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
309 {"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
310 {"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
311 {"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
312 {"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
313 {"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
314 {"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
315 {"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
316 NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
317 {"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
318 {"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
319 NT_STATUS_INVALID_OPLOCK_PROTOCOL},
320 {"NT_STATUS_INTERNAL_DB_CORRUPTION",
321 NT_STATUS_INTERNAL_DB_CORRUPTION},
322 {"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
323 {"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
324 {"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
325 NT_STATUS_BAD_DESCRIPTOR_FORMAT},
326 {"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
327 {"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
328 {"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
329 NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
330 {"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
331 NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
332 {"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
333 NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
334 {"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
335 {"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
336 {"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
337 {"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
338 {"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
339 {"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
340 {"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
341 {"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
342 {"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
343 {"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
344 {"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
345 {"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
346 {"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
347 {"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
348 {"NT_STATUS_REDIRECTOR_NOT_STARTED",
349 NT_STATUS_REDIRECTOR_NOT_STARTED},
350 {"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
351 {"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
352 {"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
353 {"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
354 {"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
355 {"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
356 {"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
357 {"NT_STATUS_BAD_LOGON_SESSION_STATE",
358 NT_STATUS_BAD_LOGON_SESSION_STATE},
359 {"NT_STATUS_LOGON_SESSION_COLLISION",
360 NT_STATUS_LOGON_SESSION_COLLISION},
361 {"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
362 {"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
363 {"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
364 {"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
365 {"NT_STATUS_PROCESS_IS_TERMINATING",
366 NT_STATUS_PROCESS_IS_TERMINATING},
367 {"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
368 {"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
369 {"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
370 {"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
371 {"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
372 {"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
373 {"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
374 NT_STATUS_ABIOS_LID_ALREADY_OWNED},
375 {"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
376 {"NT_STATUS_ABIOS_INVALID_COMMAND",
377 NT_STATUS_ABIOS_INVALID_COMMAND},
378 {"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
379 {"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
380 NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
381 {"NT_STATUS_ABIOS_INVALID_SELECTOR",
382 NT_STATUS_ABIOS_INVALID_SELECTOR},
383 {"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
384 {"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
385 {"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
386 {"NT_STATUS_INVALID_LDT_DESCRIPTOR",
387 NT_STATUS_INVALID_LDT_DESCRIPTOR},
388 {"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
389 NT_STATUS_INVALID_IMAGE_NE_FORMAT},
390 {"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
391 {"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
392 {"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
393 NT_STATUS_MAPPED_FILE_SIZE_ZERO},
394 {"NT_STATUS_TOO_MANY_OPENED_FILES",
395 NT_STATUS_TOO_MANY_OPENED_FILES},
396 {"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
397 {"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
398 {"NT_STATUS_INVALID_COMPUTER_NAME",
399 NT_STATUS_INVALID_COMPUTER_NAME},
400 {"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
401 {"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
402 {"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
403 {"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
404 {"NT_STATUS_MEMBERS_PRIMARY_GROUP",
405 NT_STATUS_MEMBERS_PRIMARY_GROUP},
406 {"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
407 {"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
408 {"NT_STATUS_THREAD_NOT_IN_PROCESS",
409 NT_STATUS_THREAD_NOT_IN_PROCESS},
410 {"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
411 {"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
412 NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
413 {"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
414 {"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
415 NT_STATUS_INVALID_IMAGE_LE_FORMAT},
416 {"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
417 {"NT_STATUS_INVALID_IMAGE_PROTECT",
418 NT_STATUS_INVALID_IMAGE_PROTECT},
419 {"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
420 {"NT_STATUS_LOGON_SERVER_CONFLICT",
421 NT_STATUS_LOGON_SERVER_CONFLICT},
422 {"NT_STATUS_TIME_DIFFERENCE_AT_DC",
423 NT_STATUS_TIME_DIFFERENCE_AT_DC},
424 {"NT_STATUS_SYNCHRONIZATION_REQUIRED",
425 NT_STATUS_SYNCHRONIZATION_REQUIRED},
426 {"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
427 {"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
428 {"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
429 {"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
430 {"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
431 {"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
432 {"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
433 {"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
434 {"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
435 {"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
436 {"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
437 {"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
438 {"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
439 {"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
440 {"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
441 {"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
442 {"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
443 {"NT_STATUS_PAGEFILE_CREATE_FAILED",
444 NT_STATUS_PAGEFILE_CREATE_FAILED},
445 {"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
446 {"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
447 {"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
448 {"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
449 NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
450 {"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
451 {"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
452 {"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
453 {"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
454 {"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
455 {"NT_STATUS_SERIAL_NO_DEVICE_INITED",
456 NT_STATUS_SERIAL_NO_DEVICE_INITED},
457 {"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
458 {"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
459 {"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
460 {"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
461 {"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
462 {"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
463 {"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
464 {"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
465 {"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
466 {"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
467 {"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
468 NT_STATUS_LOGON_TYPE_NOT_GRANTED},
469 {"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
470 {"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
471 NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
472 {"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
473 NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
474 {"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
475 {"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
476 NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
477 {"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
478 {"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
479 {"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
480 {"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
481 {"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
482 NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
483 {"NT_STATUS_FLOPPY_WRONG_CYLINDER",
484 NT_STATUS_FLOPPY_WRONG_CYLINDER},
485 {"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
486 {"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
487 {"NT_STATUS_DISK_RECALIBRATE_FAILED",
488 NT_STATUS_DISK_RECALIBRATE_FAILED},
489 {"NT_STATUS_DISK_OPERATION_FAILED",
490 NT_STATUS_DISK_OPERATION_FAILED},
491 {"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
492 {"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
493 {"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
494 {"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
495 {"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
496 {"NT_STATUS_DEVICE_NOT_PARTITIONED",
497 NT_STATUS_DEVICE_NOT_PARTITIONED},
498 {"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
499 {"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
500 NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
501 {"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
502 {"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
503 {"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
504 {"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
505 {"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
506 {"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
507 {"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
508 {"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
509 NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
510 {"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
511 {"NT_STATUS_CHILD_MUST_BE_VOLATILE",
512 NT_STATUS_CHILD_MUST_BE_VOLATILE},
513 {"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
514 NT_STATUS_DEVICE_CONFIGURATION_ERROR},
515 {"NT_STATUS_DRIVER_INTERNAL_ERROR",
516 NT_STATUS_DRIVER_INTERNAL_ERROR},
517 {"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
518 {"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
519 {"NT_STATUS_DEVICE_PROTOCOL_ERROR",
520 NT_STATUS_DEVICE_PROTOCOL_ERROR},
521 {"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
522 {"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
523 {"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
524 {"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
525 {"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
526 {"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
527 NT_STATUS_TRUSTED_DOMAIN_FAILURE},
528 {"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
529 NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
530 {"NT_STATUS_EVENTLOG_FILE_CORRUPT",
531 NT_STATUS_EVENTLOG_FILE_CORRUPT},
532 {"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
533 {"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
534 {"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
535 NT_STATUS_MUTANT_LIMIT_EXCEEDED},
536 {"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
537 {"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
538 {"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
539 {"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
540 NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
541 {"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
542 {"NT_STATUS_EVENTLOG_FILE_CHANGED",
543 NT_STATUS_EVENTLOG_FILE_CHANGED},
544 {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
545 NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
546 {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
547 NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
548 {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
549 NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
550 {"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
551 NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
552 {"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
553 {"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
554 {"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
555 {"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
556 NT_STATUS_RESOURCE_LANG_NOT_FOUND},
557 {"NT_STATUS_INSUFF_SERVER_RESOURCES",
558 NT_STATUS_INSUFF_SERVER_RESOURCES},
559 {"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
560 {"NT_STATUS_INVALID_ADDRESS_COMPONENT",
561 NT_STATUS_INVALID_ADDRESS_COMPONENT},
562 {"NT_STATUS_INVALID_ADDRESS_WILDCARD",
563 NT_STATUS_INVALID_ADDRESS_WILDCARD},
564 {"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
565 {"NT_STATUS_ADDRESS_ALREADY_EXISTS",
566 NT_STATUS_ADDRESS_ALREADY_EXISTS},
567 {"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
568 {"NT_STATUS_CONNECTION_DISCONNECTED",
569 NT_STATUS_CONNECTION_DISCONNECTED},
570 {"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
571 {"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
572 {"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
573 {"NT_STATUS_TRANSACTION_TIMED_OUT",
574 NT_STATUS_TRANSACTION_TIMED_OUT},
575 {"NT_STATUS_TRANSACTION_NO_RELEASE",
576 NT_STATUS_TRANSACTION_NO_RELEASE},
577 {"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
578 {"NT_STATUS_TRANSACTION_RESPONDED",
579 NT_STATUS_TRANSACTION_RESPONDED},
580 {"NT_STATUS_TRANSACTION_INVALID_ID",
581 NT_STATUS_TRANSACTION_INVALID_ID},
582 {"NT_STATUS_TRANSACTION_INVALID_TYPE",
583 NT_STATUS_TRANSACTION_INVALID_TYPE},
584 {"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
585 {"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
586 {"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
587 NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
588 {"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
589 {"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
590 NT_STATUS_SYSTEM_PROCESS_TERMINATED},
591 {"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
592 {"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
593 NT_STATUS_NO_BROWSER_SERVERS_FOUND},
594 {"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
595 {"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
596 NT_STATUS_DRIVER_CANCEL_TIMEOUT},
597 {"NT_STATUS_REPLY_MESSAGE_MISMATCH",
598 NT_STATUS_REPLY_MESSAGE_MISMATCH},
599 {"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
600 {"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
601 NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
602 {"NT_STATUS_LOST_WRITEBEHIND_DATA",
603 NT_STATUS_LOST_WRITEBEHIND_DATA},
604 {"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
605 NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
606 {"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
607 {"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
608 {"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
609 {"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
610 {"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
611 {"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
612 {"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
613 {"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
614 {"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
615 {"NT_STATUS_RETRY", NT_STATUS_RETRY},
616 {"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
617 {"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
618 {"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
619 {"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
620 {"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
621 {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
622 NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
623 {"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
624 {"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
625 {"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
626 {"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
627 {"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
628 NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
629 {"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
630 NT_STATUS_ADDRESS_NOT_ASSOCIATED},
631 {"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
632 {"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
633 {"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
634 {"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
635 {"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
636 {"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
637 {"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
638 {"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
639 {"NT_STATUS_BAD_COMPRESSION_BUFFER",
640 NT_STATUS_BAD_COMPRESSION_BUFFER},
641 {"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
642 {"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
643 {"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
644 NT_STATUS_TIMER_RESOLUTION_NOT_SET},
645 {"NT_STATUS_CONNECTION_COUNT_LIMIT",
646 NT_STATUS_CONNECTION_COUNT_LIMIT},
647 {"NT_STATUS_LOGIN_TIME_RESTRICTION",
648 NT_STATUS_LOGIN_TIME_RESTRICTION},
649 {"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
650 NT_STATUS_LOGIN_WKSTA_RESTRICTION},
651 {"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
652 {"NT_STATUS_INSUFFICIENT_LOGON_INFO",
653 NT_STATUS_INSUFFICIENT_LOGON_INFO},
654 {"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
655 {"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
656 NT_STATUS_BAD_SERVICE_ENTRYPOINT},
657 {"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
658 {"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
659 {"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
660 {"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
661 {"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
662 {"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
663 {"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
664 NT_STATUS_LICENSE_QUOTA_EXCEEDED},
665 {"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
666 {"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
667 {"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
668 {"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
669 {"NT_STATUS_UNSUPPORTED_COMPRESSION",
670 NT_STATUS_UNSUPPORTED_COMPRESSION},
671 {"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
672 {"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
673 NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
674 {"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
675 NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
676 {"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
677 NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
678 {"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
679 {"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
680 {"NT_STATUS_QUOTA_LIST_INCONSISTENT",
681 NT_STATUS_QUOTA_LIST_INCONSISTENT},
682 {"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
683 {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
684 {"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
685 {"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
686 {NULL, 0}
687};
diff --git a/fs/cifs/nterr.h b/fs/cifs/nterr.h
new file mode 100644
index 000000000000..d2fb06c97dfa
--- /dev/null
+++ b/fs/cifs/nterr.h
@@ -0,0 +1,556 @@
1/*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 NT error code constants
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) John H Terpstra 1996-2000
7 Copyright (C) Luke Kenneth Casson Leighton 1996-2000
8 Copyright (C) Paul Ashton 1998-2000
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25
26
27#ifndef _NTERR_H
28#define _NTERR_H
29
30struct nt_err_code_struct {
31 char *nt_errstr;
32 __u32 nt_errcode;
33};
34
35extern const struct nt_err_code_struct nt_errs[];
36
37/* Win32 Status codes. */
38
39#define STATUS_BUFFER_OVERFLOW 0x80000005
40#define STATUS_MORE_ENTRIES 0x0105
41#define ERROR_INVALID_PARAMETER 0x0057
42#define ERROR_INSUFFICIENT_BUFFER 0x007a
43#define STATUS_1804 0x070c
44#define STATUS_NOTIFY_ENUM_DIR 0x010c
45
46/* Win32 Error codes extracted using a loop in smbclient then printing a
47 netmon sniff to a file. */
48
49#define NT_STATUS_OK 0x0000
50#define STATUS_SOME_UNMAPPED 0x0107
51#define STATUS_BUFFER_OVERFLOW 0x80000005
52#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
53#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
54#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
55#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
56#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
57#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
58#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
59#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
60#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
61#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
62#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
63#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
64#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
65#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
66#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
67#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
68#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
69#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
70#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
71#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
72#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
73#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
74#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
75#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
76#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
77#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
78#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
79#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
80#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
81#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
82#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
83#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
84#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
85#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
86#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
87#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
88#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
89#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
90#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
91#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
92#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
93#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
94#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
95#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
96#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
97#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
98#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
99#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
100#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
101#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
102#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
103#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
104#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
105#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
106#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
107#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
108#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
109#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
110#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
111#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
112#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
113#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
114#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
115#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
116#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
117#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
118#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
119#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
120#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
121#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
122#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
123#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
124#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
125#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
126#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
127#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
128#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
129#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
130#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
131#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
132#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
133#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
134#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
135#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
136#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
137#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
138#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
139#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
140#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
141#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
142#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
143#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
144#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
145#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
146#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
147#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
148#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
149#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
150#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
151#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
152#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
153#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
154#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
155#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
156#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
157#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
158#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
159#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
160#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
161#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
162#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
163#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
164#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
165#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
166#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
167#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
168#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
169#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
170#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
171#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
172#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
173#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
174#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
175#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
176#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
177#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
178#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
179#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
180#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
181#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
182#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
183#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
184#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
185#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
186#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
187#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
188#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
189#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
190#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
191#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
192#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
193#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
194#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
195#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
196#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
197#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
198#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
199#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
200#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
201#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
202#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
203#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
204#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
205#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
206#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
207#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
208#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
209#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
210#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
211#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
212#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
213#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
214#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
215#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
216#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
217#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
218#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
219#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
220#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
221#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
222#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
223#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
224#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
225#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
226#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
227#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
228#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
229#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
230#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
231#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
232#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
233#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
234#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
235#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
236#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
237#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
238#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
239#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
240#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
241#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
242#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
243#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
244#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
245#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
246#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
247#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
248#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
249#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
250#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
251#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
252#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
253#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
254#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
255#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
256#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
257#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
258#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
259#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
260#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
261#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
262#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
263#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
264#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
265#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
266#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
267#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
268#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
269#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
270#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
271#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
272#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
273#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
274#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
275#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
276#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
277#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
278#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
279#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
280#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
281#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
282#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
283#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
284#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
285#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
286#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
287#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
288#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
289#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
290#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
291#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
292#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
293#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
294#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
295#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
296#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
297#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
298#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
299#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
300#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
301#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
302#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
303#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
304#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
305#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
306#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
307#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
308#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
309#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
310#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
311#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
312#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
313#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
314#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
315#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
316#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
317#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
318#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
319#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
320#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
321#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
322#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
323#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
324#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
325#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
326#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
327#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
328#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
329#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
330#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
331#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
332#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
333#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
334#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
335#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
336#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
337#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
338#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
339#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
340#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
341#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
342#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
343#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
344#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
345#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
346#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
347#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
348#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
349#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
350#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
351#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
352#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
353#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
354#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
355#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
356#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
357#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
358#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
359#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
360#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
361#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
362#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
363#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
364#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
365#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
366#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
367#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
368#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
369#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
370#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
371#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
372#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
373#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
374#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
375#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
376#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
377#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
378#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
379#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
380#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
381#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
382#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
383#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
384#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
385#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
386#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
387#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
388#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
389#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
390#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
391#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
392#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
393#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
394#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
395#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
396#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
397#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
398#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
399#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
400#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
401#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
402#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
403#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
404#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
405#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
406#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
407#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
408#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
409#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
410#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
411#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
412#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
413#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
414#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
415#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
416#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
417#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
418#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
419#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
420#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
421#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
422#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
423#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
424#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
425#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
426#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
427#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
428#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
429#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
430#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
431#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
432#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
433#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
434#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
435#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
436#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
437#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
438#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
439#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
440#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
441#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
442#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
443#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
444#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
445#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
446#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
447#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
448#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
449#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
450#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
451#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
452#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
453#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
454#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
455#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
456#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
457#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
458#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
459#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
460#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
461#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
462#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
463#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
464#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
465#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
466#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
467#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
468#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
469#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
470#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
471#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
472#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
473#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
474#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
475#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
476#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
477#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
478#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
479#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
480#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
481#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
482#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
483#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
484#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
485#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
486#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
487#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
488#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
489#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
490#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
491#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
492#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
493#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
494#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
495#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
496#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
497#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
498#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
499#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
500#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
501#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
502#define NT_STATUS_RETRY 0xC0000000 | 0x022d
503#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
504#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
505#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
506#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
507#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
508#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
509#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
510#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
511#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
512#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
513#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
514#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
515#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
516#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
517#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
518#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
519#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
520#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
521#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
522#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
523#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
524#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
525#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
526#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
527#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
528#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
529#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
530#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
531#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
532#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
533#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
534#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
535#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
536#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
537#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
538#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
539#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
540#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
541#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
542#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
543#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
544#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
545#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
546#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
547#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
548#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
549#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
550#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
551#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
552#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
553#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
554#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
555
556#endif /* _NTERR_H */
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
new file mode 100644
index 000000000000..6facb41117a3
--- /dev/null
+++ b/fs/cifs/ntlmssp.h
@@ -0,0 +1,101 @@
1/*
2 * fs/cifs/ntlmssp.h
3 *
4 * Copyright (c) International Business Machines Corp., 2002
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#pragma pack(1)
23
24#define NTLMSSP_SIGNATURE "NTLMSSP"
25/* Message Types */
26#define NtLmNegotiate cpu_to_le32(1)
27#define NtLmChallenge cpu_to_le32(2)
28#define NtLmAuthenticate cpu_to_le32(3)
29#define UnknownMessage cpu_to_le32(8)
30
31/* Negotiate Flags */
32#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
33#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
34#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
35#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
36#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
37#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
38#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
39#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
40#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
41#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
42#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
43#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
44#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
45#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
46#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
47#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
48#define NTLMSSP_REQUEST_INIT_RESP 0x100000
49#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
50#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
51#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
52#define NTLMSSP_NEGOTIATE_128 0x20000000
53#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
54#define NTLMSSP_NEGOTIATE_56 0x80000000
55
56/* Although typedefs are not commonly used for structure definitions */
57/* in the Linux kernel, in this particular case they are useful */
58/* to more closely match the standards document for NTLMSSP from */
59/* OpenGroup and to make the code more closely match the standard in */
60/* appearance */
61
62typedef struct _SECURITY_BUFFER {
63 __le16 Length;
64 __le16 MaximumLength;
65 __le32 Buffer; /* offset to buffer */
66} SECURITY_BUFFER;
67
68typedef struct _NEGOTIATE_MESSAGE {
69 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
70 __le32 MessageType; /* 1 */
71 __le32 NegotiateFlags;
72 SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
73 SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
74 char DomainString[0];
75 /* followed by WorkstationString */
76} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
77
78typedef struct _CHALLENGE_MESSAGE {
79 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
80 __le32 MessageType; /* 2 */
81 SECURITY_BUFFER TargetName;
82 __le32 NegotiateFlags;
83 __u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
84 __u8 Reserved[8];
85 SECURITY_BUFFER TargetInfoArray;
86} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
87
88typedef struct _AUTHENTICATE_MESSAGE {
89 __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
90 __le32 MessageType; /* 3 */
91 SECURITY_BUFFER LmChallengeResponse;
92 SECURITY_BUFFER NtChallengeResponse;
93 SECURITY_BUFFER DomainName;
94 SECURITY_BUFFER UserName;
95 SECURITY_BUFFER WorkstationName;
96 SECURITY_BUFFER SessionKey;
97 __le32 NegotiateFlags;
98 char UserString[0];
99} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
100
101#pragma pack() /* resume default structure packing */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
new file mode 100644
index 000000000000..f8bea395ec9e
--- /dev/null
+++ b/fs/cifs/readdir.c
@@ -0,0 +1,867 @@
1/*
2 * fs/cifs/readdir.c
3 *
4 * Directory search handling
5 *
6 * Copyright (C) International Business Machines Corp., 2004
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/fs.h>
24#include <linux/stat.h>
25#include <linux/smp_lock.h>
26#include "cifspdu.h"
27#include "cifsglob.h"
28#include "cifsproto.h"
29#include "cifs_unicode.h"
30#include "cifs_debug.h"
31#include "cifs_fs_sb.h"
32#include "cifsfs.h"
33
34/* BB fixme - add debug wrappers around this function to disable it fixme BB */
35/* static void dump_cifs_file_struct(struct file *file, char *label)
36{
37 struct cifsFileInfo * cf;
38
39 if(file) {
40 cf = file->private_data;
41 if(cf == NULL) {
42 cFYI(1,("empty cifs private file data"));
43 return;
44 }
45 if(cf->invalidHandle) {
46 cFYI(1,("invalid handle"));
47 }
48 if(cf->srch_inf.endOfSearch) {
49 cFYI(1,("end of search"));
50 }
51 if(cf->srch_inf.emptyDir) {
52 cFYI(1,("empty dir"));
53 }
54
55 }
56} */
57
58/* Returns one if new inode created (which therefore needs to be hashed) */
59/* Might check in the future if inode number changed so we can rehash inode */
60static int construct_dentry(struct qstr *qstring, struct file *file,
61 struct inode **ptmp_inode, struct dentry **pnew_dentry)
62{
63 struct dentry *tmp_dentry;
64 struct cifs_sb_info *cifs_sb;
65 struct cifsTconInfo *pTcon;
66 int rc = 0;
67
68 cFYI(1, ("For %s ", qstring->name));
69 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
70 pTcon = cifs_sb->tcon;
71
72 qstring->hash = full_name_hash(qstring->name, qstring->len);
73 tmp_dentry = d_lookup(file->f_dentry, qstring);
74 if (tmp_dentry) {
75 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
76 *ptmp_inode = tmp_dentry->d_inode;
77/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
78 if(*ptmp_inode == NULL) {
79 *ptmp_inode = new_inode(file->f_dentry->d_sb);
80 if(*ptmp_inode == NULL)
81 return rc;
82 rc = 1;
83 d_instantiate(tmp_dentry, *ptmp_inode);
84 }
85 } else {
86 tmp_dentry = d_alloc(file->f_dentry, qstring);
87 if(tmp_dentry == NULL) {
88 cERROR(1,("Failed allocating dentry"));
89 *ptmp_inode = NULL;
90 return rc;
91 }
92
93 *ptmp_inode = new_inode(file->f_dentry->d_sb);
94 tmp_dentry->d_op = &cifs_dentry_ops;
95 if(*ptmp_inode == NULL)
96 return rc;
97 rc = 1;
98 d_instantiate(tmp_dentry, *ptmp_inode);
99 d_rehash(tmp_dentry);
100 }
101
102 tmp_dentry->d_time = jiffies;
103 *pnew_dentry = tmp_dentry;
104 return rc;
105}
106
107static void fill_in_inode(struct inode *tmp_inode,
108 FILE_DIRECTORY_INFO *pfindData, int *pobject_type)
109{
110 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
111 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
112 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
113 __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
114 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
115
116 cifsInfo->cifsAttrs = attr;
117 cifsInfo->time = jiffies;
118
119 /* Linux can not store file creation time unfortunately so ignore it */
120 tmp_inode->i_atime =
121 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
122 tmp_inode->i_mtime =
123 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
124 tmp_inode->i_ctime =
125 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
126 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
127 /* 2767 perms - indicate mandatory locking */
128 /* BB fill in uid and gid here? with help from winbind?
129 or retrieve from NTFS stream extended attribute */
130 if (atomic_read(&cifsInfo->inUse) == 0) {
131 tmp_inode->i_uid = cifs_sb->mnt_uid;
132 tmp_inode->i_gid = cifs_sb->mnt_gid;
133 /* set default mode. will override for dirs below */
134 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
135 }
136
137 cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
138 if (attr & ATTR_DIRECTORY) {
139 *pobject_type = DT_DIR;
140 /* override default perms since we do not lock dirs */
141 if(atomic_read(&cifsInfo->inUse) == 0) {
142 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
143 }
144 tmp_inode->i_mode |= S_IFDIR;
145/* we no longer mark these because we could not follow them */
146/* } else if (attr & ATTR_REPARSE) {
147 *pobject_type = DT_LNK;
148 tmp_inode->i_mode |= S_IFLNK; */
149 } else {
150 *pobject_type = DT_REG;
151 tmp_inode->i_mode |= S_IFREG;
152 if (attr & ATTR_READONLY)
153 tmp_inode->i_mode &= ~(S_IWUGO);
154 } /* could add code here - to validate if device or weird share type? */
155
156 /* can not fill in nlink here as in qpathinfo version and Unx search */
157 if (atomic_read(&cifsInfo->inUse) == 0) {
158 atomic_set(&cifsInfo->inUse, 1);
159 }
160
161 if (is_size_safe_to_change(cifsInfo)) {
162 /* can not safely change the file size here if the
163 client is writing to it due to potential races */
164 i_size_write(tmp_inode, end_of_file);
165
166 /* 512 bytes (2**9) is the fake blocksize that must be used */
167 /* for this calculation, even though the reported blocksize is larger */
168 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
169 }
170
171 if (allocation_size < end_of_file)
172 cFYI(1, ("May be sparse file, allocation less than file size"));
173 cFYI(1,
174 ("File Size %ld and blocks %ld and blocksize %ld",
175 (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
176 tmp_inode->i_blksize));
177 if (S_ISREG(tmp_inode->i_mode)) {
178 cFYI(1, (" File inode "));
179 tmp_inode->i_op = &cifs_file_inode_ops;
180 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
181 tmp_inode->i_fop = &cifs_file_direct_ops;
182 else
183 tmp_inode->i_fop = &cifs_file_ops;
184 tmp_inode->i_data.a_ops = &cifs_addr_ops;
185 } else if (S_ISDIR(tmp_inode->i_mode)) {
186 cFYI(1, (" Directory inode"));
187 tmp_inode->i_op = &cifs_dir_inode_ops;
188 tmp_inode->i_fop = &cifs_dir_ops;
189 } else if (S_ISLNK(tmp_inode->i_mode)) {
190 cFYI(1, (" Symbolic Link inode "));
191 tmp_inode->i_op = &cifs_symlink_inode_ops;
192 } else {
193 cFYI(1, (" Init special inode "));
194 init_special_inode(tmp_inode, tmp_inode->i_mode,
195 tmp_inode->i_rdev);
196 }
197}
198
199static void unix_fill_in_inode(struct inode *tmp_inode,
200 FILE_UNIX_INFO *pfindData, int *pobject_type)
201{
202 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
203 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
204
205 __u32 type = le32_to_cpu(pfindData->Type);
206 __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
207 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
208 cifsInfo->time = jiffies;
209 atomic_inc(&cifsInfo->inUse);
210
211 tmp_inode->i_atime =
212 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
213 tmp_inode->i_mtime =
214 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
215 tmp_inode->i_ctime =
216 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
217
218 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
219 if (type == UNIX_FILE) {
220 *pobject_type = DT_REG;
221 tmp_inode->i_mode |= S_IFREG;
222 } else if (type == UNIX_SYMLINK) {
223 *pobject_type = DT_LNK;
224 tmp_inode->i_mode |= S_IFLNK;
225 } else if (type == UNIX_DIR) {
226 *pobject_type = DT_DIR;
227 tmp_inode->i_mode |= S_IFDIR;
228 } else if (type == UNIX_CHARDEV) {
229 *pobject_type = DT_CHR;
230 tmp_inode->i_mode |= S_IFCHR;
231 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
232 le64_to_cpu(pfindData->DevMinor) & MINORMASK);
233 } else if (type == UNIX_BLOCKDEV) {
234 *pobject_type = DT_BLK;
235 tmp_inode->i_mode |= S_IFBLK;
236 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
237 le64_to_cpu(pfindData->DevMinor) & MINORMASK);
238 } else if (type == UNIX_FIFO) {
239 *pobject_type = DT_FIFO;
240 tmp_inode->i_mode |= S_IFIFO;
241 } else if (type == UNIX_SOCKET) {
242 *pobject_type = DT_SOCK;
243 tmp_inode->i_mode |= S_IFSOCK;
244 }
245
246 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
247 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
248 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
249
250 if (is_size_safe_to_change(cifsInfo)) {
251 /* can not safely change the file size here if the
252 client is writing to it due to potential races */
253 i_size_write(tmp_inode,end_of_file);
254
255 /* 512 bytes (2**9) is the fake blocksize that must be used */
256 /* for this calculation, not the real blocksize */
257 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
258 }
259
260 if (S_ISREG(tmp_inode->i_mode)) {
261 cFYI(1, ("File inode"));
262 tmp_inode->i_op = &cifs_file_inode_ops;
263 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
264 tmp_inode->i_fop = &cifs_file_direct_ops;
265 else
266 tmp_inode->i_fop = &cifs_file_ops;
267 tmp_inode->i_data.a_ops = &cifs_addr_ops;
268 } else if (S_ISDIR(tmp_inode->i_mode)) {
269 cFYI(1, ("Directory inode"));
270 tmp_inode->i_op = &cifs_dir_inode_ops;
271 tmp_inode->i_fop = &cifs_dir_ops;
272 } else if (S_ISLNK(tmp_inode->i_mode)) {
273 cFYI(1, ("Symbolic Link inode"));
274 tmp_inode->i_op = &cifs_symlink_inode_ops;
275/* tmp_inode->i_fop = *//* do not need to set to anything */
276 } else {
277 cFYI(1, ("Special inode"));
278 init_special_inode(tmp_inode, tmp_inode->i_mode,
279 tmp_inode->i_rdev);
280 }
281}
282
283static int initiate_cifs_search(const int xid, struct file *file)
284{
285 int rc = 0;
286 char * full_path;
287 struct cifsFileInfo * cifsFile;
288 struct cifs_sb_info *cifs_sb;
289 struct cifsTconInfo *pTcon;
290
291 if(file->private_data == NULL) {
292 file->private_data =
293 kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
294 }
295
296 if(file->private_data == NULL) {
297 return -ENOMEM;
298 } else {
299 memset(file->private_data,0,sizeof(struct cifsFileInfo));
300 }
301 cifsFile = file->private_data;
302 cifsFile->invalidHandle = TRUE;
303 cifsFile->srch_inf.endOfSearch = FALSE;
304
305 if(file->f_dentry == NULL)
306 return -ENOENT;
307
308 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
309 if(cifs_sb == NULL)
310 return -EINVAL;
311
312 pTcon = cifs_sb->tcon;
313 if(pTcon == NULL)
314 return -EINVAL;
315
316 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
317 full_path = build_wildcard_path_from_dentry(file->f_dentry);
318 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
319
320 if(full_path == NULL) {
321 return -ENOMEM;
322 }
323
324 cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
325
326 /* test for Unix extensions */
327 if (pTcon->ses->capabilities & CAP_UNIX) {
328 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
329 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
330 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
331 } else /* not srvinos - BB fixme add check for backlevel? */ {
332 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
333 }
334
335 rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
336 &cifsFile->netfid, &cifsFile->srch_inf);
337 if(rc == 0)
338 cifsFile->invalidHandle = FALSE;
339 kfree(full_path);
340 return rc;
341}
342
343/* return length of unicode string in bytes */
344static int cifs_unicode_bytelen(char *str)
345{
346 int len;
347 __le16 * ustr = (__le16 *)str;
348
349 for(len=0;len <= PATH_MAX;len++) {
350 if(ustr[len] == 0)
351 return len << 1;
352 }
353 cFYI(1,("Unicode string longer than PATH_MAX found"));
354 return len << 1;
355}
356
357static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
358{
359 char * new_entry;
360 FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
361
362 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
363 cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
364 /* validate that new_entry is not past end of SMB */
365 if(new_entry >= end_of_smb) {
366 cFYI(1,("search entry %p began after end of SMB %p old entry %p",
367 new_entry,end_of_smb,old_entry));
368 return NULL;
369 } else
370 return new_entry;
371
372}
373
374#define UNICODE_DOT cpu_to_le16(0x2e)
375
376/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
377static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
378{
379 int rc = 0;
380 char * filename = NULL;
381 int len = 0;
382
383 if(cfile->srch_inf.info_level == 0x202) {
384 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
385 filename = &pFindData->FileName[0];
386 if(cfile->srch_inf.unicode) {
387 len = cifs_unicode_bytelen(filename);
388 } else {
389 /* BB should we make this strnlen of PATH_MAX? */
390 len = strnlen(filename, 5);
391 }
392 } else if(cfile->srch_inf.info_level == 0x101) {
393 FILE_DIRECTORY_INFO * pFindData =
394 (FILE_DIRECTORY_INFO *)current_entry;
395 filename = &pFindData->FileName[0];
396 len = le32_to_cpu(pFindData->FileNameLength);
397 } else if(cfile->srch_inf.info_level == 0x102) {
398 FILE_FULL_DIRECTORY_INFO * pFindData =
399 (FILE_FULL_DIRECTORY_INFO *)current_entry;
400 filename = &pFindData->FileName[0];
401 len = le32_to_cpu(pFindData->FileNameLength);
402 } else if(cfile->srch_inf.info_level == 0x105) {
403 SEARCH_ID_FULL_DIR_INFO * pFindData =
404 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
405 filename = &pFindData->FileName[0];
406 len = le32_to_cpu(pFindData->FileNameLength);
407 } else if(cfile->srch_inf.info_level == 0x104) {
408 FILE_BOTH_DIRECTORY_INFO * pFindData =
409 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
410 filename = &pFindData->FileName[0];
411 len = le32_to_cpu(pFindData->FileNameLength);
412 } else {
413 cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
414 }
415
416 if(filename) {
417 if(cfile->srch_inf.unicode) {
418 __le16 *ufilename = (__le16 *)filename;
419 if(len == 2) {
420 /* check for . */
421 if(ufilename[0] == UNICODE_DOT)
422 rc = 1;
423 } else if(len == 4) {
424 /* check for .. */
425 if((ufilename[0] == UNICODE_DOT)
426 &&(ufilename[1] == UNICODE_DOT))
427 rc = 2;
428 }
429 } else /* ASCII */ {
430 if(len == 1) {
431 if(filename[0] == '.')
432 rc = 1;
433 } else if(len == 2) {
434 if((filename[0] == '.') && (filename[1] == '.'))
435 rc = 2;
436 }
437 }
438 }
439
440 return rc;
441}
442
443/* find the corresponding entry in the search */
444/* Note that the SMB server returns search entries for . and .. which
445 complicates logic here if we choose to parse for them and we do not
446 assume that they are located in the findfirst return buffer.*/
447/* We start counting in the buffer with entry 2 and increment for every
448 entry (do not increment for . or .. entry) */
449static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
450 struct file *file, char **ppCurrentEntry, int *num_to_ret)
451{
452 int rc = 0;
453 int pos_in_buf = 0;
454 loff_t first_entry_in_buffer;
455 loff_t index_to_find = file->f_pos;
456 struct cifsFileInfo * cifsFile = file->private_data;
457 /* check if index in the buffer */
458
459 if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL))
460 return -ENOENT;
461
462 *ppCurrentEntry = NULL;
463 first_entry_in_buffer =
464 cifsFile->srch_inf.index_of_last_entry -
465 cifsFile->srch_inf.entries_in_buffer;
466/* dump_cifs_file_struct(file, "In fce ");*/
467 if(index_to_find < first_entry_in_buffer) {
468 /* close and restart search */
469 cFYI(1,("search backing up - close and restart search"));
470 cifsFile->invalidHandle = TRUE;
471 CIFSFindClose(xid, pTcon, cifsFile->netfid);
472 kfree(cifsFile->search_resume_name);
473 cifsFile->search_resume_name = NULL;
474 if(cifsFile->srch_inf.ntwrk_buf_start) {
475 cFYI(1,("freeing SMB ff cache buf on search rewind"));
476 cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start);
477 }
478 rc = initiate_cifs_search(xid,file);
479 if(rc) {
480 cFYI(1,("error %d reinitiating a search on rewind",rc));
481 return rc;
482 }
483 }
484
485 while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
486 (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
487 cFYI(1,("calling findnext2"));
488 rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf);
489 if(rc)
490 return -ENOENT;
491 }
492 if(index_to_find < cifsFile->srch_inf.index_of_last_entry) {
493 /* we found the buffer that contains the entry */
494 /* scan and find it */
495 int i;
496 char * current_entry;
497 char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
498 smbCalcSize((struct smb_hdr *)
499 cifsFile->srch_inf.ntwrk_buf_start);
500/* dump_cifs_file_struct(file,"found entry in fce "); */
501 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
502 - cifsFile->srch_inf.entries_in_buffer;
503 pos_in_buf = index_to_find - first_entry_in_buffer;
504 cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
505 current_entry = cifsFile->srch_inf.srch_entries_start;
506 for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
507 /* go entry to next entry figuring out which we need to start with */
508 /* if( . or ..)
509 skip */
510 rc = cifs_entry_is_dot(current_entry,cifsFile);
511 if(rc == 1) /* is . or .. so skip */ {
512 cFYI(1,("Entry is .")); /* BB removeme BB */
513 /* continue; */
514 } else if (rc == 2 ) {
515 cFYI(1,("Entry is ..")); /* BB removeme BB */
516 /* continue; */
517 }
518 current_entry = nxt_dir_entry(current_entry,end_of_smb);
519 }
520 if((current_entry == NULL) && (i < pos_in_buf)) {
521 /* BB fixme - check if we should flag this error */
522 cERROR(1,("reached end of buf searching for pos in buf"
523 " %d index to find %lld rc %d",
524 pos_in_buf,index_to_find,rc));
525 }
526 rc = 0;
527 *ppCurrentEntry = current_entry;
528 } else {
529 cFYI(1,("index not in buffer - could not findnext into it"));
530 return 0;
531 }
532
533 if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
534 cFYI(1,("can not return entries when pos_in_buf beyond last entry"));
535 *num_to_ret = 0;
536 } else
537 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
538/* dump_cifs_file_struct(file, "end fce ");*/
539
540 return rc;
541}
542
543/* inode num, inode type and filename returned */
544static int cifs_get_name_from_search_buf(struct qstr *pqst,
545 char *current_entry, __u16 level, unsigned int unicode,
546 struct cifs_sb_info * cifs_sb, ino_t *pinum)
547{
548 int rc = 0;
549 unsigned int len = 0;
550 char * filename;
551 struct nls_table * nlt = cifs_sb->local_nls;
552
553 *pinum = 0;
554
555 if(level == SMB_FIND_FILE_UNIX) {
556 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
557
558 filename = &pFindData->FileName[0];
559 if(unicode) {
560 len = cifs_unicode_bytelen(filename);
561 } else {
562 /* BB should we make this strnlen of PATH_MAX? */
563 len = strnlen(filename, PATH_MAX);
564 }
565
566 /* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */
567 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
568 *pinum = pFindData->UniqueId;
569 } else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
570 FILE_DIRECTORY_INFO * pFindData =
571 (FILE_DIRECTORY_INFO *)current_entry;
572 filename = &pFindData->FileName[0];
573 len = le32_to_cpu(pFindData->FileNameLength);
574 } else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
575 FILE_FULL_DIRECTORY_INFO * pFindData =
576 (FILE_FULL_DIRECTORY_INFO *)current_entry;
577 filename = &pFindData->FileName[0];
578 len = le32_to_cpu(pFindData->FileNameLength);
579 } else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
580 SEARCH_ID_FULL_DIR_INFO * pFindData =
581 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
582 filename = &pFindData->FileName[0];
583 len = le32_to_cpu(pFindData->FileNameLength);
584 *pinum = pFindData->UniqueId;
585 } else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
586 FILE_BOTH_DIRECTORY_INFO * pFindData =
587 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
588 filename = &pFindData->FileName[0];
589 len = le32_to_cpu(pFindData->FileNameLength);
590 } else {
591 cFYI(1,("Unknown findfirst level %d",level));
592 return -EINVAL;
593 }
594 if(unicode) {
595 /* BB fixme - test with long names */
596 /* Note converted filename can be longer than in unicode */
597 pqst->len = cifs_strfromUCS_le((char *)pqst->name,(wchar_t *)filename,len/2,nlt);
598 } else {
599 pqst->name = filename;
600 pqst->len = len;
601 }
602 pqst->hash = full_name_hash(pqst->name,pqst->len);
603/* cFYI(1,("filldir on %s",pqst->name)); */
604 return rc;
605}
606
607static int cifs_filldir(char *pfindEntry, struct file *file,
608 filldir_t filldir, void *direntry, char *scratch_buf)
609{
610 int rc = 0;
611 struct qstr qstring;
612 struct cifsFileInfo * pCifsF;
613 unsigned obj_type;
614 ino_t inum;
615 struct cifs_sb_info * cifs_sb;
616 struct inode *tmp_inode;
617 struct dentry *tmp_dentry;
618
619 /* get filename and len into qstring */
620 /* get dentry */
621 /* decide whether to create and populate ionde */
622 if((direntry == NULL) || (file == NULL))
623 return -EINVAL;
624
625 pCifsF = file->private_data;
626
627 if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
628 return -ENOENT;
629
630 if(file->f_dentry == NULL)
631 return -ENOENT;
632
633 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
634
635 qstring.name = scratch_buf;
636 rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
637 pCifsF->srch_inf.info_level,
638 pCifsF->srch_inf.unicode,cifs_sb,
639 &inum /* returned */);
640
641 if(rc)
642 return rc;
643
644 rc = construct_dentry(&qstring,file,&tmp_inode, &tmp_dentry);
645 if((tmp_inode == NULL) || (tmp_dentry == NULL))
646 return -ENOMEM;
647
648 if(rc) {
649 /* inode created, we need to hash it with right inode number */
650 if(inum != 0) {
651 /* BB fixme - hash the 2 32 quantities bits together if necessary BB */
652 tmp_inode->i_ino = inum;
653 }
654 insert_inode_hash(tmp_inode);
655 }
656
657 if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
658 unix_fill_in_inode(tmp_inode,(FILE_UNIX_INFO *)pfindEntry,&obj_type);
659 } else {
660 fill_in_inode(tmp_inode,(FILE_DIRECTORY_INFO *)pfindEntry,&obj_type);
661 }
662
663 rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);
664 if(rc) {
665 cFYI(1,("filldir rc = %d",rc));
666 }
667
668 dput(tmp_dentry);
669 return rc;
670}
671
672static int cifs_save_resume_key(const char *current_entry,
673 struct cifsFileInfo *cifsFile)
674{
675 int rc = 0;
676 unsigned int len = 0;
677 __u16 level;
678 char * filename;
679
680 if((cifsFile == NULL) || (current_entry == NULL))
681 return -EINVAL;
682
683 level = cifsFile->srch_inf.info_level;
684
685 if(level == SMB_FIND_FILE_UNIX) {
686 FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
687
688 filename = &pFindData->FileName[0];
689 if(cifsFile->srch_inf.unicode) {
690 len = cifs_unicode_bytelen(filename);
691 } else {
692 /* BB should we make this strnlen of PATH_MAX? */
693 len = strnlen(filename, PATH_MAX);
694 }
695 cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
696 } else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
697 FILE_DIRECTORY_INFO * pFindData =
698 (FILE_DIRECTORY_INFO *)current_entry;
699 filename = &pFindData->FileName[0];
700 len = le32_to_cpu(pFindData->FileNameLength);
701 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
702 } else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
703 FILE_FULL_DIRECTORY_INFO * pFindData =
704 (FILE_FULL_DIRECTORY_INFO *)current_entry;
705 filename = &pFindData->FileName[0];
706 len = le32_to_cpu(pFindData->FileNameLength);
707 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
708 } else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
709 SEARCH_ID_FULL_DIR_INFO * pFindData =
710 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
711 filename = &pFindData->FileName[0];
712 len = le32_to_cpu(pFindData->FileNameLength);
713 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
714 } else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
715 FILE_BOTH_DIRECTORY_INFO * pFindData =
716 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
717 filename = &pFindData->FileName[0];
718 len = le32_to_cpu(pFindData->FileNameLength);
719 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
720 } else {
721 cFYI(1,("Unknown findfirst level %d",level));
722 return -EINVAL;
723 }
724 cifsFile->srch_inf.resume_name_len = len;
725 cifsFile->srch_inf.presume_name = filename;
726 return rc;
727}
728
729int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
730{
731 int rc = 0;
732 int xid,i;
733 struct cifs_sb_info *cifs_sb;
734 struct cifsTconInfo *pTcon;
735 struct cifsFileInfo *cifsFile = NULL;
736 char * current_entry;
737 int num_to_fill = 0;
738 char * tmp_buf = NULL;
739 char * end_of_smb;
740
741 xid = GetXid();
742
743 if(file->f_dentry == NULL) {
744 FreeXid(xid);
745 return -EIO;
746 }
747/* dump_cifs_file_struct(file, "Begin rdir "); */
748
749 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
750 pTcon = cifs_sb->tcon;
751 if(pTcon == NULL)
752 return -EINVAL;
753
754/* cFYI(1,("readdir2 pos: %lld",file->f_pos)); */
755
756 switch ((int) file->f_pos) {
757 case 0:
758 /*if (filldir(direntry, ".", 1, file->f_pos,
759 file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
760 cERROR(1, ("Filldir for current dir failed "));
761 rc = -ENOMEM;
762 break;
763 }
764 file->f_pos++; */
765 case 1:
766 /* if (filldir(direntry, "..", 2, file->f_pos,
767 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
768 cERROR(1, ("Filldir for parent dir failed "));
769 rc = -ENOMEM;
770 break;
771 }
772 file->f_pos++; */
773 case 2:
774 /* 1) If search is active,
775 is in current search buffer?
776 if it before then restart search
777 if after then keep searching till find it */
778
779 if(file->private_data == NULL) {
780 rc = initiate_cifs_search(xid,file);
781 cFYI(1,("initiate cifs search rc %d",rc));
782 if(rc) {
783 FreeXid(xid);
784 return rc;
785 }
786 }
787 default:
788 if(file->private_data == NULL) {
789 rc = -EINVAL;
790 FreeXid(xid);
791 return rc;
792 }
793 cifsFile = file->private_data;
794 if (cifsFile->srch_inf.endOfSearch) {
795 if(cifsFile->srch_inf.emptyDir) {
796 cFYI(1, ("End of search, empty dir"));
797 rc = 0;
798 break;
799 }
800 } /* else {
801 cifsFile->invalidHandle = TRUE;
802 CIFSFindClose(xid, pTcon, cifsFile->netfid);
803 }
804 kfree(cifsFile->search_resume_name);
805 cifsFile->search_resume_name = NULL; */
806
807 /* BB account for . and .. in f_pos as special case */
808 /* dump_cifs_file_struct(file, "rdir after default ");*/
809
810 rc = find_cifs_entry(xid,pTcon, file,
811 &current_entry,&num_to_fill);
812 if(rc) {
813 cFYI(1,("fce error %d",rc));
814 goto rddir2_exit;
815 } else if (current_entry != NULL) {
816 cFYI(1,("entry %lld found",file->f_pos));
817 } else {
818 cFYI(1,("could not find entry"));
819 goto rddir2_exit;
820 }
821 cFYI(1,("loop through %d times filling dir for net buf %p",
822 num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
823 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
824 smbCalcSize((struct smb_hdr *)
825 cifsFile->srch_inf.ntwrk_buf_start);
826 tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL);
827 for(i=0;(i<num_to_fill) && (rc == 0);i++) {
828 if(current_entry == NULL) {
829 /* evaluate whether this case is an error */
830 cERROR(1,("past end of SMB num to fill %d i %d",
831 num_to_fill, i));
832 break;
833 }
834
835 /* BB FIXME - need to enable the below code BB */
836
837 /* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
838 (cifsFile->srch_inf.info_level !=
839 something that supports server inodes)) {
840 create dentry
841 create inode
842 fill in inode new_inode (getting local i_ino)
843 }
844 also create local inode for performance reasons (so we
845 have a cache of inode metadata) unless this new mount
846 parm says otherwise */
847
848 rc = cifs_filldir(current_entry, file,
849 filldir, direntry,tmp_buf);
850 file->f_pos++;
851 if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) {
852 cFYI(1,("last entry in buf at pos %lld %s",
853 file->f_pos,tmp_buf)); /* BB removeme BB */
854 cifs_save_resume_key(current_entry,cifsFile);
855 break;
856 } else
857 current_entry = nxt_dir_entry(current_entry,end_of_smb);
858 }
859 kfree(tmp_buf);
860 break;
861 } /* end switch */
862
863rddir2_exit:
864 /* dump_cifs_file_struct(file, "end rdir "); */
865 FreeXid(xid);
866 return rc;
867}
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
new file mode 100644
index 000000000000..806c0ed06da9
--- /dev/null
+++ b/fs/cifs/rfc1002pdu.h
@@ -0,0 +1,79 @@
1/*
2 * fs/cifs/rfc1002pdu.h
3 *
4 * Protocol Data Unit definitions for RFC 1001/1002 support
5 *
6 * Copyright (c) International Business Machines Corp., 2004
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#pragma pack(1)
25
26/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
27
28 /* RFC 1002 session packet types */
29#define RFC1002_SESSION_MESASAGE 0x00
30#define RFC1002_SESSION_REQUEST 0x81
31#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
32#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
33#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
34#define RFC1002_SESSION_KEEP_ALIVE 0x85
35
36 /* RFC 1002 flags (only one defined */
37#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
38
39struct rfc1002_session_packet {
40 __u8 type;
41 __u8 flags;
42 __u16 length;
43 union {
44 struct {
45 __u8 called_len;
46 __u8 called_name[32];
47 __u8 scope1; /* null */
48 __u8 calling_len;
49 __u8 calling_name[32];
50 __u8 scope2; /* null */
51 } session_req;
52 struct {
53 __u32 retarget_ip_addr;
54 __u16 port;
55 } retarget_resp;
56 __u8 neg_ses_resp_error_code;
57 /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
58 SESSION_KEEP_ALIVE packet also does not include a trailer.
59 Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
60 } trailer;
61};
62
63/* Negative Session Response error codes */
64#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */
65#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
66#define RFC1002_NOT_PRESENT 0x82 /* called name not present */
67#define RFC1002_INSUFFICIENT_RESOURCE 0x83
68#define RFC1002_UNSPECIFIED_ERROR 0x8F
69
70/* RFC 1002 Datagram service packets are not defined here as they
71are not needed for the network filesystem client unless we plan on
72implementing broadcast resolution of the server ip address (from
73server netbios name). Currently server names are resolved only via DNS
74(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
75
76#define DEFAULT_CIFS_CALLED_NAME "*SMBSERVER "
77
78#pragma pack() /* resume default structure packing */
79
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
new file mode 100644
index 000000000000..efaa044523a7
--- /dev/null
+++ b/fs/cifs/smbdes.c
@@ -0,0 +1,412 @@
1/*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4
5 a partial implementation of DES designed for use in the
6 SMB authentication protocol
7
8 Copyright (C) Andrew Tridgell 1998
9 Modified by Steve French (sfrench@us.ibm.com) 2002,2004
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24*/
25
26/* NOTES:
27
28 This code makes no attempt to be fast! In fact, it is a very
29 slow implementation
30
31 This code is NOT a complete DES implementation. It implements only
32 the minimum necessary for SMB authentication, as used by all SMB
33 products (including every copy of Microsoft Windows95 ever sold)
34
35 In particular, it can only do a unchained forward DES pass. This
36 means it is not possible to use this code for encryption/decryption
37 of data, instead it is only useful as a "hash" algorithm.
38
39 There is no entry point into this code that allows normal DES operation.
40
41 I believe this means that this code does not come under ITAR
42 regulations but this is NOT a legal opinion. If you are concerned
43 about the applicability of ITAR regulations to this code then you
44 should confirm it for yourself (and maybe let me know if you come
45 up with a different answer to the one above)
46*/
47#include <linux/slab.h>
48#include "cifsencrypt.h"
49#define uchar unsigned char
50
51static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
52 1, 58, 50, 42, 34, 26, 18,
53 10, 2, 59, 51, 43, 35, 27,
54 19, 11, 3, 60, 52, 44, 36,
55 63, 55, 47, 39, 31, 23, 15,
56 7, 62, 54, 46, 38, 30, 22,
57 14, 6, 61, 53, 45, 37, 29,
58 21, 13, 5, 28, 20, 12, 4
59};
60
61static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
62 3, 28, 15, 6, 21, 10,
63 23, 19, 12, 4, 26, 8,
64 16, 7, 27, 20, 13, 2,
65 41, 52, 31, 37, 47, 55,
66 30, 40, 51, 45, 33, 48,
67 44, 49, 39, 56, 34, 53,
68 46, 42, 50, 36, 29, 32
69};
70
71static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
72 60, 52, 44, 36, 28, 20, 12, 4,
73 62, 54, 46, 38, 30, 22, 14, 6,
74 64, 56, 48, 40, 32, 24, 16, 8,
75 57, 49, 41, 33, 25, 17, 9, 1,
76 59, 51, 43, 35, 27, 19, 11, 3,
77 61, 53, 45, 37, 29, 21, 13, 5,
78 63, 55, 47, 39, 31, 23, 15, 7
79};
80
81static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
82 4, 5, 6, 7, 8, 9,
83 8, 9, 10, 11, 12, 13,
84 12, 13, 14, 15, 16, 17,
85 16, 17, 18, 19, 20, 21,
86 20, 21, 22, 23, 24, 25,
87 24, 25, 26, 27, 28, 29,
88 28, 29, 30, 31, 32, 1
89};
90
91static uchar perm5[32] = { 16, 7, 20, 21,
92 29, 12, 28, 17,
93 1, 15, 23, 26,
94 5, 18, 31, 10,
95 2, 8, 24, 14,
96 32, 27, 3, 9,
97 19, 13, 30, 6,
98 22, 11, 4, 25
99};
100
101static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
102 39, 7, 47, 15, 55, 23, 63, 31,
103 38, 6, 46, 14, 54, 22, 62, 30,
104 37, 5, 45, 13, 53, 21, 61, 29,
105 36, 4, 44, 12, 52, 20, 60, 28,
106 35, 3, 43, 11, 51, 19, 59, 27,
107 34, 2, 42, 10, 50, 18, 58, 26,
108 33, 1, 41, 9, 49, 17, 57, 25
109};
110
111static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
112
113static uchar sbox[8][4][16] = {
114 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
115 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
116 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
117 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
118
119 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
120 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
121 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
122 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
123
124 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
125 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
126 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
127 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
128
129 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
130 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
131 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
132 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
133
134 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
135 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
136 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
137 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
138
139 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
140 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
141 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
142 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
143
144 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
145 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
146 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
147 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
148
149 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
150 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
151 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
152 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
153};
154
155static void
156permute(char *out, char *in, uchar * p, int n)
157{
158 int i;
159 for (i = 0; i < n; i++)
160 out[i] = in[p[i] - 1];
161}
162
163static void
164lshift(char *d, int count, int n)
165{
166 char out[64];
167 int i;
168 for (i = 0; i < n; i++)
169 out[i] = d[(i + count) % n];
170 for (i = 0; i < n; i++)
171 d[i] = out[i];
172}
173
174static void
175concat(char *out, char *in1, char *in2, int l1, int l2)
176{
177 while (l1--)
178 *out++ = *in1++;
179 while (l2--)
180 *out++ = *in2++;
181}
182
183static void
184xor(char *out, char *in1, char *in2, int n)
185{
186 int i;
187 for (i = 0; i < n; i++)
188 out[i] = in1[i] ^ in2[i];
189}
190
191static void
192dohash(char *out, char *in, char *key, int forw)
193{
194 int i, j, k;
195 char *pk1;
196 char c[28];
197 char d[28];
198 char *cd;
199 char ki[16][48];
200 char *pd1;
201 char l[32], r[32];
202 char *rl;
203
204 /* Have to reduce stack usage */
205 pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
206 if(pk1 == NULL)
207 return;
208
209 cd = pk1 + 56;
210 pd1= cd + 56;
211 rl = pd1 + 64;
212
213 permute(pk1, key, perm1, 56);
214
215 for (i = 0; i < 28; i++)
216 c[i] = pk1[i];
217 for (i = 0; i < 28; i++)
218 d[i] = pk1[i + 28];
219
220 for (i = 0; i < 16; i++) {
221 lshift(c, sc[i], 28);
222 lshift(d, sc[i], 28);
223
224 concat(cd, c, d, 28, 28);
225 permute(ki[i], cd, perm2, 48);
226 }
227
228 permute(pd1, in, perm3, 64);
229
230 for (j = 0; j < 32; j++) {
231 l[j] = pd1[j];
232 r[j] = pd1[j + 32];
233 }
234
235 for (i = 0; i < 16; i++) {
236 char *er; /* er[48] */
237 char *erk; /* erk[48] */
238 char b[8][6];
239 char *cb; /* cb[32] */
240 char *pcb; /* pcb[32] */
241 char *r2; /* r2[32] */
242
243 er = kmalloc(48+48+32+32+32, GFP_KERNEL);
244 if(er == NULL) {
245 kfree(pk1);
246 return;
247 }
248 erk = er+48;
249 cb = erk+48;
250 pcb = cb+32;
251 r2 = pcb+32;
252
253 permute(er, r, perm4, 48);
254
255 xor(erk, er, ki[forw ? i : 15 - i], 48);
256
257 for (j = 0; j < 8; j++)
258 for (k = 0; k < 6; k++)
259 b[j][k] = erk[j * 6 + k];
260
261 for (j = 0; j < 8; j++) {
262 int m, n;
263 m = (b[j][0] << 1) | b[j][5];
264
265 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
266 1) | b[j][4];
267
268 for (k = 0; k < 4; k++)
269 b[j][k] =
270 (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
271 }
272
273 for (j = 0; j < 8; j++)
274 for (k = 0; k < 4; k++)
275 cb[j * 4 + k] = b[j][k];
276 permute(pcb, cb, perm5, 32);
277
278 xor(r2, l, pcb, 32);
279
280 for (j = 0; j < 32; j++)
281 l[j] = r[j];
282
283 for (j = 0; j < 32; j++)
284 r[j] = r2[j];
285
286 kfree(er);
287 }
288
289 concat(rl, r, l, 32, 32);
290
291 permute(out, rl, perm6, 64);
292 kfree(pk1);
293}
294
295static void
296str_to_key(unsigned char *str, unsigned char *key)
297{
298 int i;
299
300 key[0] = str[0] >> 1;
301 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
302 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
303 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
304 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
305 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
306 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
307 key[7] = str[6] & 0x7F;
308 for (i = 0; i < 8; i++) {
309 key[i] = (key[i] << 1);
310 }
311}
312
313static void
314smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
315{
316 int i;
317 char *outb; /* outb[64] */
318 char *inb; /* inb[64] */
319 char *keyb; /* keyb[64] */
320 unsigned char key2[8];
321
322 outb = kmalloc(64 * 3,GFP_KERNEL);
323 if(outb == NULL)
324 return;
325
326 inb = outb + 64;
327 keyb = inb + 64;
328
329 str_to_key(key, key2);
330
331 for (i = 0; i < 64; i++) {
332 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
333 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
334 outb[i] = 0;
335 }
336
337 dohash(outb, inb, keyb, forw);
338
339 for (i = 0; i < 8; i++) {
340 out[i] = 0;
341 }
342
343 for (i = 0; i < 64; i++) {
344 if (outb[i])
345 out[i / 8] |= (1 << (7 - (i % 8)));
346 }
347 kfree(outb);
348}
349
350void
351E_P16(unsigned char *p14, unsigned char *p16)
352{
353 unsigned char sp8[8] =
354 { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
355 smbhash(p16, sp8, p14, 1);
356 smbhash(p16 + 8, sp8, p14 + 7, 1);
357}
358
359void
360E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
361{
362 smbhash(p24, c8, p21, 1);
363 smbhash(p24 + 8, c8, p21 + 7, 1);
364 smbhash(p24 + 16, c8, p21 + 14, 1);
365}
366
367void
368D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
369{
370 smbhash(out, in, p14, 0);
371 smbhash(out + 8, in + 8, p14 + 7, 0);
372}
373
374void
375E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
376{
377 smbhash(out, in, p14, 1);
378 smbhash(out + 8, in + 8, p14 + 7, 1);
379}
380#if 0
381/* these routines are currently unneeded, but may be
382 needed later */
383void
384cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
385{
386 unsigned char buf[8];
387
388 smbhash(buf, in, key, 1);
389 smbhash(out, buf, key + 9, 1);
390}
391
392void
393cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
394{
395 unsigned char buf[8];
396 static unsigned char key2[8];
397
398 smbhash(buf, in, key, 1);
399 key2[0] = key[7];
400 smbhash(out, buf, key2, 1);
401}
402
403void
404cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
405{
406 static unsigned char key2[8];
407
408 smbhash(out, in, key, forw);
409 key2[0] = key[7];
410 smbhash(out + 8, in + 8, key2, forw);
411}
412#endif /* unneeded routines */
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
new file mode 100644
index 000000000000..6103bcdfb16d
--- /dev/null
+++ b/fs/cifs/smbencrypt.c
@@ -0,0 +1,285 @@
1/*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 SMB parameters and setup
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Luke Kenneth Casson Leighton 1996-2000
7 Modified by Jeremy Allison 1995.
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
9 Modified by Steve French (sfrench@us.ibm.com) 2002-2003
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24*/
25
26#include <linux/module.h>
27#include <linux/fs.h>
28#include <linux/string.h>
29#include <linux/kernel.h>
30#include <linux/random.h>
31#include "cifs_unicode.h"
32#include "cifspdu.h"
33#include "md5.h"
34#include "cifs_debug.h"
35#include "cifsencrypt.h"
36
37#ifndef FALSE
38#define FALSE 0
39#endif
40#ifndef TRUE
41#define TRUE 1
42#endif
43
44/* following came from the other byteorder.h to avoid include conflicts */
45#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
46#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
47#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
48
49/*The following definitions come from libsmb/smbencrypt.c */
50
51void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
52void E_md4hash(const unsigned char *passwd, unsigned char *p16);
53void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
54static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
55 unsigned char p24[24]);
56void NTLMSSPOWFencrypt(unsigned char passwd[8],
57 unsigned char *ntlmchalresp, unsigned char p24[24]);
58void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
59
60/*
61 This implements the X/Open SMB password encryption
62 It takes a password, a 8 byte "crypt key" and puts 24 bytes of
63 encrypted password into p24 */
64/* Note that password must be uppercased and null terminated */
65void
66SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
67{
68 unsigned char p14[15], p21[21];
69
70 memset(p21, '\0', 21);
71 memset(p14, '\0', 14);
72 strncpy((char *) p14, (char *) passwd, 14);
73
74/* strupper((char *)p14); *//* BB at least uppercase the easy range */
75 E_P16(p14, p21);
76
77 SMBOWFencrypt(p21, c8, p24);
78
79 memset(p14,0,15);
80 memset(p21,0,21);
81}
82
83/* Routines for Windows NT MD4 Hash functions. */
84static int
85_my_wcslen(__u16 * str)
86{
87 int len = 0;
88 while (*str++ != 0)
89 len++;
90 return len;
91}
92
93/*
94 * Convert a string into an NT UNICODE string.
95 * Note that regardless of processor type
96 * this must be in intel (little-endian)
97 * format.
98 */
99
100static int
101_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
102{ /* not a very good conversion routine - change/fix */
103 int i;
104 __u16 val;
105
106 for (i = 0; i < len; i++) {
107 val = *src;
108 SSVAL(dst, 0, val);
109 dst++;
110 src++;
111 if (val == 0)
112 break;
113 }
114 return i;
115}
116
117/*
118 * Creates the MD4 Hash of the users password in NT UNICODE.
119 */
120
121void
122E_md4hash(const unsigned char *passwd, unsigned char *p16)
123{
124 int len;
125 __u16 wpwd[129];
126
127 /* Password cannot be longer than 128 characters */
128 if(passwd) {
129 len = strlen((char *) passwd);
130 if (len > 128) {
131 len = 128;
132 }
133 /* Password must be converted to NT unicode */
134 _my_mbstowcs(wpwd, passwd, len);
135 } else
136 len = 0;
137
138 wpwd[len] = 0; /* Ensure string is null terminated */
139 /* Calculate length in bytes */
140 len = _my_wcslen(wpwd) * sizeof (__u16);
141
142 mdfour(p16, (unsigned char *) wpwd, len);
143 memset(wpwd,0,129 * 2);
144}
145
146/* Does both the NT and LM owfs of a user's password */
147void
148nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
149{
150 char passwd[514];
151
152 memset(passwd, '\0', 514);
153 if (strlen(pwd) < 513)
154 strcpy(passwd, pwd);
155 else
156 memcpy(passwd, pwd, 512);
157 /* Calculate the MD4 hash (NT compatible) of the password */
158 memset(nt_p16, '\0', 16);
159 E_md4hash(passwd, nt_p16);
160
161 /* Mangle the passwords into Lanman format */
162 passwd[14] = '\0';
163/* strupper(passwd); */
164
165 /* Calculate the SMB (lanman) hash functions of the password */
166
167 memset(p16, '\0', 16);
168 E_P16((unsigned char *) passwd, (unsigned char *) p16);
169
170 /* clear out local copy of user's password (just being paranoid). */
171 memset(passwd, '\0', sizeof (passwd));
172}
173
174/* Does the NTLMv2 owfs of a user's password */
175#if 0 /* function not needed yet - but will be soon */
176static void
177ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
178 const char *domain_n, unsigned char kr_buf[16],
179 const struct nls_table *nls_codepage)
180{
181 wchar_t * user_u;
182 wchar_t * dom_u;
183 int user_l, domain_l;
184 struct HMACMD5Context ctx;
185
186 /* might as well do one alloc to hold both (user_u and dom_u) */
187 user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL);
188 if(user_u == NULL)
189 return;
190 dom_u = user_u + 1024;
191
192 /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
193 push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
194
195 /* BB user and domain may need to be uppercased */
196 user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
197 domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
198
199 user_l++; /* trailing null */
200 domain_l++;
201
202 hmac_md5_init_limK_to_64(owf, 16, &ctx);
203 hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
204 hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
205 hmac_md5_final(kr_buf, &ctx);
206
207 kfree(user_u);
208}
209#endif
210
211/* Does the des encryption from the NT or LM MD4 hash. */
212static void
213SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
214 unsigned char p24[24])
215{
216 unsigned char p21[21];
217
218 memset(p21, '\0', 21);
219
220 memcpy(p21, passwd, 16);
221 E_P24(p21, c8, p24);
222}
223
224/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
225void
226NTLMSSPOWFencrypt(unsigned char passwd[8],
227 unsigned char *ntlmchalresp, unsigned char p24[24])
228{
229 unsigned char p21[21];
230
231 memset(p21, '\0', 21);
232 memcpy(p21, passwd, 8);
233 memset(p21 + 8, 0xbd, 8);
234
235 E_P24(p21, ntlmchalresp, p24);
236}
237
238/* Does the NT MD4 hash then des encryption. */
239
240void
241SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
242{
243 unsigned char p21[21];
244
245 memset(p21, '\0', 21);
246
247 E_md4hash(passwd, p21);
248 SMBOWFencrypt(p21, c8, p24);
249}
250
251
252/* Does the md5 encryption from the NT hash for NTLMv2. */
253/* These routines will be needed later */
254#if 0
255static void
256SMBOWFencrypt_ntv2(const unsigned char kr[16],
257 const struct data_blob * srv_chal,
258 const struct data_blob * cli_chal, unsigned char resp_buf[16])
259{
260 struct HMACMD5Context ctx;
261
262 hmac_md5_init_limK_to_64(kr, 16, &ctx);
263 hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
264 hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
265 hmac_md5_final(resp_buf, &ctx);
266}
267
268static void
269SMBsesskeygen_ntv2(const unsigned char kr[16],
270 const unsigned char *nt_resp, __u8 sess_key[16])
271{
272 struct HMACMD5Context ctx;
273
274 hmac_md5_init_limK_to_64(kr, 16, &ctx);
275 hmac_md5_update(nt_resp, 16, &ctx);
276 hmac_md5_final((unsigned char *) sess_key, &ctx);
277}
278
279static void
280SMBsesskeygen_ntv1(const unsigned char kr[16],
281 const unsigned char *nt_resp, __u8 sess_key[16])
282{
283 mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
284}
285#endif
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
new file mode 100644
index 000000000000..e21f1384661f
--- /dev/null
+++ b/fs/cifs/smberr.h
@@ -0,0 +1,115 @@
1/*
2 * fs/cifs/smberr.h
3 *
4 * Copyright (c) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * See Error Codes section of the SNIA CIFS Specification
8 * for more information
9 *
10 * This library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#define SUCCESS 0 /* The request was successful. */
26#define ERRDOS 0x01 /* Error is from the core DOS operating system set */
27#define ERRSRV 0x02 /* Error is generated by the file server daemon */
28#define ERRHRD 0x03 /* Error is a hardware error. */
29#define ERRCMD 0xFF /* Command was not in the "SMB" format. */
30
31/* The following error codes may be generated with the SUCCESS error class.*/
32
33#define SUCCESS 0 /* The request was successful. */
34
35/* The following error codes may be generated with the ERRDOS error class.*/
36
37#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */
38#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */
39#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */
40#define ERRnofids 4 /* Too many open files. The server has no file handles available. */
41#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */
42#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */
43#define ERRbadmcb 7 /* Memory control blocks destroyed. */
44#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */
45#define ERRbadmem 9 /* Invalid memory block address. */
46#define ERRbadenv 10 /* Invalid environment. */
47#define ERRbadformat 11 /* Invalid format. */
48#define ERRbadaccess 12 /* Invalid open mode. */
49#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */
50#define ERRbaddrive 15 /* Invalid drive specified. */
51#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */
52#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */
53#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */
54#define ERRgeneral 31
55#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
56#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */
57#define ERRunsup 50
58#define ERRnosuchshare 67
59#define ERRfilexists 80 /* The file named in the request already exists. */
60#define ERRinvparm 87
61#define ERRdiskfull 112
62#define ERRinvname 123
63#define ERRinvlevel 124
64#define ERRdirnotempty 145
65#define ERRnotlocked 158
66#define ERRalreadyexists 183
67#define ERRbadpipe 230
68#define ERRpipebusy 231
69#define ERRpipeclosing 232
70#define ERRnotconnected 233
71#define ERRmoredata 234
72#define ERReasnotsupported 282
73#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */
74#define ErrNotALink 0x201 /* A link operation was performed on a pathname that
75 was not a link. */
76
77/* Following error codes may be generated with the ERRSRV error
78class.*/
79
80#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */
81#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
82#define ERRbadtype 3 /* used for indicating DFS referral needed */
83#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */
84#define ERRinvtid 5 /* The Tid specified in a command was invalid. */
85#define ERRinvnetname 6 /* Invalid network name in tree connect. */
86#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
87#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */
88#define ERRqtoobig 50 /* Print queue full -- no space. */
89#define ERRqeof 51 /* EOF on print queue dump */
90#define ERRinvpfid 52 /* Invalid print file FID. */
91#define ERRsmbcmd 64 /* The server did not recognize the command received. */
92#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */
93#define ERRbadBID 66 /* (obsolete) */
94#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */
95#define ERRbadLink 68 /* (obsolete) */
96#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */
97#define ERRbadPID 70
98#define ERRsetattrmode 71 /* attribute (mode) is invalid */
99#define ERRpaused 81 /* Server is paused */
100#define ERRmsgoff 82 /* reserved - messaging off */
101#define ERRnoroom 83 /* reserved - no room for message */
102#define ERRrmuns 87 /* reserved - too many remote names */
103#define ERRtimeout 88 /* operation timed out */
104#define ERRnoresource 89 /* No resources available for request */
105#define ERRtoomanyuids 90 /* Too many UIDs active on this session */
106#define ERRbaduid 91 /* The UID is not known as a valid user */
107#define ERRusempx 250 /* temporarily unable to use raw */
108#define ERRusestd 251 /* temporarily unable to use either raw or mpx */
109#define ERR_NOTIFY_ENUM_DIR 1024
110#define ERRaccountexpired 2239
111#define ERRbadclient 2240
112#define ERRbadLogonTime 2241
113#define ERRpasswordExpired 2242
114#define ERRnetlogonNotStarted 2455
115#define ERRnosupport 0xFFFF
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
new file mode 100644
index 000000000000..af13e526b150
--- /dev/null
+++ b/fs/cifs/transport.c
@@ -0,0 +1,619 @@
1/*
2 * fs/cifs/transport.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/fs.h>
23#include <linux/list.h>
24#include <linux/wait.h>
25#include <linux/net.h>
26#include <linux/delay.h>
27#include <asm/uaccess.h>
28#include <asm/processor.h>
29#include <linux/mempool.h>
30#include "cifspdu.h"
31#include "cifsglob.h"
32#include "cifsproto.h"
33#include "cifs_debug.h"
34
35extern mempool_t *cifs_mid_poolp;
36extern kmem_cache_t *cifs_oplock_cachep;
37
38static struct mid_q_entry *
39AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
40{
41 struct mid_q_entry *temp;
42
43 if (ses == NULL) {
44 cERROR(1, ("Null session passed in to AllocMidQEntry "));
45 return NULL;
46 }
47 if (ses->server == NULL) {
48 cERROR(1, ("Null TCP session in AllocMidQEntry"));
49 return NULL;
50 }
51
52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS);
53 if (temp == NULL)
54 return temp;
55 else {
56 memset(temp, 0, sizeof (struct mid_q_entry));
57 temp->mid = smb_buffer->Mid; /* always LE */
58 temp->pid = current->pid;
59 temp->command = smb_buffer->Command;
60 cFYI(1, ("For smb_command %d", temp->command));
61 do_gettimeofday(&temp->when_sent);
62 temp->ses = ses;
63 temp->tsk = current;
64 }
65
66 spin_lock(&GlobalMid_Lock);
67 list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
68 atomic_inc(&midCount);
69 temp->midState = MID_REQUEST_ALLOCATED;
70 spin_unlock(&GlobalMid_Lock);
71 return temp;
72}
73
74static void
75DeleteMidQEntry(struct mid_q_entry *midEntry)
76{
77 spin_lock(&GlobalMid_Lock);
78 midEntry->midState = MID_FREE;
79 list_del(&midEntry->qhead);
80 atomic_dec(&midCount);
81 spin_unlock(&GlobalMid_Lock);
82 cifs_buf_release(midEntry->resp_buf);
83 mempool_free(midEntry, cifs_mid_poolp);
84}
85
86struct oplock_q_entry *
87AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
88{
89 struct oplock_q_entry *temp;
90 if ((pinode== NULL) || (tcon == NULL)) {
91 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
92 return NULL;
93 }
94 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
95 SLAB_KERNEL);
96 if (temp == NULL)
97 return temp;
98 else {
99 temp->pinode = pinode;
100 temp->tcon = tcon;
101 temp->netfid = fid;
102 spin_lock(&GlobalMid_Lock);
103 list_add_tail(&temp->qhead, &GlobalOplock_Q);
104 spin_unlock(&GlobalMid_Lock);
105 }
106 return temp;
107
108}
109
110void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
111{
112 spin_lock(&GlobalMid_Lock);
113 /* should we check if list empty first? */
114 list_del(&oplockEntry->qhead);
115 spin_unlock(&GlobalMid_Lock);
116 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
117}
118
119int
120smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
121 unsigned int smb_buf_length, struct sockaddr *sin)
122{
123 int rc = 0;
124 int i = 0;
125 struct msghdr smb_msg;
126 struct kvec iov;
127 unsigned len = smb_buf_length + 4;
128
129 if(ssocket == NULL)
130 return -ENOTSOCK; /* BB eventually add reconnect code here */
131 iov.iov_base = smb_buffer;
132 iov.iov_len = len;
133
134 smb_msg.msg_name = sin;
135 smb_msg.msg_namelen = sizeof (struct sockaddr);
136 smb_msg.msg_control = NULL;
137 smb_msg.msg_controllen = 0;
138 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
139
140 /* smb header is converted in header_assemble. bcc and rest of SMB word
141 area, and byte area if necessary, is converted to littleendian in
142 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
143 Flags2 is converted in SendReceive */
144
145 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
146 cFYI(1, ("Sending smb of length %d ", smb_buf_length));
147 dump_smb(smb_buffer, len);
148
149 while (len > 0) {
150 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
151 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
152 i++;
153 if(i > 60) {
154 cERROR(1,
155 ("sends on sock %p stuck for 30 seconds",
156 ssocket));
157 rc = -EAGAIN;
158 break;
159 }
160 msleep(500);
161 continue;
162 }
163 if (rc < 0)
164 break;
165 iov.iov_base += rc;
166 iov.iov_len -= rc;
167 len -= rc;
168 }
169
170 if (rc < 0) {
171 cERROR(1,("Error %d sending data on socket to server.", rc));
172 } else {
173 rc = 0;
174 }
175
176 return rc;
177}
178
179#ifdef CIFS_EXPERIMENTAL
180/* BB finish off this function, adding support for writing set of pages as iovec */
181/* and also adding support for operations that need to parse the response smb */
182
183int
184smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
185 unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin)
186{
187 int rc = 0;
188 int i = 0;
189 struct msghdr smb_msg;
190 number_of_pages += 1; /* account for SMB header */
191 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec));
192 if(i=0;i<num_pages-1;i++
193 unsigned len = smb_buf_length + 4;
194
195 if(ssocket == NULL)
196 return -ENOTSOCK; /* BB eventually add reconnect code here */
197 iov.iov_base = smb_buffer;
198 iov.iov_len = len;
199
200 smb_msg.msg_name = sin;
201 smb_msg.msg_namelen = sizeof (struct sockaddr);
202 smb_msg.msg_control = NULL;
203 smb_msg.msg_controllen = 0;
204 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
205
206 /* smb header is converted in header_assemble. bcc and rest of SMB word
207 area, and byte area if necessary, is converted to littleendian in
208 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
209 Flags2 is converted in SendReceive */
210
211 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
212 cFYI(1, ("Sending smb of length %d ", smb_buf_length));
213 dump_smb(smb_buffer, len);
214
215 while (len > 0) {
216 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?);
217 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
218 i++;
219 if(i > 60) {
220 cERROR(1,
221 ("sends on sock %p stuck for 30 seconds",
222 ssocket));
223 rc = -EAGAIN;
224 break;
225 }
226 msleep(500);
227 continue;
228 }
229 if (rc < 0)
230 break;
231 iov.iov_base += rc;
232 iov.iov_len -= rc;
233 len -= rc;
234 }
235
236 if (rc < 0) {
237 cERROR(1,("Error %d sending data on socket to server.", rc));
238 } else {
239 rc = 0;
240 }
241
242 return rc;
243}
244
245
246int
247CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
248 struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op)
249{
250 int rc = 0;
251 unsigned long timeout = 15 * HZ;
252 struct mid_q_entry *midQ = NULL;
253
254 if (ses == NULL) {
255 cERROR(1,("Null smb session"));
256 return -EIO;
257 }
258 if(ses->server == NULL) {
259 cERROR(1,("Null tcp session"));
260 return -EIO;
261 }
262 if(pbytes_returned == NULL)
263 return -EIO;
264 else
265 *pbytes_returned = 0;
266
267
268
269 /* Ensure that we do not send more than 50 overlapping requests
270 to the same server. We may make this configurable later or
271 use ses->maxReq */
272 if(long_op == -1) {
273 /* oplock breaks must not be held up */
274 atomic_inc(&ses->server->inFlight);
275 } else {
276 spin_lock(&GlobalMid_Lock);
277 while(1) {
278 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
279 spin_unlock(&GlobalMid_Lock);
280 wait_event(ses->server->request_q,
281 atomic_read(&ses->server->inFlight)
282 < cifs_max_pending);
283 spin_lock(&GlobalMid_Lock);
284 } else {
285 if(ses->server->tcpStatus == CifsExiting) {
286 spin_unlock(&GlobalMid_Lock);
287 return -ENOENT;
288 }
289
290 /* can not count locking commands against total since
291 they are allowed to block on server */
292
293 if(long_op < 3) {
294 /* update # of requests on the wire to server */
295 atomic_inc(&ses->server->inFlight);
296 }
297 spin_unlock(&GlobalMid_Lock);
298 break;
299 }
300 }
301 }
302 /* make sure that we sign in the same order that we send on this socket
303 and avoid races inside tcp sendmsg code that could cause corruption
304 of smb data */
305
306 down(&ses->server->tcpSem);
307
308 if (ses->server->tcpStatus == CifsExiting) {
309 rc = -ENOENT;
310 goto cifs_out_label;
311 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
312 cFYI(1,("tcp session dead - return to caller to retry"));
313 rc = -EAGAIN;
314 goto cifs_out_label;
315 } else if (ses->status != CifsGood) {
316 /* check if SMB session is bad because we are setting it up */
317 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
318 (in_buf->Command != SMB_COM_NEGOTIATE)) {
319 rc = -EAGAIN;
320 goto cifs_out_label;
321 } /* else ok - we are setting up session */
322 }
323 midQ = AllocMidQEntry(in_buf, ses);
324 if (midQ == NULL) {
325 up(&ses->server->tcpSem);
326 /* If not lock req, update # of requests on wire to server */
327 if(long_op < 3) {
328 atomic_dec(&ses->server->inFlight);
329 wake_up(&ses->server->request_q);
330 }
331 return -ENOMEM;
332 }
333
334 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
335 up(&ses->server->tcpSem);
336 cERROR(1,
337 ("Illegal length, greater than maximum frame, %d ",
338 in_buf->smb_buf_length));
339 DeleteMidQEntry(midQ);
340 /* If not lock req, update # of requests on wire to server */
341 if(long_op < 3) {
342 atomic_dec(&ses->server->inFlight);
343 wake_up(&ses->server->request_q);
344 }
345 return -EIO;
346 }
347
348 /* BB can we sign efficiently in this path? */
349 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
350
351 midQ->midState = MID_REQUEST_SUBMITTED;
352/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec,
353 (struct sockaddr *) &(ses->server->addr.sockAddr));*/
354 if(rc < 0) {
355 DeleteMidQEntry(midQ);
356 up(&ses->server->tcpSem);
357 /* If not lock req, update # of requests on wire to server */
358 if(long_op < 3) {
359 atomic_dec(&ses->server->inFlight);
360 wake_up(&ses->server->request_q);
361 }
362 return rc;
363 } else
364 up(&ses->server->tcpSem);
365cifs_out_label:
366 if(midQ)
367 DeleteMidQEntry(midQ);
368
369 if(long_op < 3) {
370 atomic_dec(&ses->server->inFlight);
371 wake_up(&ses->server->request_q);
372 }
373
374 return rc;
375}
376
377
378#endif /* CIFS_EXPERIMENTAL */
379
380int
381SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
382 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
383 int *pbytes_returned, const int long_op)
384{
385 int rc = 0;
386 unsigned int receive_len;
387 unsigned long timeout;
388 struct mid_q_entry *midQ;
389
390 if (ses == NULL) {
391 cERROR(1,("Null smb session"));
392 return -EIO;
393 }
394 if(ses->server == NULL) {
395 cERROR(1,("Null tcp session"));
396 return -EIO;
397 }
398
399 /* Ensure that we do not send more than 50 overlapping requests
400 to the same server. We may make this configurable later or
401 use ses->maxReq */
402 if(long_op == -1) {
403 /* oplock breaks must not be held up */
404 atomic_inc(&ses->server->inFlight);
405 } else {
406 spin_lock(&GlobalMid_Lock);
407 while(1) {
408 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
409 spin_unlock(&GlobalMid_Lock);
410 wait_event(ses->server->request_q,
411 atomic_read(&ses->server->inFlight)
412 < cifs_max_pending);
413 spin_lock(&GlobalMid_Lock);
414 } else {
415 if(ses->server->tcpStatus == CifsExiting) {
416 spin_unlock(&GlobalMid_Lock);
417 return -ENOENT;
418 }
419
420 /* can not count locking commands against total since
421 they are allowed to block on server */
422
423 if(long_op < 3) {
424 /* update # of requests on the wire to server */
425 atomic_inc(&ses->server->inFlight);
426 }
427 spin_unlock(&GlobalMid_Lock);
428 break;
429 }
430 }
431 }
432 /* make sure that we sign in the same order that we send on this socket
433 and avoid races inside tcp sendmsg code that could cause corruption
434 of smb data */
435
436 down(&ses->server->tcpSem);
437
438 if (ses->server->tcpStatus == CifsExiting) {
439 rc = -ENOENT;
440 goto out_unlock;
441 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
442 cFYI(1,("tcp session dead - return to caller to retry"));
443 rc = -EAGAIN;
444 goto out_unlock;
445 } else if (ses->status != CifsGood) {
446 /* check if SMB session is bad because we are setting it up */
447 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
448 (in_buf->Command != SMB_COM_NEGOTIATE)) {
449 rc = -EAGAIN;
450 goto out_unlock;
451 } /* else ok - we are setting up session */
452 }
453 midQ = AllocMidQEntry(in_buf, ses);
454 if (midQ == NULL) {
455 up(&ses->server->tcpSem);
456 /* If not lock req, update # of requests on wire to server */
457 if(long_op < 3) {
458 atomic_dec(&ses->server->inFlight);
459 wake_up(&ses->server->request_q);
460 }
461 return -ENOMEM;
462 }
463
464 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
465 up(&ses->server->tcpSem);
466 cERROR(1,
467 ("Illegal length, greater than maximum frame, %d ",
468 in_buf->smb_buf_length));
469 DeleteMidQEntry(midQ);
470 /* If not lock req, update # of requests on wire to server */
471 if(long_op < 3) {
472 atomic_dec(&ses->server->inFlight);
473 wake_up(&ses->server->request_q);
474 }
475 return -EIO;
476 }
477
478 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
479
480 midQ->midState = MID_REQUEST_SUBMITTED;
481 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
482 (struct sockaddr *) &(ses->server->addr.sockAddr));
483 if(rc < 0) {
484 DeleteMidQEntry(midQ);
485 up(&ses->server->tcpSem);
486 /* If not lock req, update # of requests on wire to server */
487 if(long_op < 3) {
488 atomic_dec(&ses->server->inFlight);
489 wake_up(&ses->server->request_q);
490 }
491 return rc;
492 } else
493 up(&ses->server->tcpSem);
494 if (long_op == -1)
495 goto cifs_no_response_exit;
496 else if (long_op == 2) /* writes past end of file can take looooong time */
497 timeout = 300 * HZ;
498 else if (long_op == 1)
499 timeout = 45 * HZ; /* should be greater than
500 servers oplock break timeout (about 43 seconds) */
501 else if (long_op > 2) {
502 timeout = MAX_SCHEDULE_TIMEOUT;
503 } else
504 timeout = 15 * HZ;
505 /* wait for 15 seconds or until woken up due to response arriving or
506 due to last connection to this server being unmounted */
507 if (signal_pending(current)) {
508 /* if signal pending do not hold up user for full smb timeout
509 but we still give response a change to complete */
510 timeout = 2 * HZ;
511 }
512
513 /* No user interrupts in wait - wreaks havoc with performance */
514 if(timeout != MAX_SCHEDULE_TIMEOUT) {
515 timeout += jiffies;
516 wait_event(ses->server->response_q,
517 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
518 time_after(jiffies, timeout) ||
519 ((ses->server->tcpStatus != CifsGood) &&
520 (ses->server->tcpStatus != CifsNew)));
521 } else {
522 wait_event(ses->server->response_q,
523 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
524 ((ses->server->tcpStatus != CifsGood) &&
525 (ses->server->tcpStatus != CifsNew)));
526 }
527
528 spin_lock(&GlobalMid_Lock);
529 if (midQ->resp_buf) {
530 spin_unlock(&GlobalMid_Lock);
531 receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
532 } else {
533 cERROR(1,("No response buffer"));
534 if(midQ->midState == MID_REQUEST_SUBMITTED) {
535 if(ses->server->tcpStatus == CifsExiting)
536 rc = -EHOSTDOWN;
537 else {
538 ses->server->tcpStatus = CifsNeedReconnect;
539 midQ->midState = MID_RETRY_NEEDED;
540 }
541 }
542
543 if (rc != -EHOSTDOWN) {
544 if(midQ->midState == MID_RETRY_NEEDED) {
545 rc = -EAGAIN;
546 cFYI(1,("marking request for retry"));
547 } else {
548 rc = -EIO;
549 }
550 }
551 spin_unlock(&GlobalMid_Lock);
552 DeleteMidQEntry(midQ);
553 /* If not lock req, update # of requests on wire to server */
554 if(long_op < 3) {
555 atomic_dec(&ses->server->inFlight);
556 wake_up(&ses->server->request_q);
557 }
558 return rc;
559 }
560
561 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
562 cERROR(1,
563 ("Frame too large received. Length: %d Xid: %d",
564 receive_len, xid));
565 rc = -EIO;
566 } else { /* rcvd frame is ok */
567
568 if (midQ->resp_buf && out_buf
569 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
570 out_buf->smb_buf_length = receive_len;
571 memcpy((char *)out_buf + 4,
572 (char *)midQ->resp_buf + 4,
573 receive_len);
574
575 dump_smb(out_buf, 92);
576 /* convert the length into a more usable form */
577 if((receive_len > 24) &&
578 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
579 rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
580 if(rc)
581 cFYI(1,("Unexpected signature received from server"));
582 }
583
584 *pbytes_returned = out_buf->smb_buf_length;
585
586 /* BB special case reconnect tid and reconnect uid here? */
587 rc = map_smb_to_linux_error(out_buf);
588
589 /* convert ByteCount if necessary */
590 if (receive_len >=
591 sizeof (struct smb_hdr) -
592 4 /* do not count RFC1001 header */ +
593 (2 * out_buf->WordCount) + 2 /* bcc */ )
594 BCC(out_buf) = le16_to_cpu(BCC(out_buf));
595 } else {
596 rc = -EIO;
597 cFYI(1,("Bad MID state? "));
598 }
599 }
600cifs_no_response_exit:
601 DeleteMidQEntry(midQ);
602
603 if(long_op < 3) {
604 atomic_dec(&ses->server->inFlight);
605 wake_up(&ses->server->request_q);
606 }
607
608 return rc;
609
610out_unlock:
611 up(&ses->server->tcpSem);
612 /* If not lock req, update # of requests on wire to server */
613 if(long_op < 3) {
614 atomic_dec(&ses->server->inFlight);
615 wake_up(&ses->server->request_q);
616 }
617
618 return rc;
619}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
new file mode 100644
index 000000000000..549afa184fd6
--- /dev/null
+++ b/fs/cifs/xattr.c
@@ -0,0 +1,334 @@
1/*
2 * fs/cifs/xattr.c
3 *
4 * Copyright (c) International Business Machines Corp., 2003
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/fs.h>
23#include <linux/posix_acl_xattr.h>
24#include "cifsfs.h"
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifsproto.h"
28#include "cifs_debug.h"
29
30#define MAX_EA_VALUE_SIZE 65535
31#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
32#define CIFS_XATTR_USER_PREFIX "user."
33#define CIFS_XATTR_SYSTEM_PREFIX "system."
34#define CIFS_XATTR_OS2_PREFIX "os2."
35#define CIFS_XATTR_SECURITY_PREFIX ".security"
36#define CIFS_XATTR_TRUSTED_PREFIX "trusted."
37#define XATTR_TRUSTED_PREFIX_LEN 8
38#define XATTR_SECURITY_PREFIX_LEN 9
39/* BB need to add server (Samba e.g) support for security and trusted prefix */
40
41
42
43int cifs_removexattr(struct dentry * direntry, const char * ea_name)
44{
45 int rc = -EOPNOTSUPP;
46#ifdef CONFIG_CIFS_XATTR
47 int xid;
48 struct cifs_sb_info *cifs_sb;
49 struct cifsTconInfo *pTcon;
50 struct super_block * sb;
51 char * full_path;
52
53 if(direntry == NULL)
54 return -EIO;
55 if(direntry->d_inode == NULL)
56 return -EIO;
57 sb = direntry->d_inode->i_sb;
58 if(sb == NULL)
59 return -EIO;
60 xid = GetXid();
61
62 cifs_sb = CIFS_SB(sb);
63 pTcon = cifs_sb->tcon;
64
65 down(&sb->s_vfs_rename_sem);
66 full_path = build_path_from_dentry(direntry);
67 up(&sb->s_vfs_rename_sem);
68 if(full_path == NULL) {
69 FreeXid(xid);
70 return -ENOMEM;
71 }
72 if(ea_name == NULL) {
73 cFYI(1,("Null xattr names not supported"));
74 } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
75 && (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
76 cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
77 /* BB what if no namespace prefix? */
78 /* Should we just pass them to server, except for
79 system and perhaps security prefixes? */
80 } else {
81 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
82 goto remove_ea_exit;
83
84 ea_name+=5; /* skip past user. prefix */
85 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
86 (__u16)0, cifs_sb->local_nls);
87 }
88remove_ea_exit:
89 if (full_path)
90 kfree(full_path);
91 FreeXid(xid);
92#endif
93 return rc;
94}
95
96int cifs_setxattr(struct dentry * direntry, const char * ea_name,
97 const void * ea_value, size_t value_size, int flags)
98{
99 int rc = -EOPNOTSUPP;
100#ifdef CONFIG_CIFS_XATTR
101 int xid;
102 struct cifs_sb_info *cifs_sb;
103 struct cifsTconInfo *pTcon;
104 struct super_block * sb;
105 char * full_path;
106
107 if(direntry == NULL)
108 return -EIO;
109 if(direntry->d_inode == NULL)
110 return -EIO;
111 sb = direntry->d_inode->i_sb;
112 if(sb == NULL)
113 return -EIO;
114 xid = GetXid();
115
116 cifs_sb = CIFS_SB(sb);
117 pTcon = cifs_sb->tcon;
118
119 down(&sb->s_vfs_rename_sem);
120 full_path = build_path_from_dentry(direntry);
121 up(&sb->s_vfs_rename_sem);
122 if(full_path == NULL) {
123 FreeXid(xid);
124 return -ENOMEM;
125 }
126 /* return dos attributes as pseudo xattr */
127 /* return alt name if available as pseudo attr */
128
129 /* if proc/fs/cifs/streamstoxattr is set then
130 search server for EAs or streams to
131 returns as xattrs */
132 if(value_size > MAX_EA_VALUE_SIZE) {
133 cFYI(1,("size of EA value too large"));
134 if(full_path)
135 kfree(full_path);
136 FreeXid(xid);
137 return -EOPNOTSUPP;
138 }
139
140 if(ea_name == NULL) {
141 cFYI(1,("Null xattr names not supported"));
142 } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
143 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
144 goto set_ea_exit;
145 if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
146 cFYI(1,("attempt to set cifs inode metadata"));
147 }
148 ea_name += 5; /* skip past user. prefix */
149 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
150 (__u16)value_size, cifs_sb->local_nls);
151 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
152 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
153 goto set_ea_exit;
154
155 ea_name += 4; /* skip past os2. prefix */
156 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
157 (__u16)value_size, cifs_sb->local_nls);
158 } else {
159 int temp;
160 temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
161 strlen(POSIX_ACL_XATTR_ACCESS));
162 if (temp == 0) {
163#ifdef CONFIG_CIFS_POSIX
164 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value,
165 (const int)value_size, ACL_TYPE_ACCESS,
166 cifs_sb->local_nls);
167 cFYI(1,("set POSIX ACL rc %d",rc));
168#else
169 cFYI(1,("set POSIX ACL not supported"));
170#endif
171 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
172#ifdef CONFIG_CIFS_POSIX
173 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value,
174 (const int)value_size, ACL_TYPE_DEFAULT,
175 cifs_sb->local_nls);
176 cFYI(1,("set POSIX default ACL rc %d",rc));
177#else
178 cFYI(1,("set default POSIX ACL not supported"));
179#endif
180 } else {
181 cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name));
182 /* BB what if no namespace prefix? */
183 /* Should we just pass them to server, except for
184 system and perhaps security prefixes? */
185 }
186 }
187
188set_ea_exit:
189 if (full_path)
190 kfree(full_path);
191 FreeXid(xid);
192#endif
193 return rc;
194}
195
196ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
197 void * ea_value, size_t buf_size)
198{
199 ssize_t rc = -EOPNOTSUPP;
200#ifdef CONFIG_CIFS_XATTR
201 int xid;
202 struct cifs_sb_info *cifs_sb;
203 struct cifsTconInfo *pTcon;
204 struct super_block * sb;
205 char * full_path;
206
207 if(direntry == NULL)
208 return -EIO;
209 if(direntry->d_inode == NULL)
210 return -EIO;
211 sb = direntry->d_inode->i_sb;
212 if(sb == NULL)
213 return -EIO;
214
215 xid = GetXid();
216
217 cifs_sb = CIFS_SB(sb);
218 pTcon = cifs_sb->tcon;
219
220 down(&sb->s_vfs_rename_sem);
221 full_path = build_path_from_dentry(direntry);
222 up(&sb->s_vfs_rename_sem);
223 if(full_path == NULL) {
224 FreeXid(xid);
225 return -ENOMEM;
226 }
227 /* return dos attributes as pseudo xattr */
228 /* return alt name if available as pseudo attr */
229 if(ea_name == NULL) {
230 cFYI(1,("Null xattr names not supported"));
231 } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
232 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
233 goto get_ea_exit;
234
235 if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
236 cFYI(1,("attempt to query cifs inode metadata"));
237 /* revalidate/getattr then populate from inode */
238 } /* BB add else when above is implemented */
239 ea_name += 5; /* skip past user. prefix */
240 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
241 buf_size, cifs_sb->local_nls);
242 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
243 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
244 goto get_ea_exit;
245
246 ea_name += 4; /* skip past os2. prefix */
247 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
248 buf_size, cifs_sb->local_nls);
249 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
250#ifdef CONFIG_CIFS_POSIX
251 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
252 ea_value, buf_size, ACL_TYPE_ACCESS,
253 cifs_sb->local_nls);
254#else
255 cFYI(1,("query POSIX ACL not supported yet"));
256#endif /* CONFIG_CIFS_POSIX */
257 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
258#ifdef CONFIG_CIFS_POSIX
259 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
260 ea_value, buf_size, ACL_TYPE_DEFAULT,
261 cifs_sb->local_nls);
262#else
263 cFYI(1,("query POSIX default ACL not supported yet"));
264#endif
265 } else if(strncmp(ea_name,
266 CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) {
267 cFYI(1,("Trusted xattr namespace not supported yet"));
268 } else if(strncmp(ea_name,
269 CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) {
270 cFYI(1,("Security xattr namespace not supported yet"));
271 } else {
272 cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
273 }
274
275 /* We could add an additional check for streams ie
276 if proc/fs/cifs/streamstoxattr is set then
277 search server for EAs or streams to
278 returns as xattrs */
279
280 if(rc == -EINVAL)
281 rc = -EOPNOTSUPP;
282
283get_ea_exit:
284 if (full_path)
285 kfree(full_path);
286 FreeXid(xid);
287#endif
288 return rc;
289}
290
291ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
292{
293 ssize_t rc = -EOPNOTSUPP;
294#ifdef CONFIG_CIFS_XATTR
295 int xid;
296 struct cifs_sb_info *cifs_sb;
297 struct cifsTconInfo *pTcon;
298 struct super_block * sb;
299 char * full_path;
300
301 if(direntry == NULL)
302 return -EIO;
303 if(direntry->d_inode == NULL)
304 return -EIO;
305 sb = direntry->d_inode->i_sb;
306 if(sb == NULL)
307 return -EIO;
308 xid = GetXid();
309
310 cifs_sb = CIFS_SB(sb);
311 pTcon = cifs_sb->tcon;
312
313 down(&sb->s_vfs_rename_sem);
314 full_path = build_path_from_dentry(direntry);
315 up(&sb->s_vfs_rename_sem);
316 if(full_path == NULL) {
317 FreeXid(xid);
318 return -ENOMEM;
319 }
320 /* return dos attributes as pseudo xattr */
321 /* return alt name if available as pseudo attr */
322
323 /* if proc/fs/cifs/streamstoxattr is set then
324 search server for EAs or streams to
325 returns as xattrs */
326 rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
327 cifs_sb->local_nls);
328
329 if (full_path)
330 kfree(full_path);
331 FreeXid(xid);
332#endif
333 return rc;
334}