4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
22 #include <linux/slab.h>
23 #include <linux/ctype.h>
24 #include <linux/mempool.h>
27 #include "cifsproto.h"
28 #include "cifs_debug.h"
31 #include "cifs_unicode.h"
33 extern mempool_t *cifs_sm_req_poolp;
34 extern mempool_t *cifs_req_poolp;
35 extern struct task_struct * oplockThread;
37 static __u16 GlobalMid; /* multiplex id - rotating counter */
39 /* The xid serves as a useful identifier for each incoming vfs request,
40 in a similar way to the mid which is useful to track each sent smb,
41 and CurrentXid can also provide a running counter (although it
42 will eventually wrap past zero) of the total vfs operations handled
43 since the cifs fs was mounted */
50 spin_lock(&GlobalMid_Lock);
51 GlobalTotalActiveXid++;
52 if (GlobalTotalActiveXid > GlobalMaxActiveXid)
53 GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
54 xid = GlobalCurrentXid++;
55 spin_unlock(&GlobalMid_Lock);
60 _FreeXid(unsigned int xid)
62 spin_lock(&GlobalMid_Lock);
63 /* if(GlobalTotalActiveXid == 0)
65 GlobalTotalActiveXid--;
66 spin_unlock(&GlobalMid_Lock);
72 struct cifsSesInfo *ret_buf;
75 (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
78 memset(ret_buf, 0, sizeof (struct cifsSesInfo));
79 write_lock(&GlobalSMBSeslock);
80 atomic_inc(&sesInfoAllocCount);
81 ret_buf->status = CifsNew;
82 list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
83 init_MUTEX(&ret_buf->sesSem);
84 write_unlock(&GlobalSMBSeslock);
90 sesInfoFree(struct cifsSesInfo *buf_to_free)
92 if (buf_to_free == NULL) {
93 cFYI(1, ("Null buffer passed to sesInfoFree"));
97 write_lock(&GlobalSMBSeslock);
98 atomic_dec(&sesInfoAllocCount);
99 list_del(&buf_to_free->cifsSessionList);
100 write_unlock(&GlobalSMBSeslock);
101 if (buf_to_free->serverOS)
102 kfree(buf_to_free->serverOS);
103 if (buf_to_free->serverDomain)
104 kfree(buf_to_free->serverDomain);
105 if (buf_to_free->serverNOS)
106 kfree(buf_to_free->serverNOS);
107 if (buf_to_free->password)
108 kfree(buf_to_free->password);
112 struct cifsTconInfo *
115 struct cifsTconInfo *ret_buf;
117 (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
120 memset(ret_buf, 0, sizeof (struct cifsTconInfo));
121 write_lock(&GlobalSMBSeslock);
122 atomic_inc(&tconInfoAllocCount);
123 list_add(&ret_buf->cifsConnectionList,
124 &GlobalTreeConnectionList);
125 ret_buf->tidStatus = CifsNew;
126 INIT_LIST_HEAD(&ret_buf->openFileList);
127 init_MUTEX(&ret_buf->tconSem);
128 #ifdef CONFIG_CIFS_STATS
129 spin_lock_init(&ret_buf->stat_lock);
131 write_unlock(&GlobalSMBSeslock);
137 tconInfoFree(struct cifsTconInfo *buf_to_free)
139 if (buf_to_free == NULL) {
140 cFYI(1, ("Null buffer passed to tconInfoFree"));
143 write_lock(&GlobalSMBSeslock);
144 atomic_dec(&tconInfoAllocCount);
145 list_del(&buf_to_free->cifsConnectionList);
146 write_unlock(&GlobalSMBSeslock);
147 if (buf_to_free->nativeFileSystem)
148 kfree(buf_to_free->nativeFileSystem);
155 struct smb_hdr *ret_buf = NULL;
157 /* We could use negotiated size instead of max_msgsize -
158 but it may be more efficient to always alloc same size
159 albeit slightly larger than necessary and maxbuffersize
160 defaults to this and can not be bigger */
162 (struct smb_hdr *) mempool_alloc(cifs_req_poolp, SLAB_KERNEL | SLAB_NOFS);
164 /* clear the first few header bytes */
165 /* for most paths, more is cleared in header_assemble */
167 memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
168 atomic_inc(&bufAllocCount);
175 cifs_buf_release(void *buf_to_free)
178 if (buf_to_free == NULL) {
179 /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
182 mempool_free(buf_to_free,cifs_req_poolp);
184 atomic_dec(&bufAllocCount);
189 cifs_small_buf_get(void)
191 struct smb_hdr *ret_buf = NULL;
193 /* We could use negotiated size instead of max_msgsize -
194 but it may be more efficient to always alloc same size
195 albeit slightly larger than necessary and maxbuffersize
196 defaults to this and can not be bigger */
198 (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, SLAB_KERNEL | SLAB_NOFS);
200 /* No need to clear memory here, cleared in header assemble */
201 /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
202 atomic_inc(&smBufAllocCount);
208 cifs_small_buf_release(void *buf_to_free)
211 if (buf_to_free == NULL) {
212 cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
215 mempool_free(buf_to_free,cifs_sm_req_poolp);
217 atomic_dec(&smBufAllocCount);
222 header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
223 const struct cifsTconInfo *treeCon, int word_count
224 /* length of fixed section (word count) in two byte units */)
226 struct list_head* temp_item;
227 struct cifsSesInfo * ses;
228 char *temp = (char *) buffer;
230 memset(temp,0,MAX_CIFS_HDR_SIZE);
232 buffer->smb_buf_length =
233 (2 * word_count) + sizeof (struct smb_hdr) -
234 4 /* RFC 1001 length field does not count */ +
235 2 /* for bcc field itself */ ;
236 /* 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 */
238 buffer->Protocol[0] = 0xFF;
239 buffer->Protocol[1] = 'S';
240 buffer->Protocol[2] = 'M';
241 buffer->Protocol[3] = 'B';
242 buffer->Command = smb_command;
243 buffer->Flags = 0x00; /* case sensitive */
244 buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
245 buffer->Pid = cpu_to_le16((__u16)current->tgid);
246 buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
247 spin_lock(&GlobalMid_Lock);
249 buffer->Mid = GlobalMid;
250 spin_unlock(&GlobalMid_Lock);
252 buffer->Tid = treeCon->tid;
254 if (treeCon->ses->capabilities & CAP_UNICODE)
255 buffer->Flags2 |= SMBFLG2_UNICODE;
256 if (treeCon->ses->capabilities & CAP_STATUS32) {
257 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
260 buffer->Uid = treeCon->ses->Suid; /* always in LE format */
261 if(multiuser_mount != 0) {
262 /* For the multiuser case, there are few obvious technically */
263 /* possible mechanisms to match the local linux user (uid) */
264 /* to a valid remote smb user (smb_uid): */
265 /* 1) Query Winbind (or other local pam/nss daemon */
266 /* for userid/password/logon_domain or credential */
267 /* 2) Query Winbind for uid to sid to username mapping */
268 /* and see if we have a matching password for existing*/
269 /* session for that user perhas getting password by */
270 /* adding a new pam_cifs module that stores passwords */
271 /* so that the cifs vfs can get at that for all logged*/
273 /* 3) (Which is the mechanism we have chosen) */
274 /* Search through sessions to the same server for a */
275 /* a match on the uid that was passed in on mount */
276 /* with the current processes uid (or euid?) and use */
277 /* that smb uid. If no existing smb session for */
278 /* that uid found, use the default smb session ie */
279 /* the smb session for the volume mounted which is */
280 /* the same as would be used if the multiuser mount */
281 /* flag were disabled. */
283 /* BB Add support for establishing new tCon and SMB Session */
284 /* with userid/password pairs found on the smb session */
285 /* for other target tcp/ip addresses BB */
286 if(current->uid != treeCon->ses->linux_uid) {
287 cFYI(1,("Multiuser mode and UID did not match tcon uid "));
288 read_lock(&GlobalSMBSeslock);
289 list_for_each(temp_item, &GlobalSMBSessionList) {
290 ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
291 if(ses->linux_uid == current->uid) {
292 if(ses->server == treeCon->ses->server) {
293 cFYI(1,("found matching uid substitute right smb_uid"));
294 buffer->Uid = ses->Suid;
297 /* BB eventually call cifs_setup_session here */
298 cFYI(1,("local UID found but smb sess with this server does not exist"));
302 read_unlock(&GlobalSMBSeslock);
306 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
307 buffer->Flags2 |= SMBFLG2_DFS;
308 if((treeCon->ses) && (treeCon->ses->server))
309 if(treeCon->ses->server->secMode &
310 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
311 buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
314 /* endian conversion of flags is now done just before sending */
315 buffer->WordCount = (char) word_count;
320 checkSMBhdr(struct smb_hdr *smb, __u16 mid)
322 /* Make sure that this really is an SMB, that it is a response,
323 and that the message ids match */
324 if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
326 if(smb->Flags & SMBFLG_RESPONSE)
329 /* only one valid case where server sends us request */
330 if(smb->Command == SMB_COM_LOCKING_ANDX)
333 cERROR(1, ("Rcvd Request not response "));
335 } else { /* bad signature or mid */
336 if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
338 ("Bad protocol string signature header %x ",
339 *(unsigned int *) smb->Protocol));
341 cERROR(1, ("Mids do not match"));
343 cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
348 checkSMB(struct smb_hdr *smb, __u16 mid, int length)
350 __u32 len = be32_to_cpu(smb->smb_buf_length);
352 ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
354 if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
355 (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
356 if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
357 if (((unsigned int)length >=
358 sizeof (struct smb_hdr) - 1)
359 && (smb->Status.CifsError != 0)) {
361 return 0; /* some error cases do not return wct and bcc */
363 cERROR(1, ("Length less than smb header size"));
367 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
369 ("smb_buf_length greater than MaxBufSize"));
371 ("bad smb detected. Illegal length. The mid=%d",
376 if (checkSMBhdr(smb, mid))
379 if ((4 + len != smbCalcSize(smb))
380 || (4 + len != (unsigned int)length)) {
383 cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
385 ("bad smb size detected. The Mid=%d", smb->Mid));
390 is_valid_oplock_break(struct smb_hdr *buf)
392 struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
393 struct list_head *tmp;
394 struct list_head *tmp1;
395 struct cifsTconInfo *tcon;
396 struct cifsFileInfo *netfile;
398 cFYI(1,("Checking for oplock break or dnotify response"));
399 if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
400 (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
401 struct smb_com_transaction_change_notify_rsp * pSMBr =
402 (struct smb_com_transaction_change_notify_rsp *)buf;
403 struct file_notify_information * pnotify;
404 __u32 data_offset = 0;
405 if(pSMBr->ByteCount > sizeof(struct file_notify_information)) {
406 data_offset = le32_to_cpu(pSMBr->DataOffset);
408 pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol
410 cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName,
411 pnotify->Action)); /* BB removeme BB */
412 /* cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */
415 if(pSMBr->hdr.Status.CifsError) {
416 cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError));
421 if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
423 if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
424 /* no sense logging error on invalid handle on oplock
425 break - harmless race between close request and oplock
426 break response is expected from time to time writing out
427 large dirty files cached on the client */
428 if ((NT_STATUS_INVALID_HANDLE) ==
429 le32_to_cpu(pSMB->hdr.Status.CifsError)) {
430 cFYI(1,("invalid handle on oplock break"));
432 } else if (ERRbadfid ==
433 le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
436 return FALSE; /* on valid oplock brk we get "request" */
439 if(pSMB->hdr.WordCount != 8)
442 cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
443 if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
446 /* look up tcon based on tid & uid */
447 read_lock(&GlobalSMBSeslock);
448 list_for_each(tmp, &GlobalTreeConnectionList) {
449 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
450 if (tcon->tid == buf->Tid) {
451 #ifdef CONFIG_CIFS_STATS
452 atomic_inc(&tcon->num_oplock_brks);
454 list_for_each(tmp1,&tcon->openFileList){
455 netfile = list_entry(tmp1,struct cifsFileInfo,
457 if(pSMB->Fid == netfile->netfid) {
458 struct cifsInodeInfo *pCifsInode;
459 read_unlock(&GlobalSMBSeslock);
460 cFYI(1,("file id match, oplock break"));
462 CIFS_I(netfile->pInode);
463 pCifsInode->clientCanCacheAll = FALSE;
464 if(pSMB->OplockLevel == 0)
465 pCifsInode->clientCanCacheRead
467 pCifsInode->oplockPending = TRUE;
468 AllocOplockQEntry(netfile->pInode,
471 cFYI(1,("about to wake up oplock thd"));
473 wake_up_process(oplockThread);
477 read_unlock(&GlobalSMBSeslock);
478 cFYI(1,("No matching file for oplock break"));
482 read_unlock(&GlobalSMBSeslock);
483 cFYI(1,("Can not process oplock break for non-existent connection"));
488 dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
492 unsigned char *buffer;
497 buffer = (unsigned char *) smb_buf;
498 for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
499 if (i % 8 == 0) { /* have reached the beginning of line */
500 printk(KERN_DEBUG "| ");
503 printk("%0#4x ", buffer[i]);
504 debug_line[2 * j] = ' ';
505 if (isprint(buffer[i]))
506 debug_line[1 + (2 * j)] = buffer[i];
508 debug_line[1 + (2 * j)] = '_';
510 if (i % 8 == 7) { /* reached end of line, time to print ascii */
512 printk(" | %s\n", debug_line);
517 debug_line[2 * j] = ' ';
518 debug_line[1 + (2 * j)] = ' ';
520 printk( " | %s\n", debug_line);
524 /* Windows maps these to the user defined 16 bit Unicode range since they are
525 reserved symbols (along with \ and /), otherwise illegal to store
526 in filenames in NTFS */
527 #define UNI_ASTERIK (__u16) ('*' + 0xF000)
528 #define UNI_QUESTION (__u16) ('?' + 0xF000)
529 #define UNI_COLON (__u16) (':' + 0xF000)
530 #define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
531 #define UNI_LESSTHAN (__u16) ('<' + 0xF000)
532 #define UNI_PIPE (__u16) ('|' + 0xF000)
533 #define UNI_SLASH (__u16) ('\\' + 0xF000)
535 /* Convert 16 bit Unicode pathname from wire format to string in current code
536 page. Conversion may involve remapping up the seven characters that are
537 only legal in POSIX-like OS (if they are present in the string). Path
538 names are little endian 16 bit Unicode on the wire */
540 cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
541 const struct nls_table * cp)
546 for(i = 0, j = 0; i < maxlen; i++) {
547 src_char = le16_to_cpu(source[i]);
550 goto cUCS_out; /* BB check this BB */
560 /* BB We can not handle remapping slash until
561 all the calls to build_path_from_dentry
562 are modified, as they use slash as separator BB */
576 len = cp->uni2char(src_char, &target[j],
577 NLS_MAX_CHARSET_SIZE);
586 /* make sure we do not overrun callers allocated temp buffer */
587 if(j >= (2 * NAME_MAX))
595 /* Convert 16 bit Unicode pathname to wire format from string in current code
596 page. Conversion may involve remapping up the seven characters that are
597 only legal in POSIX-like OS (if they are present in the string). Path
598 names are little endian 16 bit Unicode on the wire */
600 cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
601 const struct nls_table * cp, int mapChars)
604 int len_remaining = maxlen;
608 return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
610 for(i = 0, j = 0; i < maxlen; j++) {
611 src_char = source[i];
617 target[j] = cpu_to_le16(UNI_COLON);
620 target[j] = cpu_to_le16(UNI_ASTERIK);
623 target[j] = cpu_to_le16(UNI_QUESTION);
626 target[j] = cpu_to_le16(UNI_LESSTHAN);
629 target[j] = cpu_to_le16(UNI_GRTRTHAN);
632 target[j] = cpu_to_le16(UNI_PIPE);
634 /* BB We can not handle remapping slash until
635 all the calls to build_path_from_dentry
636 are modified, as they use slash as separator BB */
638 target[j] = cpu_to_le16(UNI_SLASH);
641 charlen = cp->char2uni(source+i,
642 len_remaining, target+j);
643 /* if no match, use question mark, which
644 at least in some cases servers as wild card */
646 target[j] = cpu_to_le16(0x003f);
649 len_remaining -= charlen;
650 /* character may take more than one byte in the
651 the source string, but will take exactly two
652 bytes in the target string */
656 i++; /* move to next char in source string */