• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   fs/cifs/misc.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2008
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 #include "cifs_unicode.h"
32 
33 extern mempool_t *cifs_sm_req_poolp;
34 extern mempool_t *cifs_req_poolp;
35 extern struct task_struct *oplockThread;
36 
37 /* The xid serves as a useful identifier for each incoming vfs request,
38    in a similar way to the mid which is useful to track each sent smb,
39    and CurrentXid can also provide a running counter (although it
40    will eventually wrap past zero) of the total vfs operations handled
41    since the cifs fs was mounted */
42 
43 unsigned int
_GetXid(void)44 _GetXid(void)
45 {
46 	unsigned int xid;
47 
48 	spin_lock(&GlobalMid_Lock);
49 	GlobalTotalActiveXid++;
50 
51 	/* keep high water mark for number of simultaneous ops in filesystem */
52 	if (GlobalTotalActiveXid > GlobalMaxActiveXid)
53 		GlobalMaxActiveXid = GlobalTotalActiveXid;
54 	if (GlobalTotalActiveXid > 65000)
55 		cFYI(1, ("warning: more than 65000 requests active"));
56 	xid = GlobalCurrentXid++;
57 	spin_unlock(&GlobalMid_Lock);
58 	return xid;
59 }
60 
61 void
_FreeXid(unsigned int xid)62 _FreeXid(unsigned int xid)
63 {
64 	spin_lock(&GlobalMid_Lock);
65 	/* if (GlobalTotalActiveXid == 0)
66 		BUG(); */
67 	GlobalTotalActiveXid--;
68 	spin_unlock(&GlobalMid_Lock);
69 }
70 
71 struct cifsSesInfo *
sesInfoAlloc(void)72 sesInfoAlloc(void)
73 {
74 	struct cifsSesInfo *ret_buf;
75 
76 	ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL);
77 	if (ret_buf) {
78 		atomic_inc(&sesInfoAllocCount);
79 		ret_buf->status = CifsNew;
80 		++ret_buf->ses_count;
81 		INIT_LIST_HEAD(&ret_buf->smb_ses_list);
82 		INIT_LIST_HEAD(&ret_buf->tcon_list);
83 		init_MUTEX(&ret_buf->sesSem);
84 	}
85 	return ret_buf;
86 }
87 
88 void
sesInfoFree(struct cifsSesInfo * buf_to_free)89 sesInfoFree(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 	atomic_dec(&sesInfoAllocCount);
97 	kfree(buf_to_free->serverOS);
98 	kfree(buf_to_free->serverDomain);
99 	kfree(buf_to_free->serverNOS);
100 	if (buf_to_free->password) {
101 		memset(buf_to_free->password, 0, strlen(buf_to_free->password));
102 		kfree(buf_to_free->password);
103 	}
104 	kfree(buf_to_free->domainName);
105 	kfree(buf_to_free);
106 }
107 
108 struct cifsTconInfo *
tconInfoAlloc(void)109 tconInfoAlloc(void)
110 {
111 	struct cifsTconInfo *ret_buf;
112 	ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
113 	if (ret_buf) {
114 		atomic_inc(&tconInfoAllocCount);
115 		ret_buf->tidStatus = CifsNew;
116 		++ret_buf->tc_count;
117 		INIT_LIST_HEAD(&ret_buf->openFileList);
118 		INIT_LIST_HEAD(&ret_buf->tcon_list);
119 #ifdef CONFIG_CIFS_STATS
120 		spin_lock_init(&ret_buf->stat_lock);
121 #endif
122 	}
123 	return ret_buf;
124 }
125 
126 void
tconInfoFree(struct cifsTconInfo * buf_to_free)127 tconInfoFree(struct cifsTconInfo *buf_to_free)
128 {
129 	if (buf_to_free == NULL) {
130 		cFYI(1, ("Null buffer passed to tconInfoFree"));
131 		return;
132 	}
133 	atomic_dec(&tconInfoAllocCount);
134 	kfree(buf_to_free->nativeFileSystem);
135 	if (buf_to_free->password) {
136 		memset(buf_to_free->password, 0, strlen(buf_to_free->password));
137 		kfree(buf_to_free->password);
138 	}
139 	kfree(buf_to_free);
140 }
141 
142 struct smb_hdr *
cifs_buf_get(void)143 cifs_buf_get(void)
144 {
145 	struct smb_hdr *ret_buf = NULL;
146 
147 /* We could use negotiated size instead of max_msgsize -
148    but it may be more efficient to always alloc same size
149    albeit slightly larger than necessary and maxbuffersize
150    defaults to this and can not be bigger */
151 	ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS);
152 
153 	/* clear the first few header bytes */
154 	/* for most paths, more is cleared in header_assemble */
155 	if (ret_buf) {
156 		memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
157 		atomic_inc(&bufAllocCount);
158 #ifdef CONFIG_CIFS_STATS2
159 		atomic_inc(&totBufAllocCount);
160 #endif /* CONFIG_CIFS_STATS2 */
161 	}
162 
163 	return ret_buf;
164 }
165 
166 void
cifs_buf_release(void * buf_to_free)167 cifs_buf_release(void *buf_to_free)
168 {
169 	if (buf_to_free == NULL) {
170 		/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
171 		return;
172 	}
173 	mempool_free(buf_to_free, cifs_req_poolp);
174 
175 	atomic_dec(&bufAllocCount);
176 	return;
177 }
178 
179 struct smb_hdr *
cifs_small_buf_get(void)180 cifs_small_buf_get(void)
181 {
182 	struct smb_hdr *ret_buf = NULL;
183 
184 /* We could use negotiated size instead of max_msgsize -
185    but it may be more efficient to always alloc same size
186    albeit slightly larger than necessary and maxbuffersize
187    defaults to this and can not be bigger */
188 	ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS);
189 	if (ret_buf) {
190 	/* No need to clear memory here, cleared in header assemble */
191 	/*	memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
192 		atomic_inc(&smBufAllocCount);
193 #ifdef CONFIG_CIFS_STATS2
194 		atomic_inc(&totSmBufAllocCount);
195 #endif /* CONFIG_CIFS_STATS2 */
196 
197 	}
198 	return ret_buf;
199 }
200 
201 void
cifs_small_buf_release(void * buf_to_free)202 cifs_small_buf_release(void *buf_to_free)
203 {
204 
205 	if (buf_to_free == NULL) {
206 		cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
207 		return;
208 	}
209 	mempool_free(buf_to_free, cifs_sm_req_poolp);
210 
211 	atomic_dec(&smBufAllocCount);
212 	return;
213 }
214 
215 /*
216 	Find a free multiplex id (SMB mid). Otherwise there could be
217 	mid collisions which might cause problems, demultiplexing the
218 	wrong response to this request. Multiplex ids could collide if
219 	one of a series requests takes much longer than the others, or
220 	if a very large number of long lived requests (byte range
221 	locks or FindNotify requests) are pending.  No more than
222 	64K-1 requests can be outstanding at one time.  If no
223 	mids are available, return zero.  A future optimization
224 	could make the combination of mids and uid the key we use
225 	to demultiplex on (rather than mid alone).
226 	In addition to the above check, the cifs demultiplex
227 	code already used the command code as a secondary
228 	check of the frame and if signing is negotiated the
229 	response would be discarded if the mid were the same
230 	but the signature was wrong.  Since the mid is not put in the
231 	pending queue until later (when it is about to be dispatched)
232 	we do have to limit the number of outstanding requests
233 	to somewhat less than 64K-1 although it is hard to imagine
234 	so many threads being in the vfs at one time.
235 */
GetNextMid(struct TCP_Server_Info * server)236 __u16 GetNextMid(struct TCP_Server_Info *server)
237 {
238 	__u16 mid = 0;
239 	__u16 last_mid;
240 	int   collision;
241 
242 	if (server == NULL)
243 		return mid;
244 
245 	spin_lock(&GlobalMid_Lock);
246 	last_mid = server->CurrentMid; /* we do not want to loop forever */
247 	server->CurrentMid++;
248 	/* This nested loop looks more expensive than it is.
249 	In practice the list of pending requests is short,
250 	fewer than 50, and the mids are likely to be unique
251 	on the first pass through the loop unless some request
252 	takes longer than the 64 thousand requests before it
253 	(and it would also have to have been a request that
254 	 did not time out) */
255 	while (server->CurrentMid != last_mid) {
256 		struct list_head *tmp;
257 		struct mid_q_entry *mid_entry;
258 
259 		collision = 0;
260 		if (server->CurrentMid == 0)
261 			server->CurrentMid++;
262 
263 		list_for_each(tmp, &server->pending_mid_q) {
264 			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
265 
266 			if ((mid_entry->mid == server->CurrentMid) &&
267 			    (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
268 				/* This mid is in use, try a different one */
269 				collision = 1;
270 				break;
271 			}
272 		}
273 		if (collision == 0) {
274 			mid = server->CurrentMid;
275 			break;
276 		}
277 		server->CurrentMid++;
278 	}
279 	spin_unlock(&GlobalMid_Lock);
280 	return mid;
281 }
282 
283 /* NB: MID can not be set if treeCon not passed in, in that
284    case it is responsbility of caller to set the mid */
285 void
header_assemble(struct smb_hdr * buffer,char smb_command,const struct cifsTconInfo * treeCon,int word_count)286 header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
287 		const struct cifsTconInfo *treeCon, int word_count
288 		/* length of fixed section (word count) in two byte units  */)
289 {
290 	struct list_head *temp_item;
291 	struct cifsSesInfo *ses;
292 	char *temp = (char *) buffer;
293 
294 	memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
295 
296 	buffer->smb_buf_length =
297 	    (2 * word_count) + sizeof(struct smb_hdr) -
298 	    4 /*  RFC 1001 length field does not count */  +
299 	    2 /* for bcc field itself */ ;
300 	/* Note that this is the only network field that has to be converted
301 	   to big endian and it is done just before we send it */
302 
303 	buffer->Protocol[0] = 0xFF;
304 	buffer->Protocol[1] = 'S';
305 	buffer->Protocol[2] = 'M';
306 	buffer->Protocol[3] = 'B';
307 	buffer->Command = smb_command;
308 	buffer->Flags = 0x00;	/* case sensitive */
309 	buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
310 	buffer->Pid = cpu_to_le16((__u16)current->tgid);
311 	buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
312 	if (treeCon) {
313 		buffer->Tid = treeCon->tid;
314 		if (treeCon->ses) {
315 			if (treeCon->ses->capabilities & CAP_UNICODE)
316 				buffer->Flags2 |= SMBFLG2_UNICODE;
317 			if (treeCon->ses->capabilities & CAP_STATUS32)
318 				buffer->Flags2 |= SMBFLG2_ERR_STATUS;
319 
320 			/* Uid is not converted */
321 			buffer->Uid = treeCon->ses->Suid;
322 			buffer->Mid = GetNextMid(treeCon->ses->server);
323 			if (multiuser_mount != 0) {
324 		/* For the multiuser case, there are few obvious technically  */
325 		/* possible mechanisms to match the local linux user (uid)    */
326 		/* to a valid remote smb user (smb_uid):		      */
327 		/* 	1) Query Winbind (or other local pam/nss daemon       */
328 		/* 	  for userid/password/logon_domain or credential      */
329 		/*      2) Query Winbind for uid to sid to username mapping   */
330 		/* 	   and see if we have a matching password for existing*/
331 		/*         session for that user perhas getting password by   */
332 		/*         adding a new pam_cifs module that stores passwords */
333 		/*         so that the cifs vfs can get at that for all logged*/
334 		/*	   on users					      */
335 		/*	3) (Which is the mechanism we have chosen)	      */
336 		/*	   Search through sessions to the same server for a   */
337 		/*	   a match on the uid that was passed in on mount     */
338 		/*         with the current processes uid (or euid?) and use  */
339 		/* 	   that smb uid.   If no existing smb session for     */
340 		/* 	   that uid found, use the default smb session ie     */
341 		/*         the smb session for the volume mounted which is    */
342 		/* 	   the same as would be used if the multiuser mount   */
343 		/* 	   flag were disabled.  */
344 
345 		/*  BB Add support for establishing new tCon and SMB Session  */
346 		/*      with userid/password pairs found on the smb session   */
347 		/*	for other target tcp/ip addresses 		BB    */
348 				if (current_fsuid() != treeCon->ses->linux_uid) {
349 					cFYI(1, ("Multiuser mode and UID "
350 						 "did not match tcon uid"));
351 					read_lock(&cifs_tcp_ses_lock);
352 					list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
353 						ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
354 						if (ses->linux_uid == current_fsuid()) {
355 							if (ses->server == treeCon->ses->server) {
356 								cFYI(1, ("found matching uid substitute right smb_uid"));
357 								buffer->Uid = ses->Suid;
358 								break;
359 							} else {
360 				/* BB eventually call cifs_setup_session here */
361 								cFYI(1, ("local UID found but no smb sess with this server exists"));
362 							}
363 						}
364 					}
365 					read_unlock(&cifs_tcp_ses_lock);
366 				}
367 			}
368 		}
369 		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
370 			buffer->Flags2 |= SMBFLG2_DFS;
371 		if (treeCon->nocase)
372 			buffer->Flags  |= SMBFLG_CASELESS;
373 		if ((treeCon->ses) && (treeCon->ses->server))
374 			if (treeCon->ses->server->secMode &
375 			  (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
376 				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
377 	}
378 
379 /*  endian conversion of flags is now done just before sending */
380 	buffer->WordCount = (char) word_count;
381 	return;
382 }
383 
384 static int
checkSMBhdr(struct smb_hdr * smb,__u16 mid)385 checkSMBhdr(struct smb_hdr *smb, __u16 mid)
386 {
387 	/* Make sure that this really is an SMB, that it is a response,
388 	   and that the message ids match */
389 	if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) &&
390 		(mid == smb->Mid)) {
391 		if (smb->Flags & SMBFLG_RESPONSE)
392 			return 0;
393 		else {
394 		/* only one valid case where server sends us request */
395 			if (smb->Command == SMB_COM_LOCKING_ANDX)
396 				return 0;
397 			else
398 				cERROR(1, ("Received Request not response"));
399 		}
400 	} else { /* bad signature or mid */
401 		if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
402 			cERROR(1,
403 			       ("Bad protocol string signature header %x",
404 				*(unsigned int *) smb->Protocol));
405 		if (mid != smb->Mid)
406 			cERROR(1, ("Mids do not match"));
407 	}
408 	cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
409 	return 1;
410 }
411 
412 int
checkSMB(struct smb_hdr * smb,__u16 mid,unsigned int length)413 checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
414 {
415 	__u32 len = smb->smb_buf_length;
416 	__u32 clc_len;  /* calculated length */
417 	cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
418 
419 	if (length < 2 + sizeof(struct smb_hdr)) {
420 		if ((length >= sizeof(struct smb_hdr) - 1)
421 			    && (smb->Status.CifsError != 0)) {
422 			smb->WordCount = 0;
423 			/* some error cases do not return wct and bcc */
424 			return 0;
425 		} else if ((length == sizeof(struct smb_hdr) + 1) &&
426 				(smb->WordCount == 0)) {
427 			char *tmp = (char *)smb;
428 			/* Need to work around a bug in two servers here */
429 			/* First, check if the part of bcc they sent was zero */
430 			if (tmp[sizeof(struct smb_hdr)] == 0) {
431 				/* some servers return only half of bcc
432 				 * on simple responses (wct, bcc both zero)
433 				 * in particular have seen this on
434 				 * ulogoffX and FindClose. This leaves
435 				 * one byte of bcc potentially unitialized
436 				 */
437 				/* zero rest of bcc */
438 				tmp[sizeof(struct smb_hdr)+1] = 0;
439 				return 0;
440 			}
441 			cERROR(1, ("rcvd invalid byte count (bcc)"));
442 		} else {
443 			cERROR(1, ("Length less than smb header size"));
444 		}
445 		return 1;
446 	}
447 	if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
448 		cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
449 				   smb->Mid));
450 		return 1;
451 	}
452 
453 	if (checkSMBhdr(smb, mid))
454 		return 1;
455 	clc_len = smbCalcSize_LE(smb);
456 
457 	if (4 + len != length) {
458 		cERROR(1, ("Length read does not match RFC1001 length %d",
459 			   len));
460 		return 1;
461 	}
462 
463 	if (4 + len != clc_len) {
464 		/* check if bcc wrapped around for large read responses */
465 		if ((len > 64 * 1024) && (len > clc_len)) {
466 			/* check if lengths match mod 64K */
467 			if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
468 				return 0; /* bcc wrapped */
469 		}
470 		cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
471 				clc_len, 4 + len, smb->Mid));
472 		/* Windows XP can return a few bytes too much, presumably
473 		an illegal pad, at the end of byte range lock responses
474 		so we allow for that three byte pad, as long as actual
475 		received length is as long or longer than calculated length */
476 		/* We have now had to extend this more, since there is a
477 		case in which it needs to be bigger still to handle a
478 		malformed response to transact2 findfirst from WinXP when
479 		access denied is returned and thus bcc and wct are zero
480 		but server says length is 0x21 bytes too long as if the server
481 		forget to reset the smb rfc1001 length when it reset the
482 		wct and bcc to minimum size and drop the t2 parms and data */
483 		if ((4+len > clc_len) && (len <= clc_len + 512))
484 			return 0;
485 		else {
486 			cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
487 					len, smb->Mid));
488 			return 1;
489 		}
490 	}
491 	return 0;
492 }
493 
494 bool
is_valid_oplock_break(struct smb_hdr * buf,struct TCP_Server_Info * srv)495 is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
496 {
497 	struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
498 	struct list_head *tmp, *tmp1, *tmp2;
499 	struct cifsSesInfo *ses;
500 	struct cifsTconInfo *tcon;
501 	struct cifsInodeInfo *pCifsInode;
502 	struct cifsFileInfo *netfile;
503 
504 	cFYI(1, ("Checking for oplock break or dnotify response"));
505 	if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
506 	   (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
507 		struct smb_com_transaction_change_notify_rsp *pSMBr =
508 			(struct smb_com_transaction_change_notify_rsp *)buf;
509 		struct file_notify_information *pnotify;
510 		__u32 data_offset = 0;
511 		if (pSMBr->ByteCount > sizeof(struct file_notify_information)) {
512 			data_offset = le32_to_cpu(pSMBr->DataOffset);
513 
514 			pnotify = (struct file_notify_information *)
515 				((char *)&pSMBr->hdr.Protocol + data_offset);
516 			cFYI(1, ("dnotify on %s Action: 0x%x",
517 				 pnotify->FileName, pnotify->Action));
518 			/*   cifs_dump_mem("Rcvd notify Data: ",buf,
519 				sizeof(struct smb_hdr)+60); */
520 			return true;
521 		}
522 		if (pSMBr->hdr.Status.CifsError) {
523 			cFYI(1, ("notify err 0x%d",
524 				pSMBr->hdr.Status.CifsError));
525 			return true;
526 		}
527 		return false;
528 	}
529 	if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
530 		return false;
531 	if (pSMB->hdr.Flags & SMBFLG_RESPONSE) {
532 		/* no sense logging error on invalid handle on oplock
533 		   break - harmless race between close request and oplock
534 		   break response is expected from time to time writing out
535 		   large dirty files cached on the client */
536 		if ((NT_STATUS_INVALID_HANDLE) ==
537 		   le32_to_cpu(pSMB->hdr.Status.CifsError)) {
538 			cFYI(1, ("invalid handle on oplock break"));
539 			return true;
540 		} else if (ERRbadfid ==
541 		   le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
542 			return true;
543 		} else {
544 			return false; /* on valid oplock brk we get "request" */
545 		}
546 	}
547 	if (pSMB->hdr.WordCount != 8)
548 		return false;
549 
550 	cFYI(1, ("oplock type 0x%d level 0x%d",
551 		 pSMB->LockType, pSMB->OplockLevel));
552 	if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
553 		return false;
554 
555 	/* look up tcon based on tid & uid */
556 	read_lock(&cifs_tcp_ses_lock);
557 	list_for_each(tmp, &srv->smb_ses_list) {
558 		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
559 		list_for_each(tmp1, &ses->tcon_list) {
560 			tcon = list_entry(tmp1, struct cifsTconInfo, tcon_list);
561 			if (tcon->tid != buf->Tid)
562 				continue;
563 
564 			cifs_stats_inc(&tcon->num_oplock_brks);
565 			write_lock(&GlobalSMBSeslock);
566 			list_for_each(tmp2, &tcon->openFileList) {
567 				netfile = list_entry(tmp2, struct cifsFileInfo,
568 						     tlist);
569 				if (pSMB->Fid != netfile->netfid)
570 					continue;
571 
572 				write_unlock(&GlobalSMBSeslock);
573 				read_unlock(&cifs_tcp_ses_lock);
574 				cFYI(1, ("file id match, oplock break"));
575 				pCifsInode = CIFS_I(netfile->pInode);
576 				pCifsInode->clientCanCacheAll = false;
577 				if (pSMB->OplockLevel == 0)
578 					pCifsInode->clientCanCacheRead = false;
579 				pCifsInode->oplockPending = true;
580 				AllocOplockQEntry(netfile->pInode,
581 						  netfile->netfid, tcon);
582 				cFYI(1, ("about to wake up oplock thread"));
583 				if (oplockThread)
584 					wake_up_process(oplockThread);
585 
586 				return true;
587 			}
588 			write_unlock(&GlobalSMBSeslock);
589 			read_unlock(&cifs_tcp_ses_lock);
590 			cFYI(1, ("No matching file for oplock break"));
591 			return true;
592 		}
593 	}
594 	read_unlock(&cifs_tcp_ses_lock);
595 	cFYI(1, ("Can not process oplock break for non-existent connection"));
596 	return true;
597 }
598 
599 void
dump_smb(struct smb_hdr * smb_buf,int smb_buf_length)600 dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
601 {
602 	int i, j;
603 	char debug_line[17];
604 	unsigned char *buffer;
605 
606 	if (traceSMB == 0)
607 		return;
608 
609 	buffer = (unsigned char *) smb_buf;
610 	for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
611 		if (i % 8 == 0) {
612 			/* have reached the beginning of line */
613 			printk(KERN_DEBUG "| ");
614 			j = 0;
615 		}
616 		printk("%0#4x ", buffer[i]);
617 		debug_line[2 * j] = ' ';
618 		if (isprint(buffer[i]))
619 			debug_line[1 + (2 * j)] = buffer[i];
620 		else
621 			debug_line[1 + (2 * j)] = '_';
622 
623 		if (i % 8 == 7) {
624 			/* reached end of line, time to print ascii */
625 			debug_line[16] = 0;
626 			printk(" | %s\n", debug_line);
627 		}
628 	}
629 	for (; j < 8; j++) {
630 		printk("     ");
631 		debug_line[2 * j] = ' ';
632 		debug_line[1 + (2 * j)] = ' ';
633 	}
634 	printk(" | %s\n", debug_line);
635 	return;
636 }
637 
638 /* Windows maps these to the user defined 16 bit Unicode range since they are
639    reserved symbols (along with \ and /), otherwise illegal to store
640    in filenames in NTFS */
641 #define UNI_ASTERIK     (__u16) ('*' + 0xF000)
642 #define UNI_QUESTION    (__u16) ('?' + 0xF000)
643 #define UNI_COLON       (__u16) (':' + 0xF000)
644 #define UNI_GRTRTHAN    (__u16) ('>' + 0xF000)
645 #define UNI_LESSTHAN    (__u16) ('<' + 0xF000)
646 #define UNI_PIPE        (__u16) ('|' + 0xF000)
647 #define UNI_SLASH       (__u16) ('\\' + 0xF000)
648 
649 /* Convert 16 bit Unicode pathname from wire format to string in current code
650    page.  Conversion may involve remapping up the seven characters that are
651    only legal in POSIX-like OS (if they are present in the string). Path
652    names are little endian 16 bit Unicode on the wire */
653 int
cifs_convertUCSpath(char * target,const __le16 * source,int maxlen,const struct nls_table * cp)654 cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
655 		    const struct nls_table *cp)
656 {
657 	int i, j, len;
658 	__u16 src_char;
659 
660 	for (i = 0, j = 0; i < maxlen; i++) {
661 		src_char = le16_to_cpu(source[i]);
662 		switch (src_char) {
663 			case 0:
664 				goto cUCS_out; /* BB check this BB */
665 			case UNI_COLON:
666 				target[j] = ':';
667 				break;
668 			case UNI_ASTERIK:
669 				target[j] = '*';
670 				break;
671 			case UNI_QUESTION:
672 				target[j] = '?';
673 				break;
674 			/* BB We can not handle remapping slash until
675 			   all the calls to build_path_from_dentry
676 			   are modified, as they use slash as separator BB */
677 			/* case UNI_SLASH:
678 				target[j] = '\\';
679 				break;*/
680 			case UNI_PIPE:
681 				target[j] = '|';
682 				break;
683 			case UNI_GRTRTHAN:
684 				target[j] = '>';
685 				break;
686 			case UNI_LESSTHAN:
687 				target[j] = '<';
688 				break;
689 			default:
690 				len = cp->uni2char(src_char, &target[j],
691 						NLS_MAX_CHARSET_SIZE);
692 				if (len > 0) {
693 					j += len;
694 					continue;
695 				} else {
696 					target[j] = '?';
697 				}
698 		}
699 		j++;
700 		/* make sure we do not overrun callers allocated temp buffer */
701 		if (j >= (2 * NAME_MAX))
702 			break;
703 	}
704 cUCS_out:
705 	target[j] = 0;
706 	return j;
707 }
708 
709 /* Convert 16 bit Unicode pathname to wire format from string in current code
710    page.  Conversion may involve remapping up the seven characters that are
711    only legal in POSIX-like OS (if they are present in the string). Path
712    names are little endian 16 bit Unicode on the wire */
713 int
cifsConvertToUCS(__le16 * target,const char * source,int maxlen,const struct nls_table * cp,int mapChars)714 cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
715 		 const struct nls_table *cp, int mapChars)
716 {
717 	int i, j, charlen;
718 	int len_remaining = maxlen;
719 	char src_char;
720 	__u16 temp;
721 
722 	if (!mapChars)
723 		return cifs_strtoUCS(target, source, PATH_MAX, cp);
724 
725 	for (i = 0, j = 0; i < maxlen; j++) {
726 		src_char = source[i];
727 		switch (src_char) {
728 			case 0:
729 				target[j] = 0;
730 				goto ctoUCS_out;
731 			case ':':
732 				target[j] = cpu_to_le16(UNI_COLON);
733 				break;
734 			case '*':
735 				target[j] = cpu_to_le16(UNI_ASTERIK);
736 				break;
737 			case '?':
738 				target[j] = cpu_to_le16(UNI_QUESTION);
739 				break;
740 			case '<':
741 				target[j] = cpu_to_le16(UNI_LESSTHAN);
742 				break;
743 			case '>':
744 				target[j] = cpu_to_le16(UNI_GRTRTHAN);
745 				break;
746 			case '|':
747 				target[j] = cpu_to_le16(UNI_PIPE);
748 				break;
749 			/* BB We can not handle remapping slash until
750 			   all the calls to build_path_from_dentry
751 			   are modified, as they use slash as separator BB */
752 			/* case '\\':
753 				target[j] = cpu_to_le16(UNI_SLASH);
754 				break;*/
755 			default:
756 				charlen = cp->char2uni(source+i,
757 					len_remaining, &temp);
758 				/* if no match, use question mark, which
759 				at least in some cases servers as wild card */
760 				if (charlen < 1) {
761 					target[j] = cpu_to_le16(0x003f);
762 					charlen = 1;
763 				} else
764 					target[j] = cpu_to_le16(temp);
765 				len_remaining -= charlen;
766 				/* character may take more than one byte in the
767 				   the source string, but will take exactly two
768 				   bytes in the target string */
769 				i += charlen;
770 				continue;
771 		}
772 		i++; /* move to next char in source string */
773 		len_remaining--;
774 	}
775 
776 ctoUCS_out:
777 	return i;
778 }
779