• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2010
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 differently for reconnection purposes since we never     */
28  /* want to reuse a stale file handle and only the caller knows the file info */
29 
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/slab.h>
34 #include <linux/posix_acl_xattr.h>
35 #include <linux/pagemap.h>
36 #include <linux/swap.h>
37 #include <linux/task_io_accounting_ops.h>
38 #include <asm/uaccess.h>
39 #include "cifspdu.h"
40 #include "cifsglob.h"
41 #include "cifsacl.h"
42 #include "cifsproto.h"
43 #include "cifs_unicode.h"
44 #include "cifs_debug.h"
45 #include "fscache.h"
46 
47 #ifdef CONFIG_CIFS_POSIX
48 static struct {
49 	int index;
50 	char *name;
51 } protocols[] = {
52 #ifdef CONFIG_CIFS_WEAK_PW_HASH
53 	{LANMAN_PROT, "\2LM1.2X002"},
54 	{LANMAN2_PROT, "\2LANMAN2.1"},
55 #endif /* weak password hashing for legacy clients */
56 	{CIFS_PROT, "\2NT LM 0.12"},
57 	{POSIX_PROT, "\2POSIX 2"},
58 	{BAD_PROT, "\2"}
59 };
60 #else
61 static struct {
62 	int index;
63 	char *name;
64 } protocols[] = {
65 #ifdef CONFIG_CIFS_WEAK_PW_HASH
66 	{LANMAN_PROT, "\2LM1.2X002"},
67 	{LANMAN2_PROT, "\2LANMAN2.1"},
68 #endif /* weak password hashing for legacy clients */
69 	{CIFS_PROT, "\2NT LM 0.12"},
70 	{BAD_PROT, "\2"}
71 };
72 #endif
73 
74 /* define the number of elements in the cifs dialect array */
75 #ifdef CONFIG_CIFS_POSIX
76 #ifdef CONFIG_CIFS_WEAK_PW_HASH
77 #define CIFS_NUM_PROT 4
78 #else
79 #define CIFS_NUM_PROT 2
80 #endif /* CIFS_WEAK_PW_HASH */
81 #else /* not posix */
82 #ifdef CONFIG_CIFS_WEAK_PW_HASH
83 #define CIFS_NUM_PROT 3
84 #else
85 #define CIFS_NUM_PROT 1
86 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
87 #endif /* CIFS_POSIX */
88 
89 /* Forward declarations */
90 static void cifs_readv_complete(struct work_struct *work);
91 
92 #ifdef CONFIG_HIGHMEM
93 /*
94  * On arches that have high memory, kmap address space is limited. By
95  * serializing the kmap operations on those arches, we ensure that we don't
96  * end up with a bunch of threads in writeback with partially mapped page
97  * arrays, stuck waiting for kmap to come back. That situation prevents
98  * progress and can deadlock.
99  */
100 static DEFINE_MUTEX(cifs_kmap_mutex);
101 
102 static inline void
cifs_kmap_lock(void)103 cifs_kmap_lock(void)
104 {
105 	mutex_lock(&cifs_kmap_mutex);
106 }
107 
108 static inline void
cifs_kmap_unlock(void)109 cifs_kmap_unlock(void)
110 {
111 	mutex_unlock(&cifs_kmap_mutex);
112 }
113 #else /* !CONFIG_HIGHMEM */
114 #define cifs_kmap_lock() do { ; } while(0)
115 #define cifs_kmap_unlock() do { ; } while(0)
116 #endif /* CONFIG_HIGHMEM */
117 
118 /* Mark as invalid, all open files on tree connections since they
119    were closed when session to server was lost */
mark_open_files_invalid(struct cifs_tcon * pTcon)120 static void mark_open_files_invalid(struct cifs_tcon *pTcon)
121 {
122 	struct cifsFileInfo *open_file = NULL;
123 	struct list_head *tmp;
124 	struct list_head *tmp1;
125 
126 /* list all files open on tree connection and mark them invalid */
127 	spin_lock(&cifs_file_list_lock);
128 	list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
129 		open_file = list_entry(tmp, struct cifsFileInfo, tlist);
130 		open_file->invalidHandle = true;
131 		open_file->oplock_break_cancelled = true;
132 	}
133 	spin_unlock(&cifs_file_list_lock);
134 	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted
135 	   to this tcon */
136 }
137 
138 /* reconnect the socket, tcon, and smb session if needed */
139 static int
cifs_reconnect_tcon(struct cifs_tcon * tcon,int smb_command)140 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
141 {
142 	int rc;
143 	struct cifs_ses *ses;
144 	struct TCP_Server_Info *server;
145 	struct nls_table *nls_codepage;
146 
147 	/*
148 	 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
149 	 * tcp and smb session status done differently for those three - in the
150 	 * calling routine
151 	 */
152 	if (!tcon)
153 		return 0;
154 
155 	ses = tcon->ses;
156 	server = ses->server;
157 
158 	/*
159 	 * only tree disconnect, open, and write, (and ulogoff which does not
160 	 * have tcon) are allowed as we start force umount
161 	 */
162 	if (tcon->tidStatus == CifsExiting) {
163 		if (smb_command != SMB_COM_WRITE_ANDX &&
164 		    smb_command != SMB_COM_OPEN_ANDX &&
165 		    smb_command != SMB_COM_TREE_DISCONNECT) {
166 			cFYI(1, "can not send cmd %d while umounting",
167 				smb_command);
168 			return -ENODEV;
169 		}
170 	}
171 
172 	/*
173 	 * Give demultiplex thread up to 10 seconds to reconnect, should be
174 	 * greater than cifs socket timeout which is 7 seconds
175 	 */
176 	while (server->tcpStatus == CifsNeedReconnect) {
177 		wait_event_interruptible_timeout(server->response_q,
178 			(server->tcpStatus != CifsNeedReconnect), 10 * HZ);
179 
180 		/* are we still trying to reconnect? */
181 		if (server->tcpStatus != CifsNeedReconnect)
182 			break;
183 
184 		/*
185 		 * on "soft" mounts we wait once. Hard mounts keep
186 		 * retrying until process is killed or server comes
187 		 * back on-line
188 		 */
189 		if (!tcon->retry) {
190 			cFYI(1, "gave up waiting on reconnect in smb_init");
191 			return -EHOSTDOWN;
192 		}
193 	}
194 
195 	if (!ses->need_reconnect && !tcon->need_reconnect)
196 		return 0;
197 
198 	nls_codepage = load_nls_default();
199 
200 	/*
201 	 * need to prevent multiple threads trying to simultaneously
202 	 * reconnect the same SMB session
203 	 */
204 	mutex_lock(&ses->session_mutex);
205 	rc = cifs_negotiate_protocol(0, ses);
206 	if (rc == 0 && ses->need_reconnect)
207 		rc = cifs_setup_session(0, ses, nls_codepage);
208 
209 	/* do we need to reconnect tcon? */
210 	if (rc || !tcon->need_reconnect) {
211 		mutex_unlock(&ses->session_mutex);
212 		goto out;
213 	}
214 
215 	mark_open_files_invalid(tcon);
216 	rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
217 	mutex_unlock(&ses->session_mutex);
218 	cFYI(1, "reconnect tcon rc = %d", rc);
219 
220 	if (rc)
221 		goto out;
222 
223 	/*
224 	 * FIXME: check if wsize needs updated due to negotiated smb buffer
225 	 * 	  size shrinking
226 	 */
227 	atomic_inc(&tconInfoReconnectCount);
228 
229 	/* tell server Unix caps we support */
230 	if (ses->capabilities & CAP_UNIX)
231 		reset_cifs_unix_caps(0, tcon, NULL, NULL);
232 
233 	/*
234 	 * Removed call to reopen open files here. It is safer (and faster) to
235 	 * reopen files one at a time as needed in read and write.
236 	 *
237 	 * FIXME: what about file locks? don't we need to reclaim them ASAP?
238 	 */
239 
240 out:
241 	/*
242 	 * Check if handle based operation so we know whether we can continue
243 	 * or not without returning to caller to reset file handle
244 	 */
245 	switch (smb_command) {
246 	case SMB_COM_READ_ANDX:
247 	case SMB_COM_WRITE_ANDX:
248 	case SMB_COM_CLOSE:
249 	case SMB_COM_FIND_CLOSE2:
250 	case SMB_COM_LOCKING_ANDX:
251 		rc = -EAGAIN;
252 	}
253 
254 	unload_nls(nls_codepage);
255 	return rc;
256 }
257 
258 /* Allocate and return pointer to an SMB request buffer, and set basic
259    SMB information in the SMB header.  If the return code is zero, this
260    function must have filled in request_buf pointer */
261 static int
small_smb_init(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf)262 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
263 		void **request_buf)
264 {
265 	int rc;
266 
267 	rc = cifs_reconnect_tcon(tcon, smb_command);
268 	if (rc)
269 		return rc;
270 
271 	*request_buf = cifs_small_buf_get();
272 	if (*request_buf == NULL) {
273 		/* BB should we add a retry in here if not a writepage? */
274 		return -ENOMEM;
275 	}
276 
277 	header_assemble((struct smb_hdr *) *request_buf, smb_command,
278 			tcon, wct);
279 
280 	if (tcon != NULL)
281 		cifs_stats_inc(&tcon->num_smbs_sent);
282 
283 	return 0;
284 }
285 
286 int
small_smb_init_no_tc(const int smb_command,const int wct,struct cifs_ses * ses,void ** request_buf)287 small_smb_init_no_tc(const int smb_command, const int wct,
288 		     struct cifs_ses *ses, void **request_buf)
289 {
290 	int rc;
291 	struct smb_hdr *buffer;
292 
293 	rc = small_smb_init(smb_command, wct, NULL, request_buf);
294 	if (rc)
295 		return rc;
296 
297 	buffer = (struct smb_hdr *)*request_buf;
298 	buffer->Mid = GetNextMid(ses->server);
299 	if (ses->capabilities & CAP_UNICODE)
300 		buffer->Flags2 |= SMBFLG2_UNICODE;
301 	if (ses->capabilities & CAP_STATUS32)
302 		buffer->Flags2 |= SMBFLG2_ERR_STATUS;
303 
304 	/* uid, tid can stay at zero as set in header assemble */
305 
306 	/* BB add support for turning on the signing when
307 	this function is used after 1st of session setup requests */
308 
309 	return rc;
310 }
311 
312 /* If the return code is zero, this function must fill in request_buf pointer */
313 static int
__smb_init(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf,void ** response_buf)314 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
315 			void **request_buf, void **response_buf)
316 {
317 	*request_buf = cifs_buf_get();
318 	if (*request_buf == NULL) {
319 		/* BB should we add a retry in here if not a writepage? */
320 		return -ENOMEM;
321 	}
322     /* Although the original thought was we needed the response buf for  */
323     /* potential retries of smb operations it turns out we can determine */
324     /* from the mid flags when the request buffer can be resent without  */
325     /* having to use a second distinct buffer for the response */
326 	if (response_buf)
327 		*response_buf = *request_buf;
328 
329 	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
330 			wct);
331 
332 	if (tcon != NULL)
333 		cifs_stats_inc(&tcon->num_smbs_sent);
334 
335 	return 0;
336 }
337 
338 /* If the return code is zero, this function must fill in request_buf pointer */
339 static int
smb_init(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf,void ** response_buf)340 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
341 	 void **request_buf, void **response_buf)
342 {
343 	int rc;
344 
345 	rc = cifs_reconnect_tcon(tcon, smb_command);
346 	if (rc)
347 		return rc;
348 
349 	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
350 }
351 
352 static int
smb_init_no_reconnect(int smb_command,int wct,struct cifs_tcon * tcon,void ** request_buf,void ** response_buf)353 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
354 			void **request_buf, void **response_buf)
355 {
356 	if (tcon->ses->need_reconnect || tcon->need_reconnect)
357 		return -EHOSTDOWN;
358 
359 	return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
360 }
361 
validate_t2(struct smb_t2_rsp * pSMB)362 static int validate_t2(struct smb_t2_rsp *pSMB)
363 {
364 	unsigned int total_size;
365 
366 	/* check for plausible wct */
367 	if (pSMB->hdr.WordCount < 10)
368 		goto vt2_err;
369 
370 	/* check for parm and data offset going beyond end of smb */
371 	if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
372 	    get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
373 		goto vt2_err;
374 
375 	total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
376 	if (total_size >= 512)
377 		goto vt2_err;
378 
379 	/* check that bcc is at least as big as parms + data, and that it is
380 	 * less than negotiated smb buffer
381 	 */
382 	total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
383 	if (total_size > get_bcc(&pSMB->hdr) ||
384 	    total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
385 		goto vt2_err;
386 
387 	return 0;
388 vt2_err:
389 	cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
390 		sizeof(struct smb_t2_rsp) + 16);
391 	return -EINVAL;
392 }
393 
inc_rfc1001_len(void * pSMB,int count)394 static inline void inc_rfc1001_len(void *pSMB, int count)
395 {
396 	struct smb_hdr *hdr = (struct smb_hdr *)pSMB;
397 
398 	be32_add_cpu(&hdr->smb_buf_length, count);
399 }
400 
401 int
CIFSSMBNegotiate(unsigned int xid,struct cifs_ses * ses)402 CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
403 {
404 	NEGOTIATE_REQ *pSMB;
405 	NEGOTIATE_RSP *pSMBr;
406 	int rc = 0;
407 	int bytes_returned;
408 	int i;
409 	struct TCP_Server_Info *server;
410 	u16 count;
411 	unsigned int secFlags;
412 
413 	if (ses->server)
414 		server = ses->server;
415 	else {
416 		rc = -EIO;
417 		return rc;
418 	}
419 	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
420 		      (void **) &pSMB, (void **) &pSMBr);
421 	if (rc)
422 		return rc;
423 
424 	/* if any of auth flags (ie not sign or seal) are overriden use them */
425 	if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
426 		secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
427 	else /* if override flags set only sign/seal OR them with global auth */
428 		secFlags = global_secflags | ses->overrideSecFlg;
429 
430 	cFYI(1, "secFlags 0x%x", secFlags);
431 
432 	pSMB->hdr.Mid = GetNextMid(server);
433 	pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
434 
435 	if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
436 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
437 	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
438 		cFYI(1, "Kerberos only mechanism, enable extended security");
439 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
440 	} else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
441 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
442 	else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
443 		cFYI(1, "NTLMSSP only mechanism, enable extended security");
444 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
445 	}
446 
447 	count = 0;
448 	for (i = 0; i < CIFS_NUM_PROT; i++) {
449 		strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
450 		count += strlen(protocols[i].name) + 1;
451 		/* null at end of source and target buffers anyway */
452 	}
453 	inc_rfc1001_len(pSMB, count);
454 	pSMB->ByteCount = cpu_to_le16(count);
455 
456 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
457 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
458 	if (rc != 0)
459 		goto neg_err_exit;
460 
461 	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
462 	cFYI(1, "Dialect: %d", server->dialect);
463 	/* Check wct = 1 error case */
464 	if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
465 		/* core returns wct = 1, but we do not ask for core - otherwise
466 		small wct just comes when dialect index is -1 indicating we
467 		could not negotiate a common dialect */
468 		rc = -EOPNOTSUPP;
469 		goto neg_err_exit;
470 #ifdef CONFIG_CIFS_WEAK_PW_HASH
471 	} else if ((pSMBr->hdr.WordCount == 13)
472 			&& ((server->dialect == LANMAN_PROT)
473 				|| (server->dialect == LANMAN2_PROT))) {
474 		__s16 tmp;
475 		struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
476 
477 		if ((secFlags & CIFSSEC_MAY_LANMAN) ||
478 			(secFlags & CIFSSEC_MAY_PLNTXT))
479 			server->secType = LANMAN;
480 		else {
481 			cERROR(1, "mount failed weak security disabled"
482 				   " in /proc/fs/cifs/SecurityFlags");
483 			rc = -EOPNOTSUPP;
484 			goto neg_err_exit;
485 		}
486 		server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
487 		server->maxReq = min_t(unsigned int,
488 				       le16_to_cpu(rsp->MaxMpxCount),
489 				       cifs_max_pending);
490 		cifs_set_credits(server, server->maxReq);
491 		server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
492 		server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
493 		/* even though we do not use raw we might as well set this
494 		accurately, in case we ever find a need for it */
495 		if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
496 			server->max_rw = 0xFF00;
497 			server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
498 		} else {
499 			server->max_rw = 0;/* do not need to use raw anyway */
500 			server->capabilities = CAP_MPX_MODE;
501 		}
502 		tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
503 		if (tmp == -1) {
504 			/* OS/2 often does not set timezone therefore
505 			 * we must use server time to calc time zone.
506 			 * Could deviate slightly from the right zone.
507 			 * Smallest defined timezone difference is 15 minutes
508 			 * (i.e. Nepal).  Rounding up/down is done to match
509 			 * this requirement.
510 			 */
511 			int val, seconds, remain, result;
512 			struct timespec ts, utc;
513 			utc = CURRENT_TIME;
514 			ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
515 					    rsp->SrvTime.Time, 0);
516 			cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
517 				(int)ts.tv_sec, (int)utc.tv_sec,
518 				(int)(utc.tv_sec - ts.tv_sec));
519 			val = (int)(utc.tv_sec - ts.tv_sec);
520 			seconds = abs(val);
521 			result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
522 			remain = seconds % MIN_TZ_ADJ;
523 			if (remain >= (MIN_TZ_ADJ / 2))
524 				result += MIN_TZ_ADJ;
525 			if (val < 0)
526 				result = -result;
527 			server->timeAdj = result;
528 		} else {
529 			server->timeAdj = (int)tmp;
530 			server->timeAdj *= 60; /* also in seconds */
531 		}
532 		cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
533 
534 
535 		/* BB get server time for time conversions and add
536 		code to use it and timezone since this is not UTC */
537 
538 		if (rsp->EncryptionKeyLength ==
539 				cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
540 			memcpy(ses->server->cryptkey, rsp->EncryptionKey,
541 				CIFS_CRYPTO_KEY_SIZE);
542 		} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
543 			rc = -EIO; /* need cryptkey unless plain text */
544 			goto neg_err_exit;
545 		}
546 
547 		cFYI(1, "LANMAN negotiated");
548 		/* we will not end up setting signing flags - as no signing
549 		was in LANMAN and server did not return the flags on */
550 		goto signing_check;
551 #else /* weak security disabled */
552 	} else if (pSMBr->hdr.WordCount == 13) {
553 		cERROR(1, "mount failed, cifs module not built "
554 			  "with CIFS_WEAK_PW_HASH support");
555 		rc = -EOPNOTSUPP;
556 #endif /* WEAK_PW_HASH */
557 		goto neg_err_exit;
558 	} else if (pSMBr->hdr.WordCount != 17) {
559 		/* unknown wct */
560 		rc = -EOPNOTSUPP;
561 		goto neg_err_exit;
562 	}
563 	/* else wct == 17 NTLM */
564 	server->sec_mode = pSMBr->SecurityMode;
565 	if ((server->sec_mode & SECMODE_USER) == 0)
566 		cFYI(1, "share mode security");
567 
568 	if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
569 #ifdef CONFIG_CIFS_WEAK_PW_HASH
570 		if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
571 #endif /* CIFS_WEAK_PW_HASH */
572 			cERROR(1, "Server requests plain text password"
573 				  " but client support disabled");
574 
575 	if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
576 		server->secType = NTLMv2;
577 	else if (secFlags & CIFSSEC_MAY_NTLM)
578 		server->secType = NTLM;
579 	else if (secFlags & CIFSSEC_MAY_NTLMV2)
580 		server->secType = NTLMv2;
581 	else if (secFlags & CIFSSEC_MAY_KRB5)
582 		server->secType = Kerberos;
583 	else if (secFlags & CIFSSEC_MAY_NTLMSSP)
584 		server->secType = RawNTLMSSP;
585 	else if (secFlags & CIFSSEC_MAY_LANMAN)
586 		server->secType = LANMAN;
587 	else {
588 		rc = -EOPNOTSUPP;
589 		cERROR(1, "Invalid security type");
590 		goto neg_err_exit;
591 	}
592 	/* else ... any others ...? */
593 
594 	/* one byte, so no need to convert this or EncryptionKeyLen from
595 	   little endian */
596 	server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
597 			       cifs_max_pending);
598 	cifs_set_credits(server, server->maxReq);
599 	/* probably no need to store and check maxvcs */
600 	server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
601 	server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
602 	cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
603 	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
604 	server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
605 	server->timeAdj *= 60;
606 	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
607 		memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
608 		       CIFS_CRYPTO_KEY_SIZE);
609 	} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
610 			server->capabilities & CAP_EXTENDED_SECURITY) &&
611 				(pSMBr->EncryptionKeyLength == 0)) {
612 		/* decode security blob */
613 		count = get_bcc(&pSMBr->hdr);
614 		if (count < 16) {
615 			rc = -EIO;
616 			goto neg_err_exit;
617 		}
618 		spin_lock(&cifs_tcp_ses_lock);
619 		if (server->srv_count > 1) {
620 			spin_unlock(&cifs_tcp_ses_lock);
621 			if (memcmp(server->server_GUID,
622 				   pSMBr->u.extended_response.
623 				   GUID, 16) != 0) {
624 				cFYI(1, "server UID changed");
625 				memcpy(server->server_GUID,
626 					pSMBr->u.extended_response.GUID,
627 					16);
628 			}
629 		} else {
630 			spin_unlock(&cifs_tcp_ses_lock);
631 			memcpy(server->server_GUID,
632 			       pSMBr->u.extended_response.GUID, 16);
633 		}
634 
635 		if (count == 16) {
636 			server->secType = RawNTLMSSP;
637 		} else {
638 			rc = decode_negTokenInit(pSMBr->u.extended_response.
639 						 SecurityBlob, count - 16,
640 						 server);
641 			if (rc == 1)
642 				rc = 0;
643 			else
644 				rc = -EINVAL;
645 			if (server->secType == Kerberos) {
646 				if (!server->sec_kerberos &&
647 						!server->sec_mskerberos)
648 					rc = -EOPNOTSUPP;
649 			} else if (server->secType == RawNTLMSSP) {
650 				if (!server->sec_ntlmssp)
651 					rc = -EOPNOTSUPP;
652 			} else
653 					rc = -EOPNOTSUPP;
654 		}
655 	} else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
656 		rc = -EIO; /* no crypt key only if plain text pwd */
657 		goto neg_err_exit;
658 	} else
659 		server->capabilities &= ~CAP_EXTENDED_SECURITY;
660 
661 #ifdef CONFIG_CIFS_WEAK_PW_HASH
662 signing_check:
663 #endif
664 	if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
665 		/* MUST_SIGN already includes the MAY_SIGN FLAG
666 		   so if this is zero it means that signing is disabled */
667 		cFYI(1, "Signing disabled");
668 		if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
669 			cERROR(1, "Server requires "
670 				   "packet signing to be enabled in "
671 				   "/proc/fs/cifs/SecurityFlags.");
672 			rc = -EOPNOTSUPP;
673 		}
674 		server->sec_mode &=
675 			~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
676 	} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
677 		/* signing required */
678 		cFYI(1, "Must sign - secFlags 0x%x", secFlags);
679 		if ((server->sec_mode &
680 			(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
681 			cERROR(1, "signing required but server lacks support");
682 			rc = -EOPNOTSUPP;
683 		} else
684 			server->sec_mode |= SECMODE_SIGN_REQUIRED;
685 	} else {
686 		/* signing optional ie CIFSSEC_MAY_SIGN */
687 		if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
688 			server->sec_mode &=
689 				~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
690 	}
691 
692 neg_err_exit:
693 	cifs_buf_release(pSMB);
694 
695 	cFYI(1, "negprot rc %d", rc);
696 	return rc;
697 }
698 
699 int
CIFSSMBTDis(const int xid,struct cifs_tcon * tcon)700 CIFSSMBTDis(const int xid, struct cifs_tcon *tcon)
701 {
702 	struct smb_hdr *smb_buffer;
703 	int rc = 0;
704 
705 	cFYI(1, "In tree disconnect");
706 
707 	/* BB: do we need to check this? These should never be NULL. */
708 	if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
709 		return -EIO;
710 
711 	/*
712 	 * No need to return error on this operation if tid invalidated and
713 	 * closed on server already e.g. due to tcp session crashing. Also,
714 	 * the tcon is no longer on the list, so no need to take lock before
715 	 * checking this.
716 	 */
717 	if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
718 		return 0;
719 
720 	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
721 			    (void **)&smb_buffer);
722 	if (rc)
723 		return rc;
724 
725 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
726 	if (rc)
727 		cFYI(1, "Tree disconnect failed %d", rc);
728 
729 	/* No need to return error on this operation if tid invalidated and
730 	   closed on server already e.g. due to tcp session crashing */
731 	if (rc == -EAGAIN)
732 		rc = 0;
733 
734 	return rc;
735 }
736 
737 /*
738  * This is a no-op for now. We're not really interested in the reply, but
739  * rather in the fact that the server sent one and that server->lstrp
740  * gets updated.
741  *
742  * FIXME: maybe we should consider checking that the reply matches request?
743  */
744 static void
cifs_echo_callback(struct mid_q_entry * mid)745 cifs_echo_callback(struct mid_q_entry *mid)
746 {
747 	struct TCP_Server_Info *server = mid->callback_data;
748 
749 	DeleteMidQEntry(mid);
750 	cifs_add_credits(server, 1);
751 }
752 
753 int
CIFSSMBEcho(struct TCP_Server_Info * server)754 CIFSSMBEcho(struct TCP_Server_Info *server)
755 {
756 	ECHO_REQ *smb;
757 	int rc = 0;
758 	struct kvec iov;
759 
760 	cFYI(1, "In echo request");
761 
762 	rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
763 	if (rc)
764 		return rc;
765 
766 	/* set up echo request */
767 	smb->hdr.Tid = 0xffff;
768 	smb->hdr.WordCount = 1;
769 	put_unaligned_le16(1, &smb->EchoCount);
770 	put_bcc(1, &smb->hdr);
771 	smb->Data[0] = 'a';
772 	inc_rfc1001_len(smb, 3);
773 	iov.iov_base = smb;
774 	iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
775 
776 	rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
777 			     server, true);
778 	if (rc)
779 		cFYI(1, "Echo request failed: %d", rc);
780 
781 	cifs_small_buf_release(smb);
782 
783 	return rc;
784 }
785 
786 int
CIFSSMBLogoff(const int xid,struct cifs_ses * ses)787 CIFSSMBLogoff(const int xid, struct cifs_ses *ses)
788 {
789 	LOGOFF_ANDX_REQ *pSMB;
790 	int rc = 0;
791 
792 	cFYI(1, "In SMBLogoff for session disconnect");
793 
794 	/*
795 	 * BB: do we need to check validity of ses and server? They should
796 	 * always be valid since we have an active reference. If not, that
797 	 * should probably be a BUG()
798 	 */
799 	if (!ses || !ses->server)
800 		return -EIO;
801 
802 	mutex_lock(&ses->session_mutex);
803 	if (ses->need_reconnect)
804 		goto session_already_dead; /* no need to send SMBlogoff if uid
805 					      already closed due to reconnect */
806 	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
807 	if (rc) {
808 		mutex_unlock(&ses->session_mutex);
809 		return rc;
810 	}
811 
812 	pSMB->hdr.Mid = GetNextMid(ses->server);
813 
814 	if (ses->server->sec_mode &
815 		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
816 			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
817 
818 	pSMB->hdr.Uid = ses->Suid;
819 
820 	pSMB->AndXCommand = 0xFF;
821 	rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
822 session_already_dead:
823 	mutex_unlock(&ses->session_mutex);
824 
825 	/* if session dead then we do not need to do ulogoff,
826 		since server closed smb session, no sense reporting
827 		error */
828 	if (rc == -EAGAIN)
829 		rc = 0;
830 	return rc;
831 }
832 
833 int
CIFSPOSIXDelFile(const int xid,struct cifs_tcon * tcon,const char * fileName,__u16 type,const struct nls_table * nls_codepage,int remap)834 CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
835 		 __u16 type, const struct nls_table *nls_codepage, int remap)
836 {
837 	TRANSACTION2_SPI_REQ *pSMB = NULL;
838 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
839 	struct unlink_psx_rq *pRqD;
840 	int name_len;
841 	int rc = 0;
842 	int bytes_returned = 0;
843 	__u16 params, param_offset, offset, byte_count;
844 
845 	cFYI(1, "In POSIX delete");
846 PsxDelete:
847 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
848 		      (void **) &pSMBr);
849 	if (rc)
850 		return rc;
851 
852 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
853 		name_len =
854 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
855 				       PATH_MAX, nls_codepage, remap);
856 		name_len++;	/* trailing null */
857 		name_len *= 2;
858 	} else { /* BB add path length overrun check */
859 		name_len = strnlen(fileName, PATH_MAX);
860 		name_len++;	/* trailing null */
861 		strncpy(pSMB->FileName, fileName, name_len);
862 	}
863 
864 	params = 6 + name_len;
865 	pSMB->MaxParameterCount = cpu_to_le16(2);
866 	pSMB->MaxDataCount = 0; /* BB double check this with jra */
867 	pSMB->MaxSetupCount = 0;
868 	pSMB->Reserved = 0;
869 	pSMB->Flags = 0;
870 	pSMB->Timeout = 0;
871 	pSMB->Reserved2 = 0;
872 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
873 				InformationLevel) - 4;
874 	offset = param_offset + params;
875 
876 	/* Setup pointer to Request Data (inode type) */
877 	pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
878 	pRqD->type = cpu_to_le16(type);
879 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
880 	pSMB->DataOffset = cpu_to_le16(offset);
881 	pSMB->SetupCount = 1;
882 	pSMB->Reserved3 = 0;
883 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
884 	byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
885 
886 	pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
887 	pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
888 	pSMB->ParameterCount = cpu_to_le16(params);
889 	pSMB->TotalParameterCount = pSMB->ParameterCount;
890 	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
891 	pSMB->Reserved4 = 0;
892 	inc_rfc1001_len(pSMB, byte_count);
893 	pSMB->ByteCount = cpu_to_le16(byte_count);
894 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
895 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
896 	if (rc)
897 		cFYI(1, "Posix delete returned %d", rc);
898 	cifs_buf_release(pSMB);
899 
900 	cifs_stats_inc(&tcon->num_deletes);
901 
902 	if (rc == -EAGAIN)
903 		goto PsxDelete;
904 
905 	return rc;
906 }
907 
908 int
CIFSSMBDelFile(const int xid,struct cifs_tcon * tcon,const char * fileName,const struct nls_table * nls_codepage,int remap)909 CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
910 	       const struct nls_table *nls_codepage, int remap)
911 {
912 	DELETE_FILE_REQ *pSMB = NULL;
913 	DELETE_FILE_RSP *pSMBr = NULL;
914 	int rc = 0;
915 	int bytes_returned;
916 	int name_len;
917 
918 DelFileRetry:
919 	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
920 		      (void **) &pSMBr);
921 	if (rc)
922 		return rc;
923 
924 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
925 		name_len =
926 		    cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
927 				       PATH_MAX, nls_codepage, remap);
928 		name_len++;	/* trailing null */
929 		name_len *= 2;
930 	} else {		/* BB improve check for buffer overruns BB */
931 		name_len = strnlen(fileName, PATH_MAX);
932 		name_len++;	/* trailing null */
933 		strncpy(pSMB->fileName, fileName, name_len);
934 	}
935 	pSMB->SearchAttributes =
936 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
937 	pSMB->BufferFormat = 0x04;
938 	inc_rfc1001_len(pSMB, name_len + 1);
939 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
940 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
941 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
942 	cifs_stats_inc(&tcon->num_deletes);
943 	if (rc)
944 		cFYI(1, "Error in RMFile = %d", rc);
945 
946 	cifs_buf_release(pSMB);
947 	if (rc == -EAGAIN)
948 		goto DelFileRetry;
949 
950 	return rc;
951 }
952 
953 int
CIFSSMBRmDir(const int xid,struct cifs_tcon * tcon,const char * dirName,const struct nls_table * nls_codepage,int remap)954 CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName,
955 	     const struct nls_table *nls_codepage, int remap)
956 {
957 	DELETE_DIRECTORY_REQ *pSMB = NULL;
958 	DELETE_DIRECTORY_RSP *pSMBr = NULL;
959 	int rc = 0;
960 	int bytes_returned;
961 	int name_len;
962 
963 	cFYI(1, "In CIFSSMBRmDir");
964 RmDirRetry:
965 	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
966 		      (void **) &pSMBr);
967 	if (rc)
968 		return rc;
969 
970 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
971 		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
972 					      PATH_MAX, nls_codepage, remap);
973 		name_len++;	/* trailing null */
974 		name_len *= 2;
975 	} else {		/* BB improve check for buffer overruns BB */
976 		name_len = strnlen(dirName, PATH_MAX);
977 		name_len++;	/* trailing null */
978 		strncpy(pSMB->DirName, dirName, name_len);
979 	}
980 
981 	pSMB->BufferFormat = 0x04;
982 	inc_rfc1001_len(pSMB, name_len + 1);
983 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
984 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
985 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
986 	cifs_stats_inc(&tcon->num_rmdirs);
987 	if (rc)
988 		cFYI(1, "Error in RMDir = %d", rc);
989 
990 	cifs_buf_release(pSMB);
991 	if (rc == -EAGAIN)
992 		goto RmDirRetry;
993 	return rc;
994 }
995 
996 int
CIFSSMBMkDir(const int xid,struct cifs_tcon * tcon,const char * name,const struct nls_table * nls_codepage,int remap)997 CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
998 	     const char *name, const struct nls_table *nls_codepage, int remap)
999 {
1000 	int rc = 0;
1001 	CREATE_DIRECTORY_REQ *pSMB = NULL;
1002 	CREATE_DIRECTORY_RSP *pSMBr = NULL;
1003 	int bytes_returned;
1004 	int name_len;
1005 
1006 	cFYI(1, "In CIFSSMBMkDir");
1007 MkDirRetry:
1008 	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1009 		      (void **) &pSMBr);
1010 	if (rc)
1011 		return rc;
1012 
1013 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1014 		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
1015 					      PATH_MAX, nls_codepage, remap);
1016 		name_len++;	/* trailing null */
1017 		name_len *= 2;
1018 	} else {		/* BB improve check for buffer overruns BB */
1019 		name_len = strnlen(name, PATH_MAX);
1020 		name_len++;	/* trailing null */
1021 		strncpy(pSMB->DirName, name, name_len);
1022 	}
1023 
1024 	pSMB->BufferFormat = 0x04;
1025 	inc_rfc1001_len(pSMB, name_len + 1);
1026 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
1027 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1028 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1029 	cifs_stats_inc(&tcon->num_mkdirs);
1030 	if (rc)
1031 		cFYI(1, "Error in Mkdir = %d", rc);
1032 
1033 	cifs_buf_release(pSMB);
1034 	if (rc == -EAGAIN)
1035 		goto MkDirRetry;
1036 	return rc;
1037 }
1038 
1039 int
CIFSPOSIXCreate(const int xid,struct cifs_tcon * tcon,__u32 posix_flags,__u64 mode,__u16 * netfid,FILE_UNIX_BASIC_INFO * pRetData,__u32 * pOplock,const char * name,const struct nls_table * nls_codepage,int remap)1040 CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags,
1041 		__u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1042 		__u32 *pOplock, const char *name,
1043 		const struct nls_table *nls_codepage, int remap)
1044 {
1045 	TRANSACTION2_SPI_REQ *pSMB = NULL;
1046 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
1047 	int name_len;
1048 	int rc = 0;
1049 	int bytes_returned = 0;
1050 	__u16 params, param_offset, offset, byte_count, count;
1051 	OPEN_PSX_REQ *pdata;
1052 	OPEN_PSX_RSP *psx_rsp;
1053 
1054 	cFYI(1, "In POSIX Create");
1055 PsxCreat:
1056 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1057 		      (void **) &pSMBr);
1058 	if (rc)
1059 		return rc;
1060 
1061 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1062 		name_len =
1063 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1064 				       PATH_MAX, nls_codepage, remap);
1065 		name_len++;	/* trailing null */
1066 		name_len *= 2;
1067 	} else {	/* BB improve the check for buffer overruns BB */
1068 		name_len = strnlen(name, PATH_MAX);
1069 		name_len++;	/* trailing null */
1070 		strncpy(pSMB->FileName, name, name_len);
1071 	}
1072 
1073 	params = 6 + name_len;
1074 	count = sizeof(OPEN_PSX_REQ);
1075 	pSMB->MaxParameterCount = cpu_to_le16(2);
1076 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* large enough */
1077 	pSMB->MaxSetupCount = 0;
1078 	pSMB->Reserved = 0;
1079 	pSMB->Flags = 0;
1080 	pSMB->Timeout = 0;
1081 	pSMB->Reserved2 = 0;
1082 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
1083 				InformationLevel) - 4;
1084 	offset = param_offset + params;
1085 	pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1086 	pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1087 	pdata->Permissions = cpu_to_le64(mode);
1088 	pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1089 	pdata->OpenFlags =  cpu_to_le32(*pOplock);
1090 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
1091 	pSMB->DataOffset = cpu_to_le16(offset);
1092 	pSMB->SetupCount = 1;
1093 	pSMB->Reserved3 = 0;
1094 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1095 	byte_count = 3 /* pad */  + params + count;
1096 
1097 	pSMB->DataCount = cpu_to_le16(count);
1098 	pSMB->ParameterCount = cpu_to_le16(params);
1099 	pSMB->TotalDataCount = pSMB->DataCount;
1100 	pSMB->TotalParameterCount = pSMB->ParameterCount;
1101 	pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1102 	pSMB->Reserved4 = 0;
1103 	inc_rfc1001_len(pSMB, byte_count);
1104 	pSMB->ByteCount = cpu_to_le16(byte_count);
1105 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1106 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1107 	if (rc) {
1108 		cFYI(1, "Posix create returned %d", rc);
1109 		goto psx_create_err;
1110 	}
1111 
1112 	cFYI(1, "copying inode info");
1113 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1114 
1115 	if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1116 		rc = -EIO;	/* bad smb */
1117 		goto psx_create_err;
1118 	}
1119 
1120 	/* copy return information to pRetData */
1121 	psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1122 			+ le16_to_cpu(pSMBr->t2.DataOffset));
1123 
1124 	*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1125 	if (netfid)
1126 		*netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1127 	/* Let caller know file was created so we can set the mode. */
1128 	/* Do we care about the CreateAction in any other cases? */
1129 	if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1130 		*pOplock |= CIFS_CREATE_ACTION;
1131 	/* check to make sure response data is there */
1132 	if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1133 		pRetData->Type = cpu_to_le32(-1); /* unknown */
1134 		cFYI(DBG2, "unknown type");
1135 	} else {
1136 		if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1137 					+ sizeof(FILE_UNIX_BASIC_INFO)) {
1138 			cERROR(1, "Open response data too small");
1139 			pRetData->Type = cpu_to_le32(-1);
1140 			goto psx_create_err;
1141 		}
1142 		memcpy((char *) pRetData,
1143 			(char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1144 			sizeof(FILE_UNIX_BASIC_INFO));
1145 	}
1146 
1147 psx_create_err:
1148 	cifs_buf_release(pSMB);
1149 
1150 	if (posix_flags & SMB_O_DIRECTORY)
1151 		cifs_stats_inc(&tcon->num_posixmkdirs);
1152 	else
1153 		cifs_stats_inc(&tcon->num_posixopens);
1154 
1155 	if (rc == -EAGAIN)
1156 		goto PsxCreat;
1157 
1158 	return rc;
1159 }
1160 
convert_disposition(int disposition)1161 static __u16 convert_disposition(int disposition)
1162 {
1163 	__u16 ofun = 0;
1164 
1165 	switch (disposition) {
1166 		case FILE_SUPERSEDE:
1167 			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1168 			break;
1169 		case FILE_OPEN:
1170 			ofun = SMBOPEN_OAPPEND;
1171 			break;
1172 		case FILE_CREATE:
1173 			ofun = SMBOPEN_OCREATE;
1174 			break;
1175 		case FILE_OPEN_IF:
1176 			ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1177 			break;
1178 		case FILE_OVERWRITE:
1179 			ofun = SMBOPEN_OTRUNC;
1180 			break;
1181 		case FILE_OVERWRITE_IF:
1182 			ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1183 			break;
1184 		default:
1185 			cFYI(1, "unknown disposition %d", disposition);
1186 			ofun =  SMBOPEN_OAPPEND; /* regular open */
1187 	}
1188 	return ofun;
1189 }
1190 
1191 static int
access_flags_to_smbopen_mode(const int access_flags)1192 access_flags_to_smbopen_mode(const int access_flags)
1193 {
1194 	int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1195 
1196 	if (masked_flags == GENERIC_READ)
1197 		return SMBOPEN_READ;
1198 	else if (masked_flags == GENERIC_WRITE)
1199 		return SMBOPEN_WRITE;
1200 
1201 	/* just go for read/write */
1202 	return SMBOPEN_READWRITE;
1203 }
1204 
1205 int
SMBLegacyOpen(const int xid,struct cifs_tcon * tcon,const char * fileName,const int openDisposition,const int access_flags,const int create_options,__u16 * netfid,int * pOplock,FILE_ALL_INFO * pfile_info,const struct nls_table * nls_codepage,int remap)1206 SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
1207 	    const char *fileName, const int openDisposition,
1208 	    const int access_flags, const int create_options, __u16 *netfid,
1209 	    int *pOplock, FILE_ALL_INFO *pfile_info,
1210 	    const struct nls_table *nls_codepage, int remap)
1211 {
1212 	int rc = -EACCES;
1213 	OPENX_REQ *pSMB = NULL;
1214 	OPENX_RSP *pSMBr = NULL;
1215 	int bytes_returned;
1216 	int name_len;
1217 	__u16 count;
1218 
1219 OldOpenRetry:
1220 	rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1221 		      (void **) &pSMBr);
1222 	if (rc)
1223 		return rc;
1224 
1225 	pSMB->AndXCommand = 0xFF;       /* none */
1226 
1227 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1228 		count = 1;      /* account for one byte pad to word boundary */
1229 		name_len =
1230 		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1231 				      fileName, PATH_MAX, nls_codepage, remap);
1232 		name_len++;     /* trailing null */
1233 		name_len *= 2;
1234 	} else {                /* BB improve check for buffer overruns BB */
1235 		count = 0;      /* no pad */
1236 		name_len = strnlen(fileName, PATH_MAX);
1237 		name_len++;     /* trailing null */
1238 		strncpy(pSMB->fileName, fileName, name_len);
1239 	}
1240 	if (*pOplock & REQ_OPLOCK)
1241 		pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1242 	else if (*pOplock & REQ_BATCHOPLOCK)
1243 		pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1244 
1245 	pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1246 	pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1247 	pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1248 	/* set file as system file if special file such
1249 	   as fifo and server expecting SFU style and
1250 	   no Unix extensions */
1251 
1252 	if (create_options & CREATE_OPTION_SPECIAL)
1253 		pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1254 	else /* BB FIXME BB */
1255 		pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1256 
1257 	if (create_options & CREATE_OPTION_READONLY)
1258 		pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1259 
1260 	/* BB FIXME BB */
1261 /*	pSMB->CreateOptions = cpu_to_le32(create_options &
1262 						 CREATE_OPTIONS_MASK); */
1263 	/* BB FIXME END BB */
1264 
1265 	pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1266 	pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1267 	count += name_len;
1268 	inc_rfc1001_len(pSMB, count);
1269 
1270 	pSMB->ByteCount = cpu_to_le16(count);
1271 	/* long_op set to 1 to allow for oplock break timeouts */
1272 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1273 			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
1274 	cifs_stats_inc(&tcon->num_opens);
1275 	if (rc) {
1276 		cFYI(1, "Error in Open = %d", rc);
1277 	} else {
1278 	/* BB verify if wct == 15 */
1279 
1280 /*		*pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1281 
1282 		*netfid = pSMBr->Fid;   /* cifs fid stays in le */
1283 		/* Let caller know file was created so we can set the mode. */
1284 		/* Do we care about the CreateAction in any other cases? */
1285 	/* BB FIXME BB */
1286 /*		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1287 			*pOplock |= CIFS_CREATE_ACTION; */
1288 	/* BB FIXME END */
1289 
1290 		if (pfile_info) {
1291 			pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1292 			pfile_info->LastAccessTime = 0; /* BB fixme */
1293 			pfile_info->LastWriteTime = 0; /* BB fixme */
1294 			pfile_info->ChangeTime = 0;  /* BB fixme */
1295 			pfile_info->Attributes =
1296 				cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1297 			/* the file_info buf is endian converted by caller */
1298 			pfile_info->AllocationSize =
1299 				cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1300 			pfile_info->EndOfFile = pfile_info->AllocationSize;
1301 			pfile_info->NumberOfLinks = cpu_to_le32(1);
1302 			pfile_info->DeletePending = 0;
1303 		}
1304 	}
1305 
1306 	cifs_buf_release(pSMB);
1307 	if (rc == -EAGAIN)
1308 		goto OldOpenRetry;
1309 	return rc;
1310 }
1311 
1312 int
CIFSSMBOpen(const int xid,struct cifs_tcon * tcon,const char * fileName,const int openDisposition,const int access_flags,const int create_options,__u16 * netfid,int * pOplock,FILE_ALL_INFO * pfile_info,const struct nls_table * nls_codepage,int remap)1313 CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
1314 	    const char *fileName, const int openDisposition,
1315 	    const int access_flags, const int create_options, __u16 *netfid,
1316 	    int *pOplock, FILE_ALL_INFO *pfile_info,
1317 	    const struct nls_table *nls_codepage, int remap)
1318 {
1319 	int rc = -EACCES;
1320 	OPEN_REQ *pSMB = NULL;
1321 	OPEN_RSP *pSMBr = NULL;
1322 	int bytes_returned;
1323 	int name_len;
1324 	__u16 count;
1325 
1326 openRetry:
1327 	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1328 		      (void **) &pSMBr);
1329 	if (rc)
1330 		return rc;
1331 
1332 	pSMB->AndXCommand = 0xFF;	/* none */
1333 
1334 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1335 		count = 1;	/* account for one byte pad to word boundary */
1336 		name_len =
1337 		    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1338 				       fileName, PATH_MAX, nls_codepage, remap);
1339 		name_len++;	/* trailing null */
1340 		name_len *= 2;
1341 		pSMB->NameLength = cpu_to_le16(name_len);
1342 	} else {		/* BB improve check for buffer overruns BB */
1343 		count = 0;	/* no pad */
1344 		name_len = strnlen(fileName, PATH_MAX);
1345 		name_len++;	/* trailing null */
1346 		pSMB->NameLength = cpu_to_le16(name_len);
1347 		strncpy(pSMB->fileName, fileName, name_len);
1348 	}
1349 	if (*pOplock & REQ_OPLOCK)
1350 		pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1351 	else if (*pOplock & REQ_BATCHOPLOCK)
1352 		pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1353 	pSMB->DesiredAccess = cpu_to_le32(access_flags);
1354 	pSMB->AllocationSize = 0;
1355 	/* set file as system file if special file such
1356 	   as fifo and server expecting SFU style and
1357 	   no Unix extensions */
1358 	if (create_options & CREATE_OPTION_SPECIAL)
1359 		pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1360 	else
1361 		pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1362 
1363 	/* XP does not handle ATTR_POSIX_SEMANTICS */
1364 	/* but it helps speed up case sensitive checks for other
1365 	servers such as Samba */
1366 	if (tcon->ses->capabilities & CAP_UNIX)
1367 		pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1368 
1369 	if (create_options & CREATE_OPTION_READONLY)
1370 		pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1371 
1372 	pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1373 	pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1374 	pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1375 	/* BB Expirement with various impersonation levels and verify */
1376 	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1377 	pSMB->SecurityFlags =
1378 	    SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1379 
1380 	count += name_len;
1381 	inc_rfc1001_len(pSMB, count);
1382 
1383 	pSMB->ByteCount = cpu_to_le16(count);
1384 	/* long_op set to 1 to allow for oplock break timeouts */
1385 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1386 			(struct smb_hdr *)pSMBr, &bytes_returned, 0);
1387 	cifs_stats_inc(&tcon->num_opens);
1388 	if (rc) {
1389 		cFYI(1, "Error in Open = %d", rc);
1390 	} else {
1391 		*pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1392 		*netfid = pSMBr->Fid;	/* cifs fid stays in le */
1393 		/* Let caller know file was created so we can set the mode. */
1394 		/* Do we care about the CreateAction in any other cases? */
1395 		if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1396 			*pOplock |= CIFS_CREATE_ACTION;
1397 		if (pfile_info) {
1398 			memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1399 				36 /* CreationTime to Attributes */);
1400 			/* the file_info buf is endian converted by caller */
1401 			pfile_info->AllocationSize = pSMBr->AllocationSize;
1402 			pfile_info->EndOfFile = pSMBr->EndOfFile;
1403 			pfile_info->NumberOfLinks = cpu_to_le32(1);
1404 			pfile_info->DeletePending = 0;
1405 		}
1406 	}
1407 
1408 	cifs_buf_release(pSMB);
1409 	if (rc == -EAGAIN)
1410 		goto openRetry;
1411 	return rc;
1412 }
1413 
1414 struct cifs_readdata *
cifs_readdata_alloc(unsigned int nr_pages)1415 cifs_readdata_alloc(unsigned int nr_pages)
1416 {
1417 	struct cifs_readdata *rdata;
1418 
1419 	/* readdata + 1 kvec for each page */
1420 	rdata = kzalloc(sizeof(*rdata) +
1421 			sizeof(struct kvec) * nr_pages, GFP_KERNEL);
1422 	if (rdata != NULL) {
1423 		INIT_WORK(&rdata->work, cifs_readv_complete);
1424 		INIT_LIST_HEAD(&rdata->pages);
1425 	}
1426 	return rdata;
1427 }
1428 
1429 void
cifs_readdata_free(struct cifs_readdata * rdata)1430 cifs_readdata_free(struct cifs_readdata *rdata)
1431 {
1432 	cifsFileInfo_put(rdata->cfile);
1433 	kfree(rdata);
1434 }
1435 
1436 /*
1437  * Discard any remaining data in the current SMB. To do this, we borrow the
1438  * current bigbuf.
1439  */
1440 static int
cifs_readv_discard(struct TCP_Server_Info * server,struct mid_q_entry * mid)1441 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1442 {
1443 	unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1444 	int remaining = rfclen + 4 - server->total_read;
1445 	struct cifs_readdata *rdata = mid->callback_data;
1446 
1447 	while (remaining > 0) {
1448 		int length;
1449 
1450 		length = cifs_read_from_socket(server, server->bigbuf,
1451 				min_t(unsigned int, remaining,
1452 					CIFSMaxBufSize + max_header_size()));
1453 		if (length < 0)
1454 			return length;
1455 		server->total_read += length;
1456 		remaining -= length;
1457 	}
1458 
1459 	dequeue_mid(mid, rdata->result);
1460 	return 0;
1461 }
1462 
1463 static inline size_t
read_rsp_size(void)1464 read_rsp_size(void)
1465 {
1466 	return sizeof(READ_RSP);
1467 }
1468 
1469 static inline unsigned int
read_data_offset(char * buf)1470 read_data_offset(char *buf)
1471 {
1472 	READ_RSP *rsp = (READ_RSP *)buf;
1473 	return le16_to_cpu(rsp->DataOffset);
1474 }
1475 
1476 static inline unsigned int
read_data_length(char * buf)1477 read_data_length(char *buf)
1478 {
1479 	READ_RSP *rsp = (READ_RSP *)buf;
1480 	return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
1481 	       le16_to_cpu(rsp->DataLength);
1482 }
1483 
1484 static int
cifs_readv_receive(struct TCP_Server_Info * server,struct mid_q_entry * mid)1485 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1486 {
1487 	int length, len;
1488 	unsigned int data_offset, remaining, data_len;
1489 	struct cifs_readdata *rdata = mid->callback_data;
1490 	char *buf = server->smallbuf;
1491 	unsigned int buflen = get_rfc1002_length(buf) + 4;
1492 	u64 eof;
1493 	pgoff_t eof_index;
1494 	struct page *page, *tpage;
1495 
1496 	cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1497 		mid->mid, rdata->offset, rdata->bytes);
1498 
1499 	/*
1500 	 * read the rest of READ_RSP header (sans Data array), or whatever we
1501 	 * can if there's not enough data. At this point, we've read down to
1502 	 * the Mid.
1503 	 */
1504 	len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1;
1505 
1506 	rdata->iov[0].iov_base = buf + header_size() - 1;
1507 	rdata->iov[0].iov_len = len;
1508 
1509 	length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1510 	if (length < 0)
1511 		return length;
1512 	server->total_read += length;
1513 
1514 	/* Was the SMB read successful? */
1515 	rdata->result = map_smb_to_linux_error(buf, false);
1516 	if (rdata->result != 0) {
1517 		cFYI(1, "%s: server returned error %d", __func__,
1518 			rdata->result);
1519 		return cifs_readv_discard(server, mid);
1520 	}
1521 
1522 	/* Is there enough to get to the rest of the READ_RSP header? */
1523 	if (server->total_read < read_rsp_size()) {
1524 		cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1525 			__func__, server->total_read, read_rsp_size());
1526 		rdata->result = -EIO;
1527 		return cifs_readv_discard(server, mid);
1528 	}
1529 
1530 	data_offset = read_data_offset(buf) + 4;
1531 	if (data_offset < server->total_read) {
1532 		/*
1533 		 * win2k8 sometimes sends an offset of 0 when the read
1534 		 * is beyond the EOF. Treat it as if the data starts just after
1535 		 * the header.
1536 		 */
1537 		cFYI(1, "%s: data offset (%u) inside read response header",
1538 			__func__, data_offset);
1539 		data_offset = server->total_read;
1540 	} else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1541 		/* data_offset is beyond the end of smallbuf */
1542 		cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1543 			__func__, data_offset);
1544 		rdata->result = -EIO;
1545 		return cifs_readv_discard(server, mid);
1546 	}
1547 
1548 	cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1549 		server->total_read, data_offset);
1550 
1551 	len = data_offset - server->total_read;
1552 	if (len > 0) {
1553 		/* read any junk before data into the rest of smallbuf */
1554 		rdata->iov[0].iov_base = buf + server->total_read;
1555 		rdata->iov[0].iov_len = len;
1556 		length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1557 		if (length < 0)
1558 			return length;
1559 		server->total_read += length;
1560 	}
1561 
1562 	/* set up first iov for signature check */
1563 	rdata->iov[0].iov_base = buf;
1564 	rdata->iov[0].iov_len = server->total_read;
1565 	cFYI(1, "0: iov_base=%p iov_len=%zu",
1566 		rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1567 
1568 	/* how much data is in the response? */
1569 	data_len = read_data_length(buf);
1570 	if (data_offset + data_len > buflen) {
1571 		/* data_len is corrupt -- discard frame */
1572 		rdata->result = -EIO;
1573 		return cifs_readv_discard(server, mid);
1574 	}
1575 
1576 	/* marshal up the page array */
1577 	len = 0;
1578 	remaining = data_len;
1579 	rdata->nr_iov = 1;
1580 
1581 	/* determine the eof that the server (probably) has */
1582 	eof = CIFS_I(rdata->mapping->host)->server_eof;
1583 	eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
1584 	cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
1585 
1586 	cifs_kmap_lock();
1587 	list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1588 		if (remaining >= PAGE_CACHE_SIZE) {
1589 			/* enough data to fill the page */
1590 			rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1591 			rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
1592 			cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1593 				rdata->nr_iov, page->index,
1594 				rdata->iov[rdata->nr_iov].iov_base,
1595 				rdata->iov[rdata->nr_iov].iov_len);
1596 			++rdata->nr_iov;
1597 			len += PAGE_CACHE_SIZE;
1598 			remaining -= PAGE_CACHE_SIZE;
1599 		} else if (remaining > 0) {
1600 			/* enough for partial page, fill and zero the rest */
1601 			rdata->iov[rdata->nr_iov].iov_base = kmap(page);
1602 			rdata->iov[rdata->nr_iov].iov_len = remaining;
1603 			cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
1604 				rdata->nr_iov, page->index,
1605 				rdata->iov[rdata->nr_iov].iov_base,
1606 				rdata->iov[rdata->nr_iov].iov_len);
1607 			memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
1608 				'\0', PAGE_CACHE_SIZE - remaining);
1609 			++rdata->nr_iov;
1610 			len += remaining;
1611 			remaining = 0;
1612 		} else if (page->index > eof_index) {
1613 			/*
1614 			 * The VFS will not try to do readahead past the
1615 			 * i_size, but it's possible that we have outstanding
1616 			 * writes with gaps in the middle and the i_size hasn't
1617 			 * caught up yet. Populate those with zeroed out pages
1618 			 * to prevent the VFS from repeatedly attempting to
1619 			 * fill them until the writes are flushed.
1620 			 */
1621 			zero_user(page, 0, PAGE_CACHE_SIZE);
1622 			list_del(&page->lru);
1623 			lru_cache_add_file(page);
1624 			flush_dcache_page(page);
1625 			SetPageUptodate(page);
1626 			unlock_page(page);
1627 			page_cache_release(page);
1628 		} else {
1629 			/* no need to hold page hostage */
1630 			list_del(&page->lru);
1631 			lru_cache_add_file(page);
1632 			unlock_page(page);
1633 			page_cache_release(page);
1634 		}
1635 	}
1636 	cifs_kmap_unlock();
1637 
1638 	/* issue the read if we have any iovecs left to fill */
1639 	if (rdata->nr_iov > 1) {
1640 		length = cifs_readv_from_socket(server, &rdata->iov[1],
1641 						rdata->nr_iov - 1, len);
1642 		if (length < 0)
1643 			return length;
1644 		server->total_read += length;
1645 	} else {
1646 		length = 0;
1647 	}
1648 
1649 	rdata->bytes = length;
1650 
1651 	cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1652 		buflen, remaining);
1653 
1654 	/* discard anything left over */
1655 	if (server->total_read < buflen)
1656 		return cifs_readv_discard(server, mid);
1657 
1658 	dequeue_mid(mid, false);
1659 	return length;
1660 }
1661 
1662 static void
cifs_readv_complete(struct work_struct * work)1663 cifs_readv_complete(struct work_struct *work)
1664 {
1665 	struct cifs_readdata *rdata = container_of(work,
1666 						struct cifs_readdata, work);
1667 	struct page *page, *tpage;
1668 
1669 	list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
1670 		list_del(&page->lru);
1671 		lru_cache_add_file(page);
1672 
1673 		if (rdata->result == 0) {
1674 			kunmap(page);
1675 			flush_dcache_page(page);
1676 			SetPageUptodate(page);
1677 		}
1678 
1679 		unlock_page(page);
1680 
1681 		if (rdata->result == 0)
1682 			cifs_readpage_to_fscache(rdata->mapping->host, page);
1683 
1684 		page_cache_release(page);
1685 	}
1686 	cifs_readdata_free(rdata);
1687 }
1688 
1689 static void
cifs_readv_callback(struct mid_q_entry * mid)1690 cifs_readv_callback(struct mid_q_entry *mid)
1691 {
1692 	struct cifs_readdata *rdata = mid->callback_data;
1693 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1694 	struct TCP_Server_Info *server = tcon->ses->server;
1695 
1696 	cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1697 		mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1698 
1699 	switch (mid->mid_state) {
1700 	case MID_RESPONSE_RECEIVED:
1701 		/* result already set, check signature */
1702 		if (server->sec_mode &
1703 		    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1704 			if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1705 					  server, mid->sequence_number + 1))
1706 				cERROR(1, "Unexpected SMB signature");
1707 		}
1708 		/* FIXME: should this be counted toward the initiating task? */
1709 		task_io_account_read(rdata->bytes);
1710 		cifs_stats_bytes_read(tcon, rdata->bytes);
1711 		break;
1712 	case MID_REQUEST_SUBMITTED:
1713 	case MID_RETRY_NEEDED:
1714 		rdata->result = -EAGAIN;
1715 		break;
1716 	default:
1717 		rdata->result = -EIO;
1718 	}
1719 
1720 	queue_work(cifsiod_wq, &rdata->work);
1721 	DeleteMidQEntry(mid);
1722 	cifs_add_credits(server, 1);
1723 }
1724 
1725 /* cifs_async_readv - send an async write, and set up mid to handle result */
1726 int
cifs_async_readv(struct cifs_readdata * rdata)1727 cifs_async_readv(struct cifs_readdata *rdata)
1728 {
1729 	int rc;
1730 	READ_REQ *smb = NULL;
1731 	int wct;
1732 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1733 
1734 	cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1735 		rdata->offset, rdata->bytes);
1736 
1737 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1738 		wct = 12;
1739 	else {
1740 		wct = 10; /* old style read */
1741 		if ((rdata->offset >> 32) > 0)  {
1742 			/* can not handle this big offset for old */
1743 			return -EIO;
1744 		}
1745 	}
1746 
1747 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1748 	if (rc)
1749 		return rc;
1750 
1751 	smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1752 	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1753 
1754 	smb->AndXCommand = 0xFF;	/* none */
1755 	smb->Fid = rdata->cfile->netfid;
1756 	smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1757 	if (wct == 12)
1758 		smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1759 	smb->Remaining = 0;
1760 	smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1761 	smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1762 	if (wct == 12)
1763 		smb->ByteCount = 0;
1764 	else {
1765 		/* old style read */
1766 		struct smb_com_readx_req *smbr =
1767 			(struct smb_com_readx_req *)smb;
1768 		smbr->ByteCount = 0;
1769 	}
1770 
1771 	/* 4 for RFC1001 length + 1 for BCC */
1772 	rdata->iov[0].iov_base = smb;
1773 	rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1774 
1775 	rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1776 			     cifs_readv_receive, cifs_readv_callback,
1777 			     rdata, false);
1778 
1779 	if (rc == 0)
1780 		cifs_stats_inc(&tcon->num_reads);
1781 
1782 	cifs_small_buf_release(smb);
1783 	return rc;
1784 }
1785 
1786 int
CIFSSMBRead(const int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,char ** buf,int * pbuf_type)1787 CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1788 	    char **buf, int *pbuf_type)
1789 {
1790 	int rc = -EACCES;
1791 	READ_REQ *pSMB = NULL;
1792 	READ_RSP *pSMBr = NULL;
1793 	char *pReadData = NULL;
1794 	int wct;
1795 	int resp_buf_type = 0;
1796 	struct kvec iov[1];
1797 	__u32 pid = io_parms->pid;
1798 	__u16 netfid = io_parms->netfid;
1799 	__u64 offset = io_parms->offset;
1800 	struct cifs_tcon *tcon = io_parms->tcon;
1801 	unsigned int count = io_parms->length;
1802 
1803 	cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1804 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1805 		wct = 12;
1806 	else {
1807 		wct = 10; /* old style read */
1808 		if ((offset >> 32) > 0)  {
1809 			/* can not handle this big offset for old */
1810 			return -EIO;
1811 		}
1812 	}
1813 
1814 	*nbytes = 0;
1815 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1816 	if (rc)
1817 		return rc;
1818 
1819 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1820 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1821 
1822 	/* tcon and ses pointer are checked in smb_init */
1823 	if (tcon->ses->server == NULL)
1824 		return -ECONNABORTED;
1825 
1826 	pSMB->AndXCommand = 0xFF;       /* none */
1827 	pSMB->Fid = netfid;
1828 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1829 	if (wct == 12)
1830 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1831 
1832 	pSMB->Remaining = 0;
1833 	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1834 	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1835 	if (wct == 12)
1836 		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1837 	else {
1838 		/* old style read */
1839 		struct smb_com_readx_req *pSMBW =
1840 			(struct smb_com_readx_req *)pSMB;
1841 		pSMBW->ByteCount = 0;
1842 	}
1843 
1844 	iov[0].iov_base = (char *)pSMB;
1845 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1846 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1847 			 &resp_buf_type, CIFS_LOG_ERROR);
1848 	cifs_stats_inc(&tcon->num_reads);
1849 	pSMBr = (READ_RSP *)iov[0].iov_base;
1850 	if (rc) {
1851 		cERROR(1, "Send error in read = %d", rc);
1852 	} else {
1853 		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1854 		data_length = data_length << 16;
1855 		data_length += le16_to_cpu(pSMBr->DataLength);
1856 		*nbytes = data_length;
1857 
1858 		/*check that DataLength would not go beyond end of SMB */
1859 		if ((data_length > CIFSMaxBufSize)
1860 				|| (data_length > count)) {
1861 			cFYI(1, "bad length %d for count %d",
1862 				 data_length, count);
1863 			rc = -EIO;
1864 			*nbytes = 0;
1865 		} else {
1866 			pReadData = (char *) (&pSMBr->hdr.Protocol) +
1867 					le16_to_cpu(pSMBr->DataOffset);
1868 /*			if (rc = copy_to_user(buf, pReadData, data_length)) {
1869 				cERROR(1, "Faulting on read rc = %d",rc);
1870 				rc = -EFAULT;
1871 			}*/ /* can not use copy_to_user when using page cache*/
1872 			if (*buf)
1873 				memcpy(*buf, pReadData, data_length);
1874 		}
1875 	}
1876 
1877 /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1878 	if (*buf) {
1879 		if (resp_buf_type == CIFS_SMALL_BUFFER)
1880 			cifs_small_buf_release(iov[0].iov_base);
1881 		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1882 			cifs_buf_release(iov[0].iov_base);
1883 	} else if (resp_buf_type != CIFS_NO_BUFFER) {
1884 		/* return buffer to caller to free */
1885 		*buf = iov[0].iov_base;
1886 		if (resp_buf_type == CIFS_SMALL_BUFFER)
1887 			*pbuf_type = CIFS_SMALL_BUFFER;
1888 		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1889 			*pbuf_type = CIFS_LARGE_BUFFER;
1890 	} /* else no valid buffer on return - leave as null */
1891 
1892 	/* Note: On -EAGAIN error only caller can retry on handle based calls
1893 		since file handle passed in no longer valid */
1894 	return rc;
1895 }
1896 
1897 
1898 int
CIFSSMBWrite(const int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,const char * buf,const char __user * ubuf,const int long_op)1899 CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1900 	     unsigned int *nbytes, const char *buf,
1901 	     const char __user *ubuf, const int long_op)
1902 {
1903 	int rc = -EACCES;
1904 	WRITE_REQ *pSMB = NULL;
1905 	WRITE_RSP *pSMBr = NULL;
1906 	int bytes_returned, wct;
1907 	__u32 bytes_sent;
1908 	__u16 byte_count;
1909 	__u32 pid = io_parms->pid;
1910 	__u16 netfid = io_parms->netfid;
1911 	__u64 offset = io_parms->offset;
1912 	struct cifs_tcon *tcon = io_parms->tcon;
1913 	unsigned int count = io_parms->length;
1914 
1915 	*nbytes = 0;
1916 
1917 	/* cFYI(1, "write at %lld %d bytes", offset, count);*/
1918 	if (tcon->ses == NULL)
1919 		return -ECONNABORTED;
1920 
1921 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1922 		wct = 14;
1923 	else {
1924 		wct = 12;
1925 		if ((offset >> 32) > 0) {
1926 			/* can not handle big offset for old srv */
1927 			return -EIO;
1928 		}
1929 	}
1930 
1931 	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1932 		      (void **) &pSMBr);
1933 	if (rc)
1934 		return rc;
1935 
1936 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1937 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1938 
1939 	/* tcon and ses pointer are checked in smb_init */
1940 	if (tcon->ses->server == NULL)
1941 		return -ECONNABORTED;
1942 
1943 	pSMB->AndXCommand = 0xFF;	/* none */
1944 	pSMB->Fid = netfid;
1945 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1946 	if (wct == 14)
1947 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1948 
1949 	pSMB->Reserved = 0xFFFFFFFF;
1950 	pSMB->WriteMode = 0;
1951 	pSMB->Remaining = 0;
1952 
1953 	/* Can increase buffer size if buffer is big enough in some cases ie we
1954 	can send more if LARGE_WRITE_X capability returned by the server and if
1955 	our buffer is big enough or if we convert to iovecs on socket writes
1956 	and eliminate the copy to the CIFS buffer */
1957 	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1958 		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1959 	} else {
1960 		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1961 			 & ~0xFF;
1962 	}
1963 
1964 	if (bytes_sent > count)
1965 		bytes_sent = count;
1966 	pSMB->DataOffset =
1967 		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1968 	if (buf)
1969 		memcpy(pSMB->Data, buf, bytes_sent);
1970 	else if (ubuf) {
1971 		if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1972 			cifs_buf_release(pSMB);
1973 			return -EFAULT;
1974 		}
1975 	} else if (count != 0) {
1976 		/* No buffer */
1977 		cifs_buf_release(pSMB);
1978 		return -EINVAL;
1979 	} /* else setting file size with write of zero bytes */
1980 	if (wct == 14)
1981 		byte_count = bytes_sent + 1; /* pad */
1982 	else /* wct == 12 */
1983 		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1984 
1985 	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1986 	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1987 	inc_rfc1001_len(pSMB, byte_count);
1988 
1989 	if (wct == 14)
1990 		pSMB->ByteCount = cpu_to_le16(byte_count);
1991 	else { /* old style write has byte count 4 bytes earlier
1992 		  so 4 bytes pad  */
1993 		struct smb_com_writex_req *pSMBW =
1994 			(struct smb_com_writex_req *)pSMB;
1995 		pSMBW->ByteCount = cpu_to_le16(byte_count);
1996 	}
1997 
1998 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1999 			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
2000 	cifs_stats_inc(&tcon->num_writes);
2001 	if (rc) {
2002 		cFYI(1, "Send error in write = %d", rc);
2003 	} else {
2004 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
2005 		*nbytes = (*nbytes) << 16;
2006 		*nbytes += le16_to_cpu(pSMBr->Count);
2007 
2008 		/*
2009 		 * Mask off high 16 bits when bytes written as returned by the
2010 		 * server is greater than bytes requested by the client. Some
2011 		 * OS/2 servers are known to set incorrect CountHigh values.
2012 		 */
2013 		if (*nbytes > count)
2014 			*nbytes &= 0xFFFF;
2015 	}
2016 
2017 	cifs_buf_release(pSMB);
2018 
2019 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2020 		since file handle passed in no longer valid */
2021 
2022 	return rc;
2023 }
2024 
2025 void
cifs_writedata_release(struct kref * refcount)2026 cifs_writedata_release(struct kref *refcount)
2027 {
2028 	struct cifs_writedata *wdata = container_of(refcount,
2029 					struct cifs_writedata, refcount);
2030 
2031 	if (wdata->cfile)
2032 		cifsFileInfo_put(wdata->cfile);
2033 
2034 	kfree(wdata);
2035 }
2036 
2037 /*
2038  * Write failed with a retryable error. Resend the write request. It's also
2039  * possible that the page was redirtied so re-clean the page.
2040  */
2041 static void
cifs_writev_requeue(struct cifs_writedata * wdata)2042 cifs_writev_requeue(struct cifs_writedata *wdata)
2043 {
2044 	int i, rc;
2045 	struct inode *inode = wdata->cfile->dentry->d_inode;
2046 
2047 	for (i = 0; i < wdata->nr_pages; i++) {
2048 		lock_page(wdata->pages[i]);
2049 		clear_page_dirty_for_io(wdata->pages[i]);
2050 	}
2051 
2052 	do {
2053 		rc = cifs_async_writev(wdata);
2054 	} while (rc == -EAGAIN);
2055 
2056 	for (i = 0; i < wdata->nr_pages; i++) {
2057 		if (rc != 0)
2058 			SetPageError(wdata->pages[i]);
2059 		unlock_page(wdata->pages[i]);
2060 	}
2061 
2062 	mapping_set_error(inode->i_mapping, rc);
2063 	kref_put(&wdata->refcount, cifs_writedata_release);
2064 }
2065 
2066 void
cifs_writev_complete(struct work_struct * work)2067 cifs_writev_complete(struct work_struct *work)
2068 {
2069 	struct cifs_writedata *wdata = container_of(work,
2070 						struct cifs_writedata, work);
2071 	struct inode *inode = wdata->cfile->dentry->d_inode;
2072 	int i = 0;
2073 
2074 	if (wdata->result == 0) {
2075 		spin_lock(&inode->i_lock);
2076 		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2077 		spin_unlock(&inode->i_lock);
2078 		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2079 					 wdata->bytes);
2080 	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2081 		return cifs_writev_requeue(wdata);
2082 
2083 	for (i = 0; i < wdata->nr_pages; i++) {
2084 		struct page *page = wdata->pages[i];
2085 		if (wdata->result == -EAGAIN)
2086 			__set_page_dirty_nobuffers(page);
2087 		else if (wdata->result < 0)
2088 			SetPageError(page);
2089 		end_page_writeback(page);
2090 		page_cache_release(page);
2091 	}
2092 	if (wdata->result != -EAGAIN)
2093 		mapping_set_error(inode->i_mapping, wdata->result);
2094 	kref_put(&wdata->refcount, cifs_writedata_release);
2095 }
2096 
2097 struct cifs_writedata *
cifs_writedata_alloc(unsigned int nr_pages,work_func_t complete)2098 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2099 {
2100 	struct cifs_writedata *wdata;
2101 
2102 	/* this would overflow */
2103 	if (nr_pages == 0) {
2104 		cERROR(1, "%s: called with nr_pages == 0!", __func__);
2105 		return NULL;
2106 	}
2107 
2108 	/* writedata + number of page pointers */
2109 	wdata = kzalloc(sizeof(*wdata) +
2110 			sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
2111 	if (wdata != NULL) {
2112 		kref_init(&wdata->refcount);
2113 		INIT_LIST_HEAD(&wdata->list);
2114 		init_completion(&wdata->done);
2115 		INIT_WORK(&wdata->work, complete);
2116 	}
2117 	return wdata;
2118 }
2119 
2120 /*
2121  * Check the mid_state and signature on received buffer (if any), and queue the
2122  * workqueue completion task.
2123  */
2124 static void
cifs_writev_callback(struct mid_q_entry * mid)2125 cifs_writev_callback(struct mid_q_entry *mid)
2126 {
2127 	struct cifs_writedata *wdata = mid->callback_data;
2128 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2129 	unsigned int written;
2130 	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2131 
2132 	switch (mid->mid_state) {
2133 	case MID_RESPONSE_RECEIVED:
2134 		wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2135 		if (wdata->result != 0)
2136 			break;
2137 
2138 		written = le16_to_cpu(smb->CountHigh);
2139 		written <<= 16;
2140 		written += le16_to_cpu(smb->Count);
2141 		/*
2142 		 * Mask off high 16 bits when bytes written as returned
2143 		 * by the server is greater than bytes requested by the
2144 		 * client. OS/2 servers are known to set incorrect
2145 		 * CountHigh values.
2146 		 */
2147 		if (written > wdata->bytes)
2148 			written &= 0xFFFF;
2149 
2150 		if (written < wdata->bytes)
2151 			wdata->result = -ENOSPC;
2152 		else
2153 			wdata->bytes = written;
2154 		break;
2155 	case MID_REQUEST_SUBMITTED:
2156 	case MID_RETRY_NEEDED:
2157 		wdata->result = -EAGAIN;
2158 		break;
2159 	default:
2160 		wdata->result = -EIO;
2161 		break;
2162 	}
2163 
2164 	queue_work(cifsiod_wq, &wdata->work);
2165 	DeleteMidQEntry(mid);
2166 	cifs_add_credits(tcon->ses->server, 1);
2167 }
2168 
2169 /* cifs_async_writev - send an async write, and set up mid to handle result */
2170 int
cifs_async_writev(struct cifs_writedata * wdata)2171 cifs_async_writev(struct cifs_writedata *wdata)
2172 {
2173 	int i, rc = -EACCES;
2174 	WRITE_REQ *smb = NULL;
2175 	int wct;
2176 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2177 	struct kvec *iov = NULL;
2178 
2179 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2180 		wct = 14;
2181 	} else {
2182 		wct = 12;
2183 		if (wdata->offset >> 32 > 0) {
2184 			/* can not handle big offset for old srv */
2185 			return -EIO;
2186 		}
2187 	}
2188 
2189 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2190 	if (rc)
2191 		goto async_writev_out;
2192 
2193 	/* 1 iov per page + 1 for header */
2194 	iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2195 	if (iov == NULL) {
2196 		rc = -ENOMEM;
2197 		goto async_writev_out;
2198 	}
2199 
2200 	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2201 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2202 
2203 	smb->AndXCommand = 0xFF;	/* none */
2204 	smb->Fid = wdata->cfile->netfid;
2205 	smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2206 	if (wct == 14)
2207 		smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2208 	smb->Reserved = 0xFFFFFFFF;
2209 	smb->WriteMode = 0;
2210 	smb->Remaining = 0;
2211 
2212 	smb->DataOffset =
2213 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2214 
2215 	/* 4 for RFC1001 length + 1 for BCC */
2216 	iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2217 	iov[0].iov_base = smb;
2218 
2219 	/*
2220 	 * This function should marshal up the page array into the kvec
2221 	 * array, reserving [0] for the header. It should kmap the pages
2222 	 * and set the iov_len properly for each one. It may also set
2223 	 * wdata->bytes too.
2224 	 */
2225 	cifs_kmap_lock();
2226 	wdata->marshal_iov(iov, wdata);
2227 	cifs_kmap_unlock();
2228 
2229 	cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2230 
2231 	smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2232 	smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2233 
2234 	if (wct == 14) {
2235 		inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2236 		put_bcc(wdata->bytes + 1, &smb->hdr);
2237 	} else {
2238 		/* wct == 12 */
2239 		struct smb_com_writex_req *smbw =
2240 				(struct smb_com_writex_req *)smb;
2241 		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2242 		put_bcc(wdata->bytes + 5, &smbw->hdr);
2243 		iov[0].iov_len += 4; /* pad bigger by four bytes */
2244 	}
2245 
2246 	kref_get(&wdata->refcount);
2247 	rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2248 			     NULL, cifs_writev_callback, wdata, false);
2249 
2250 	if (rc == 0)
2251 		cifs_stats_inc(&tcon->num_writes);
2252 	else
2253 		kref_put(&wdata->refcount, cifs_writedata_release);
2254 
2255 	/* send is done, unmap pages */
2256 	for (i = 0; i < wdata->nr_pages; i++)
2257 		kunmap(wdata->pages[i]);
2258 
2259 async_writev_out:
2260 	cifs_small_buf_release(smb);
2261 	kfree(iov);
2262 	return rc;
2263 }
2264 
2265 int
CIFSSMBWrite2(const int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,struct kvec * iov,int n_vec,const int long_op)2266 CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
2267 	      unsigned int *nbytes, struct kvec *iov, int n_vec,
2268 	      const int long_op)
2269 {
2270 	int rc = -EACCES;
2271 	WRITE_REQ *pSMB = NULL;
2272 	int wct;
2273 	int smb_hdr_len;
2274 	int resp_buf_type = 0;
2275 	__u32 pid = io_parms->pid;
2276 	__u16 netfid = io_parms->netfid;
2277 	__u64 offset = io_parms->offset;
2278 	struct cifs_tcon *tcon = io_parms->tcon;
2279 	unsigned int count = io_parms->length;
2280 
2281 	*nbytes = 0;
2282 
2283 	cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2284 
2285 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2286 		wct = 14;
2287 	} else {
2288 		wct = 12;
2289 		if ((offset >> 32) > 0) {
2290 			/* can not handle big offset for old srv */
2291 			return -EIO;
2292 		}
2293 	}
2294 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2295 	if (rc)
2296 		return rc;
2297 
2298 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2299 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2300 
2301 	/* tcon and ses pointer are checked in smb_init */
2302 	if (tcon->ses->server == NULL)
2303 		return -ECONNABORTED;
2304 
2305 	pSMB->AndXCommand = 0xFF;	/* none */
2306 	pSMB->Fid = netfid;
2307 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2308 	if (wct == 14)
2309 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2310 	pSMB->Reserved = 0xFFFFFFFF;
2311 	pSMB->WriteMode = 0;
2312 	pSMB->Remaining = 0;
2313 
2314 	pSMB->DataOffset =
2315 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2316 
2317 	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2318 	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2319 	/* header + 1 byte pad */
2320 	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2321 	if (wct == 14)
2322 		inc_rfc1001_len(pSMB, count + 1);
2323 	else /* wct == 12 */
2324 		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2325 	if (wct == 14)
2326 		pSMB->ByteCount = cpu_to_le16(count + 1);
2327 	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2328 		struct smb_com_writex_req *pSMBW =
2329 				(struct smb_com_writex_req *)pSMB;
2330 		pSMBW->ByteCount = cpu_to_le16(count + 5);
2331 	}
2332 	iov[0].iov_base = pSMB;
2333 	if (wct == 14)
2334 		iov[0].iov_len = smb_hdr_len + 4;
2335 	else /* wct == 12 pad bigger by four bytes */
2336 		iov[0].iov_len = smb_hdr_len + 8;
2337 
2338 
2339 	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2340 			  long_op);
2341 	cifs_stats_inc(&tcon->num_writes);
2342 	if (rc) {
2343 		cFYI(1, "Send error Write2 = %d", rc);
2344 	} else if (resp_buf_type == 0) {
2345 		/* presumably this can not happen, but best to be safe */
2346 		rc = -EIO;
2347 	} else {
2348 		WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2349 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
2350 		*nbytes = (*nbytes) << 16;
2351 		*nbytes += le16_to_cpu(pSMBr->Count);
2352 
2353 		/*
2354 		 * Mask off high 16 bits when bytes written as returned by the
2355 		 * server is greater than bytes requested by the client. OS/2
2356 		 * servers are known to set incorrect CountHigh values.
2357 		 */
2358 		if (*nbytes > count)
2359 			*nbytes &= 0xFFFF;
2360 	}
2361 
2362 /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2363 	if (resp_buf_type == CIFS_SMALL_BUFFER)
2364 		cifs_small_buf_release(iov[0].iov_base);
2365 	else if (resp_buf_type == CIFS_LARGE_BUFFER)
2366 		cifs_buf_release(iov[0].iov_base);
2367 
2368 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2369 		since file handle passed in no longer valid */
2370 
2371 	return rc;
2372 }
2373 
cifs_lockv(const int xid,struct cifs_tcon * tcon,const __u16 netfid,const __u8 lock_type,const __u32 num_unlock,const __u32 num_lock,LOCKING_ANDX_RANGE * buf)2374 int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
2375 	       const __u8 lock_type, const __u32 num_unlock,
2376 	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2377 {
2378 	int rc = 0;
2379 	LOCK_REQ *pSMB = NULL;
2380 	struct kvec iov[2];
2381 	int resp_buf_type;
2382 	__u16 count;
2383 
2384 	cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2385 
2386 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2387 	if (rc)
2388 		return rc;
2389 
2390 	pSMB->Timeout = 0;
2391 	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2392 	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2393 	pSMB->LockType = lock_type;
2394 	pSMB->AndXCommand = 0xFF; /* none */
2395 	pSMB->Fid = netfid; /* netfid stays le */
2396 
2397 	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2398 	inc_rfc1001_len(pSMB, count);
2399 	pSMB->ByteCount = cpu_to_le16(count);
2400 
2401 	iov[0].iov_base = (char *)pSMB;
2402 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2403 			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2404 	iov[1].iov_base = (char *)buf;
2405 	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2406 
2407 	cifs_stats_inc(&tcon->num_locks);
2408 	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2409 	if (rc)
2410 		cFYI(1, "Send error in cifs_lockv = %d", rc);
2411 
2412 	return rc;
2413 }
2414 
2415 int
CIFSSMBLock(const int xid,struct cifs_tcon * tcon,const __u16 smb_file_id,const __u32 netpid,const __u64 len,const __u64 offset,const __u32 numUnlock,const __u32 numLock,const __u8 lockType,const bool waitFlag,const __u8 oplock_level)2416 CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
2417 	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2418 	    const __u64 offset, const __u32 numUnlock,
2419 	    const __u32 numLock, const __u8 lockType,
2420 	    const bool waitFlag, const __u8 oplock_level)
2421 {
2422 	int rc = 0;
2423 	LOCK_REQ *pSMB = NULL;
2424 /*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2425 	int bytes_returned;
2426 	int timeout = 0;
2427 	__u16 count;
2428 
2429 	cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2430 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2431 
2432 	if (rc)
2433 		return rc;
2434 
2435 	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2436 		timeout = CIFS_ASYNC_OP; /* no response expected */
2437 		pSMB->Timeout = 0;
2438 	} else if (waitFlag) {
2439 		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2440 		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2441 	} else {
2442 		pSMB->Timeout = 0;
2443 	}
2444 
2445 	pSMB->NumberOfLocks = cpu_to_le16(numLock);
2446 	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2447 	pSMB->LockType = lockType;
2448 	pSMB->OplockLevel = oplock_level;
2449 	pSMB->AndXCommand = 0xFF;	/* none */
2450 	pSMB->Fid = smb_file_id; /* netfid stays le */
2451 
2452 	if ((numLock != 0) || (numUnlock != 0)) {
2453 		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2454 		/* BB where to store pid high? */
2455 		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2456 		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2457 		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2458 		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2459 		count = sizeof(LOCKING_ANDX_RANGE);
2460 	} else {
2461 		/* oplock break */
2462 		count = 0;
2463 	}
2464 	inc_rfc1001_len(pSMB, count);
2465 	pSMB->ByteCount = cpu_to_le16(count);
2466 
2467 	if (waitFlag) {
2468 		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2469 			(struct smb_hdr *) pSMB, &bytes_returned);
2470 		cifs_small_buf_release(pSMB);
2471 	} else {
2472 		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, timeout);
2473 		/* SMB buffer freed by function above */
2474 	}
2475 	cifs_stats_inc(&tcon->num_locks);
2476 	if (rc)
2477 		cFYI(1, "Send error in Lock = %d", rc);
2478 
2479 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2480 	since file handle passed in no longer valid */
2481 	return rc;
2482 }
2483 
2484 int
CIFSSMBPosixLock(const int xid,struct cifs_tcon * tcon,const __u16 smb_file_id,const __u32 netpid,const int get_flag,const __u64 len,struct file_lock * pLockData,const __u16 lock_type,const bool waitFlag)2485 CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
2486 		const __u16 smb_file_id, const __u32 netpid, const int get_flag,
2487 		const __u64 len, struct file_lock *pLockData,
2488 		const __u16 lock_type, const bool waitFlag)
2489 {
2490 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2491 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2492 	struct cifs_posix_lock *parm_data;
2493 	int rc = 0;
2494 	int timeout = 0;
2495 	int bytes_returned = 0;
2496 	int resp_buf_type = 0;
2497 	__u16 params, param_offset, offset, byte_count, count;
2498 	struct kvec iov[1];
2499 
2500 	cFYI(1, "Posix Lock");
2501 
2502 	if (pLockData == NULL)
2503 		return -EINVAL;
2504 
2505 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2506 
2507 	if (rc)
2508 		return rc;
2509 
2510 	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2511 
2512 	params = 6;
2513 	pSMB->MaxSetupCount = 0;
2514 	pSMB->Reserved = 0;
2515 	pSMB->Flags = 0;
2516 	pSMB->Reserved2 = 0;
2517 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2518 	offset = param_offset + params;
2519 
2520 	count = sizeof(struct cifs_posix_lock);
2521 	pSMB->MaxParameterCount = cpu_to_le16(2);
2522 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2523 	pSMB->SetupCount = 1;
2524 	pSMB->Reserved3 = 0;
2525 	if (get_flag)
2526 		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2527 	else
2528 		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2529 	byte_count = 3 /* pad */  + params + count;
2530 	pSMB->DataCount = cpu_to_le16(count);
2531 	pSMB->ParameterCount = cpu_to_le16(params);
2532 	pSMB->TotalDataCount = pSMB->DataCount;
2533 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2534 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2535 	parm_data = (struct cifs_posix_lock *)
2536 			(((char *) &pSMB->hdr.Protocol) + offset);
2537 
2538 	parm_data->lock_type = cpu_to_le16(lock_type);
2539 	if (waitFlag) {
2540 		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2541 		parm_data->lock_flags = cpu_to_le16(1);
2542 		pSMB->Timeout = cpu_to_le32(-1);
2543 	} else
2544 		pSMB->Timeout = 0;
2545 
2546 	parm_data->pid = cpu_to_le32(netpid);
2547 	parm_data->start = cpu_to_le64(pLockData->fl_start);
2548 	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2549 
2550 	pSMB->DataOffset = cpu_to_le16(offset);
2551 	pSMB->Fid = smb_file_id;
2552 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2553 	pSMB->Reserved4 = 0;
2554 	inc_rfc1001_len(pSMB, byte_count);
2555 	pSMB->ByteCount = cpu_to_le16(byte_count);
2556 	if (waitFlag) {
2557 		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2558 			(struct smb_hdr *) pSMBr, &bytes_returned);
2559 	} else {
2560 		iov[0].iov_base = (char *)pSMB;
2561 		iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2562 		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2563 				&resp_buf_type, timeout);
2564 		pSMB = NULL; /* request buf already freed by SendReceive2. Do
2565 				not try to free it twice below on exit */
2566 		pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2567 	}
2568 
2569 	if (rc) {
2570 		cFYI(1, "Send error in Posix Lock = %d", rc);
2571 	} else if (get_flag) {
2572 		/* lock structure can be returned on get */
2573 		__u16 data_offset;
2574 		__u16 data_count;
2575 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2576 
2577 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2578 			rc = -EIO;      /* bad smb */
2579 			goto plk_err_exit;
2580 		}
2581 		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2582 		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2583 		if (data_count < sizeof(struct cifs_posix_lock)) {
2584 			rc = -EIO;
2585 			goto plk_err_exit;
2586 		}
2587 		parm_data = (struct cifs_posix_lock *)
2588 			((char *)&pSMBr->hdr.Protocol + data_offset);
2589 		if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2590 			pLockData->fl_type = F_UNLCK;
2591 		else {
2592 			if (parm_data->lock_type ==
2593 					__constant_cpu_to_le16(CIFS_RDLCK))
2594 				pLockData->fl_type = F_RDLCK;
2595 			else if (parm_data->lock_type ==
2596 					__constant_cpu_to_le16(CIFS_WRLCK))
2597 				pLockData->fl_type = F_WRLCK;
2598 
2599 			pLockData->fl_start = le64_to_cpu(parm_data->start);
2600 			pLockData->fl_end = pLockData->fl_start +
2601 					le64_to_cpu(parm_data->length) - 1;
2602 			pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2603 		}
2604 	}
2605 
2606 plk_err_exit:
2607 	if (pSMB)
2608 		cifs_small_buf_release(pSMB);
2609 
2610 	if (resp_buf_type == CIFS_SMALL_BUFFER)
2611 		cifs_small_buf_release(iov[0].iov_base);
2612 	else if (resp_buf_type == CIFS_LARGE_BUFFER)
2613 		cifs_buf_release(iov[0].iov_base);
2614 
2615 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2616 	   since file handle passed in no longer valid */
2617 
2618 	return rc;
2619 }
2620 
2621 
2622 int
CIFSSMBClose(const int xid,struct cifs_tcon * tcon,int smb_file_id)2623 CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2624 {
2625 	int rc = 0;
2626 	CLOSE_REQ *pSMB = NULL;
2627 	cFYI(1, "In CIFSSMBClose");
2628 
2629 /* do not retry on dead session on close */
2630 	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2631 	if (rc == -EAGAIN)
2632 		return 0;
2633 	if (rc)
2634 		return rc;
2635 
2636 	pSMB->FileID = (__u16) smb_file_id;
2637 	pSMB->LastWriteTime = 0xFFFFFFFF;
2638 	pSMB->ByteCount = 0;
2639 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2640 	cifs_stats_inc(&tcon->num_closes);
2641 	if (rc) {
2642 		if (rc != -EINTR) {
2643 			/* EINTR is expected when user ctl-c to kill app */
2644 			cERROR(1, "Send error in Close = %d", rc);
2645 		}
2646 	}
2647 
2648 	/* Since session is dead, file will be closed on server already */
2649 	if (rc == -EAGAIN)
2650 		rc = 0;
2651 
2652 	return rc;
2653 }
2654 
2655 int
CIFSSMBFlush(const int xid,struct cifs_tcon * tcon,int smb_file_id)2656 CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2657 {
2658 	int rc = 0;
2659 	FLUSH_REQ *pSMB = NULL;
2660 	cFYI(1, "In CIFSSMBFlush");
2661 
2662 	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2663 	if (rc)
2664 		return rc;
2665 
2666 	pSMB->FileID = (__u16) smb_file_id;
2667 	pSMB->ByteCount = 0;
2668 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2669 	cifs_stats_inc(&tcon->num_flushes);
2670 	if (rc)
2671 		cERROR(1, "Send error in Flush = %d", rc);
2672 
2673 	return rc;
2674 }
2675 
2676 int
CIFSSMBRename(const int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2677 CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
2678 	      const char *fromName, const char *toName,
2679 	      const struct nls_table *nls_codepage, int remap)
2680 {
2681 	int rc = 0;
2682 	RENAME_REQ *pSMB = NULL;
2683 	RENAME_RSP *pSMBr = NULL;
2684 	int bytes_returned;
2685 	int name_len, name_len2;
2686 	__u16 count;
2687 
2688 	cFYI(1, "In CIFSSMBRename");
2689 renameRetry:
2690 	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2691 		      (void **) &pSMBr);
2692 	if (rc)
2693 		return rc;
2694 
2695 	pSMB->BufferFormat = 0x04;
2696 	pSMB->SearchAttributes =
2697 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2698 			ATTR_DIRECTORY);
2699 
2700 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2701 		name_len =
2702 		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2703 				       PATH_MAX, nls_codepage, remap);
2704 		name_len++;	/* trailing null */
2705 		name_len *= 2;
2706 		pSMB->OldFileName[name_len] = 0x04;	/* pad */
2707 	/* protocol requires ASCII signature byte on Unicode string */
2708 		pSMB->OldFileName[name_len + 1] = 0x00;
2709 		name_len2 =
2710 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2711 				       toName, PATH_MAX, nls_codepage, remap);
2712 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2713 		name_len2 *= 2;	/* convert to bytes */
2714 	} else {	/* BB improve the check for buffer overruns BB */
2715 		name_len = strnlen(fromName, PATH_MAX);
2716 		name_len++;	/* trailing null */
2717 		strncpy(pSMB->OldFileName, fromName, name_len);
2718 		name_len2 = strnlen(toName, PATH_MAX);
2719 		name_len2++;	/* trailing null */
2720 		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2721 		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2722 		name_len2++;	/* trailing null */
2723 		name_len2++;	/* signature byte */
2724 	}
2725 
2726 	count = 1 /* 1st signature byte */  + name_len + name_len2;
2727 	inc_rfc1001_len(pSMB, count);
2728 	pSMB->ByteCount = cpu_to_le16(count);
2729 
2730 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2731 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2732 	cifs_stats_inc(&tcon->num_renames);
2733 	if (rc)
2734 		cFYI(1, "Send error in rename = %d", rc);
2735 
2736 	cifs_buf_release(pSMB);
2737 
2738 	if (rc == -EAGAIN)
2739 		goto renameRetry;
2740 
2741 	return rc;
2742 }
2743 
CIFSSMBRenameOpenFile(const int xid,struct cifs_tcon * pTcon,int netfid,const char * target_name,const struct nls_table * nls_codepage,int remap)2744 int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
2745 		int netfid, const char *target_name,
2746 		const struct nls_table *nls_codepage, int remap)
2747 {
2748 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2749 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2750 	struct set_file_rename *rename_info;
2751 	char *data_offset;
2752 	char dummy_string[30];
2753 	int rc = 0;
2754 	int bytes_returned = 0;
2755 	int len_of_str;
2756 	__u16 params, param_offset, offset, count, byte_count;
2757 
2758 	cFYI(1, "Rename to File by handle");
2759 	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2760 			(void **) &pSMBr);
2761 	if (rc)
2762 		return rc;
2763 
2764 	params = 6;
2765 	pSMB->MaxSetupCount = 0;
2766 	pSMB->Reserved = 0;
2767 	pSMB->Flags = 0;
2768 	pSMB->Timeout = 0;
2769 	pSMB->Reserved2 = 0;
2770 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2771 	offset = param_offset + params;
2772 
2773 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2774 	rename_info = (struct set_file_rename *) data_offset;
2775 	pSMB->MaxParameterCount = cpu_to_le16(2);
2776 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2777 	pSMB->SetupCount = 1;
2778 	pSMB->Reserved3 = 0;
2779 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2780 	byte_count = 3 /* pad */  + params;
2781 	pSMB->ParameterCount = cpu_to_le16(params);
2782 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2783 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2784 	pSMB->DataOffset = cpu_to_le16(offset);
2785 	/* construct random name ".cifs_tmp<inodenum><mid>" */
2786 	rename_info->overwrite = cpu_to_le32(1);
2787 	rename_info->root_fid  = 0;
2788 	/* unicode only call */
2789 	if (target_name == NULL) {
2790 		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2791 		len_of_str =
2792 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2793 					dummy_string, 24, nls_codepage, remap);
2794 	} else {
2795 		len_of_str =
2796 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2797 					target_name, PATH_MAX, nls_codepage,
2798 					remap);
2799 	}
2800 	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2801 	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2802 	byte_count += count;
2803 	pSMB->DataCount = cpu_to_le16(count);
2804 	pSMB->TotalDataCount = pSMB->DataCount;
2805 	pSMB->Fid = netfid;
2806 	pSMB->InformationLevel =
2807 		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2808 	pSMB->Reserved4 = 0;
2809 	inc_rfc1001_len(pSMB, byte_count);
2810 	pSMB->ByteCount = cpu_to_le16(byte_count);
2811 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2812 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2813 	cifs_stats_inc(&pTcon->num_t2renames);
2814 	if (rc)
2815 		cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2816 
2817 	cifs_buf_release(pSMB);
2818 
2819 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2820 		since file handle passed in no longer valid */
2821 
2822 	return rc;
2823 }
2824 
2825 int
CIFSSMBCopy(const int xid,struct cifs_tcon * tcon,const char * fromName,const __u16 target_tid,const char * toName,const int flags,const struct nls_table * nls_codepage,int remap)2826 CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
2827 	    const __u16 target_tid, const char *toName, const int flags,
2828 	    const struct nls_table *nls_codepage, int remap)
2829 {
2830 	int rc = 0;
2831 	COPY_REQ *pSMB = NULL;
2832 	COPY_RSP *pSMBr = NULL;
2833 	int bytes_returned;
2834 	int name_len, name_len2;
2835 	__u16 count;
2836 
2837 	cFYI(1, "In CIFSSMBCopy");
2838 copyRetry:
2839 	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2840 			(void **) &pSMBr);
2841 	if (rc)
2842 		return rc;
2843 
2844 	pSMB->BufferFormat = 0x04;
2845 	pSMB->Tid2 = target_tid;
2846 
2847 	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2848 
2849 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2850 		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2851 					      fromName, PATH_MAX, nls_codepage,
2852 					      remap);
2853 		name_len++;     /* trailing null */
2854 		name_len *= 2;
2855 		pSMB->OldFileName[name_len] = 0x04;     /* pad */
2856 		/* protocol requires ASCII signature byte on Unicode string */
2857 		pSMB->OldFileName[name_len + 1] = 0x00;
2858 		name_len2 =
2859 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2860 				       toName, PATH_MAX, nls_codepage, remap);
2861 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2862 		name_len2 *= 2; /* convert to bytes */
2863 	} else { 	/* BB improve the check for buffer overruns BB */
2864 		name_len = strnlen(fromName, PATH_MAX);
2865 		name_len++;     /* trailing null */
2866 		strncpy(pSMB->OldFileName, fromName, name_len);
2867 		name_len2 = strnlen(toName, PATH_MAX);
2868 		name_len2++;    /* trailing null */
2869 		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2870 		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2871 		name_len2++;    /* trailing null */
2872 		name_len2++;    /* signature byte */
2873 	}
2874 
2875 	count = 1 /* 1st signature byte */  + name_len + name_len2;
2876 	inc_rfc1001_len(pSMB, count);
2877 	pSMB->ByteCount = cpu_to_le16(count);
2878 
2879 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2880 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
2881 	if (rc) {
2882 		cFYI(1, "Send error in copy = %d with %d files copied",
2883 			rc, le16_to_cpu(pSMBr->CopyCount));
2884 	}
2885 	cifs_buf_release(pSMB);
2886 
2887 	if (rc == -EAGAIN)
2888 		goto copyRetry;
2889 
2890 	return rc;
2891 }
2892 
2893 int
CIFSUnixCreateSymLink(const int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage)2894 CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
2895 		      const char *fromName, const char *toName,
2896 		      const struct nls_table *nls_codepage)
2897 {
2898 	TRANSACTION2_SPI_REQ *pSMB = NULL;
2899 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2900 	char *data_offset;
2901 	int name_len;
2902 	int name_len_target;
2903 	int rc = 0;
2904 	int bytes_returned = 0;
2905 	__u16 params, param_offset, offset, byte_count;
2906 
2907 	cFYI(1, "In Symlink Unix style");
2908 createSymLinkRetry:
2909 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2910 		      (void **) &pSMBr);
2911 	if (rc)
2912 		return rc;
2913 
2914 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2915 		name_len =
2916 		    cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2917 				    /* find define for this maxpathcomponent */
2918 				    PATH_MAX, nls_codepage);
2919 		name_len++;	/* trailing null */
2920 		name_len *= 2;
2921 
2922 	} else {	/* BB improve the check for buffer overruns BB */
2923 		name_len = strnlen(fromName, PATH_MAX);
2924 		name_len++;	/* trailing null */
2925 		strncpy(pSMB->FileName, fromName, name_len);
2926 	}
2927 	params = 6 + name_len;
2928 	pSMB->MaxSetupCount = 0;
2929 	pSMB->Reserved = 0;
2930 	pSMB->Flags = 0;
2931 	pSMB->Timeout = 0;
2932 	pSMB->Reserved2 = 0;
2933 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
2934 				InformationLevel) - 4;
2935 	offset = param_offset + params;
2936 
2937 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2938 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2939 		name_len_target =
2940 		    cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2941 				    /* find define for this maxpathcomponent */
2942 				    , nls_codepage);
2943 		name_len_target++;	/* trailing null */
2944 		name_len_target *= 2;
2945 	} else {	/* BB improve the check for buffer overruns BB */
2946 		name_len_target = strnlen(toName, PATH_MAX);
2947 		name_len_target++;	/* trailing null */
2948 		strncpy(data_offset, toName, name_len_target);
2949 	}
2950 
2951 	pSMB->MaxParameterCount = cpu_to_le16(2);
2952 	/* BB find exact max on data count below from sess */
2953 	pSMB->MaxDataCount = cpu_to_le16(1000);
2954 	pSMB->SetupCount = 1;
2955 	pSMB->Reserved3 = 0;
2956 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2957 	byte_count = 3 /* pad */  + params + name_len_target;
2958 	pSMB->DataCount = cpu_to_le16(name_len_target);
2959 	pSMB->ParameterCount = cpu_to_le16(params);
2960 	pSMB->TotalDataCount = pSMB->DataCount;
2961 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2962 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2963 	pSMB->DataOffset = cpu_to_le16(offset);
2964 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2965 	pSMB->Reserved4 = 0;
2966 	inc_rfc1001_len(pSMB, byte_count);
2967 	pSMB->ByteCount = cpu_to_le16(byte_count);
2968 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2969 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2970 	cifs_stats_inc(&tcon->num_symlinks);
2971 	if (rc)
2972 		cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2973 
2974 	cifs_buf_release(pSMB);
2975 
2976 	if (rc == -EAGAIN)
2977 		goto createSymLinkRetry;
2978 
2979 	return rc;
2980 }
2981 
2982 int
CIFSUnixCreateHardLink(const int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2983 CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
2984 		       const char *fromName, const char *toName,
2985 		       const struct nls_table *nls_codepage, int remap)
2986 {
2987 	TRANSACTION2_SPI_REQ *pSMB = NULL;
2988 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2989 	char *data_offset;
2990 	int name_len;
2991 	int name_len_target;
2992 	int rc = 0;
2993 	int bytes_returned = 0;
2994 	__u16 params, param_offset, offset, byte_count;
2995 
2996 	cFYI(1, "In Create Hard link Unix style");
2997 createHardLinkRetry:
2998 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2999 		      (void **) &pSMBr);
3000 	if (rc)
3001 		return rc;
3002 
3003 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3004 		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
3005 					      PATH_MAX, nls_codepage, remap);
3006 		name_len++;	/* trailing null */
3007 		name_len *= 2;
3008 
3009 	} else {	/* BB improve the check for buffer overruns BB */
3010 		name_len = strnlen(toName, PATH_MAX);
3011 		name_len++;	/* trailing null */
3012 		strncpy(pSMB->FileName, toName, name_len);
3013 	}
3014 	params = 6 + name_len;
3015 	pSMB->MaxSetupCount = 0;
3016 	pSMB->Reserved = 0;
3017 	pSMB->Flags = 0;
3018 	pSMB->Timeout = 0;
3019 	pSMB->Reserved2 = 0;
3020 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3021 				InformationLevel) - 4;
3022 	offset = param_offset + params;
3023 
3024 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3025 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3026 		name_len_target =
3027 		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
3028 				       PATH_MAX, nls_codepage, remap);
3029 		name_len_target++;	/* trailing null */
3030 		name_len_target *= 2;
3031 	} else {	/* BB improve the check for buffer overruns BB */
3032 		name_len_target = strnlen(fromName, PATH_MAX);
3033 		name_len_target++;	/* trailing null */
3034 		strncpy(data_offset, fromName, name_len_target);
3035 	}
3036 
3037 	pSMB->MaxParameterCount = cpu_to_le16(2);
3038 	/* BB find exact max on data count below from sess*/
3039 	pSMB->MaxDataCount = cpu_to_le16(1000);
3040 	pSMB->SetupCount = 1;
3041 	pSMB->Reserved3 = 0;
3042 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3043 	byte_count = 3 /* pad */  + params + name_len_target;
3044 	pSMB->ParameterCount = cpu_to_le16(params);
3045 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3046 	pSMB->DataCount = cpu_to_le16(name_len_target);
3047 	pSMB->TotalDataCount = pSMB->DataCount;
3048 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3049 	pSMB->DataOffset = cpu_to_le16(offset);
3050 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3051 	pSMB->Reserved4 = 0;
3052 	inc_rfc1001_len(pSMB, byte_count);
3053 	pSMB->ByteCount = cpu_to_le16(byte_count);
3054 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3055 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3056 	cifs_stats_inc(&tcon->num_hardlinks);
3057 	if (rc)
3058 		cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
3059 
3060 	cifs_buf_release(pSMB);
3061 	if (rc == -EAGAIN)
3062 		goto createHardLinkRetry;
3063 
3064 	return rc;
3065 }
3066 
3067 int
CIFSCreateHardLink(const int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)3068 CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
3069 		   const char *fromName, const char *toName,
3070 		   const struct nls_table *nls_codepage, int remap)
3071 {
3072 	int rc = 0;
3073 	NT_RENAME_REQ *pSMB = NULL;
3074 	RENAME_RSP *pSMBr = NULL;
3075 	int bytes_returned;
3076 	int name_len, name_len2;
3077 	__u16 count;
3078 
3079 	cFYI(1, "In CIFSCreateHardLink");
3080 winCreateHardLinkRetry:
3081 
3082 	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3083 		      (void **) &pSMBr);
3084 	if (rc)
3085 		return rc;
3086 
3087 	pSMB->SearchAttributes =
3088 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3089 			ATTR_DIRECTORY);
3090 	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3091 	pSMB->ClusterCount = 0;
3092 
3093 	pSMB->BufferFormat = 0x04;
3094 
3095 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3096 		name_len =
3097 		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
3098 				       PATH_MAX, nls_codepage, remap);
3099 		name_len++;	/* trailing null */
3100 		name_len *= 2;
3101 
3102 		/* protocol specifies ASCII buffer format (0x04) for unicode */
3103 		pSMB->OldFileName[name_len] = 0x04;
3104 		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3105 		name_len2 =
3106 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3107 				       toName, PATH_MAX, nls_codepage, remap);
3108 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
3109 		name_len2 *= 2;	/* convert to bytes */
3110 	} else {	/* BB improve the check for buffer overruns BB */
3111 		name_len = strnlen(fromName, PATH_MAX);
3112 		name_len++;	/* trailing null */
3113 		strncpy(pSMB->OldFileName, fromName, name_len);
3114 		name_len2 = strnlen(toName, PATH_MAX);
3115 		name_len2++;	/* trailing null */
3116 		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
3117 		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
3118 		name_len2++;	/* trailing null */
3119 		name_len2++;	/* signature byte */
3120 	}
3121 
3122 	count = 1 /* string type byte */  + name_len + name_len2;
3123 	inc_rfc1001_len(pSMB, count);
3124 	pSMB->ByteCount = cpu_to_le16(count);
3125 
3126 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3127 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3128 	cifs_stats_inc(&tcon->num_hardlinks);
3129 	if (rc)
3130 		cFYI(1, "Send error in hard link (NT rename) = %d", rc);
3131 
3132 	cifs_buf_release(pSMB);
3133 	if (rc == -EAGAIN)
3134 		goto winCreateHardLinkRetry;
3135 
3136 	return rc;
3137 }
3138 
3139 int
CIFSSMBUnixQuerySymLink(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char ** symlinkinfo,const struct nls_table * nls_codepage)3140 CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
3141 			const unsigned char *searchName, char **symlinkinfo,
3142 			const struct nls_table *nls_codepage)
3143 {
3144 /* SMB_QUERY_FILE_UNIX_LINK */
3145 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3146 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3147 	int rc = 0;
3148 	int bytes_returned;
3149 	int name_len;
3150 	__u16 params, byte_count;
3151 	char *data_start;
3152 
3153 	cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3154 
3155 querySymLinkRetry:
3156 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3157 		      (void **) &pSMBr);
3158 	if (rc)
3159 		return rc;
3160 
3161 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3162 		name_len =
3163 			cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3164 					PATH_MAX, nls_codepage);
3165 		name_len++;	/* trailing null */
3166 		name_len *= 2;
3167 	} else {	/* BB improve the check for buffer overruns BB */
3168 		name_len = strnlen(searchName, PATH_MAX);
3169 		name_len++;	/* trailing null */
3170 		strncpy(pSMB->FileName, searchName, name_len);
3171 	}
3172 
3173 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3174 	pSMB->TotalDataCount = 0;
3175 	pSMB->MaxParameterCount = cpu_to_le16(2);
3176 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3177 	pSMB->MaxSetupCount = 0;
3178 	pSMB->Reserved = 0;
3179 	pSMB->Flags = 0;
3180 	pSMB->Timeout = 0;
3181 	pSMB->Reserved2 = 0;
3182 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
3183 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3184 	pSMB->DataCount = 0;
3185 	pSMB->DataOffset = 0;
3186 	pSMB->SetupCount = 1;
3187 	pSMB->Reserved3 = 0;
3188 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3189 	byte_count = params + 1 /* pad */ ;
3190 	pSMB->TotalParameterCount = cpu_to_le16(params);
3191 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3192 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3193 	pSMB->Reserved4 = 0;
3194 	inc_rfc1001_len(pSMB, byte_count);
3195 	pSMB->ByteCount = cpu_to_le16(byte_count);
3196 
3197 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3198 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3199 	if (rc) {
3200 		cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3201 	} else {
3202 		/* decode response */
3203 
3204 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3205 		/* BB also check enough total bytes returned */
3206 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3207 			rc = -EIO;
3208 		else {
3209 			bool is_unicode;
3210 			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3211 
3212 			data_start = ((char *) &pSMBr->hdr.Protocol) +
3213 					   le16_to_cpu(pSMBr->t2.DataOffset);
3214 
3215 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3216 				is_unicode = true;
3217 			else
3218 				is_unicode = false;
3219 
3220 			/* BB FIXME investigate remapping reserved chars here */
3221 			*symlinkinfo = cifs_strndup_from_utf16(data_start,
3222 					count, is_unicode, nls_codepage);
3223 			if (!*symlinkinfo)
3224 				rc = -ENOMEM;
3225 		}
3226 	}
3227 	cifs_buf_release(pSMB);
3228 	if (rc == -EAGAIN)
3229 		goto querySymLinkRetry;
3230 	return rc;
3231 }
3232 
3233 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3234 /*
3235  *	Recent Windows versions now create symlinks more frequently
3236  *	and they use the "reparse point" mechanism below.  We can of course
3237  *	do symlinks nicely to Samba and other servers which support the
3238  *	CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3239  *	"MF" symlinks optionally, but for recent Windows we really need to
3240  *	reenable the code below and fix the cifs_symlink callers to handle this.
3241  *	In the interim this code has been moved to its own config option so
3242  *	it is not compiled in by default until callers fixed up and more tested.
3243  */
3244 int
CIFSSMBQueryReparseLinkInfo(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char * symlinkinfo,const int buflen,__u16 fid,const struct nls_table * nls_codepage)3245 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
3246 			const unsigned char *searchName,
3247 			char *symlinkinfo, const int buflen, __u16 fid,
3248 			const struct nls_table *nls_codepage)
3249 {
3250 	int rc = 0;
3251 	int bytes_returned;
3252 	struct smb_com_transaction_ioctl_req *pSMB;
3253 	struct smb_com_transaction_ioctl_rsp *pSMBr;
3254 
3255 	cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3256 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3257 		      (void **) &pSMBr);
3258 	if (rc)
3259 		return rc;
3260 
3261 	pSMB->TotalParameterCount = 0 ;
3262 	pSMB->TotalDataCount = 0;
3263 	pSMB->MaxParameterCount = cpu_to_le32(2);
3264 	/* BB find exact data count max from sess structure BB */
3265 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3266 	pSMB->MaxSetupCount = 4;
3267 	pSMB->Reserved = 0;
3268 	pSMB->ParameterOffset = 0;
3269 	pSMB->DataCount = 0;
3270 	pSMB->DataOffset = 0;
3271 	pSMB->SetupCount = 4;
3272 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3273 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3274 	pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3275 	pSMB->IsFsctl = 1; /* FSCTL */
3276 	pSMB->IsRootFlag = 0;
3277 	pSMB->Fid = fid; /* file handle always le */
3278 	pSMB->ByteCount = 0;
3279 
3280 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3281 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3282 	if (rc) {
3283 		cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3284 	} else {		/* decode response */
3285 		__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3286 		__u32 data_count = le32_to_cpu(pSMBr->DataCount);
3287 		if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3288 			/* BB also check enough total bytes returned */
3289 			rc = -EIO;	/* bad smb */
3290 			goto qreparse_out;
3291 		}
3292 		if (data_count && (data_count < 2048)) {
3293 			char *end_of_smb = 2 /* sizeof byte count */ +
3294 			       get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3295 
3296 			struct reparse_data *reparse_buf =
3297 						(struct reparse_data *)
3298 						((char *)&pSMBr->hdr.Protocol
3299 								 + data_offset);
3300 			if ((char *)reparse_buf >= end_of_smb) {
3301 				rc = -EIO;
3302 				goto qreparse_out;
3303 			}
3304 			if ((reparse_buf->LinkNamesBuf +
3305 				reparse_buf->TargetNameOffset +
3306 				reparse_buf->TargetNameLen) > end_of_smb) {
3307 				cFYI(1, "reparse buf beyond SMB");
3308 				rc = -EIO;
3309 				goto qreparse_out;
3310 			}
3311 
3312 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3313 				cifs_from_ucs2(symlinkinfo, (__le16 *)
3314 						(reparse_buf->LinkNamesBuf +
3315 						reparse_buf->TargetNameOffset),
3316 						buflen,
3317 						reparse_buf->TargetNameLen,
3318 						nls_codepage, 0);
3319 			} else { /* ASCII names */
3320 				strncpy(symlinkinfo,
3321 					reparse_buf->LinkNamesBuf +
3322 					reparse_buf->TargetNameOffset,
3323 					min_t(const int, buflen,
3324 					   reparse_buf->TargetNameLen));
3325 			}
3326 		} else {
3327 			rc = -EIO;
3328 			cFYI(1, "Invalid return data count on "
3329 				 "get reparse info ioctl");
3330 		}
3331 		symlinkinfo[buflen] = 0; /* just in case so the caller
3332 					does not go off the end of the buffer */
3333 		cFYI(1, "readlink result - %s", symlinkinfo);
3334 	}
3335 
3336 qreparse_out:
3337 	cifs_buf_release(pSMB);
3338 
3339 	/* Note: On -EAGAIN error only caller can retry on handle based calls
3340 		since file handle passed in no longer valid */
3341 
3342 	return rc;
3343 }
3344 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3345 
3346 #ifdef CONFIG_CIFS_POSIX
3347 
3348 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
cifs_convert_ace(posix_acl_xattr_entry * ace,struct cifs_posix_ace * cifs_ace)3349 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3350 			     struct cifs_posix_ace *cifs_ace)
3351 {
3352 	/* u8 cifs fields do not need le conversion */
3353 	ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3354 	ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3355 	ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3356 	/* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3357 
3358 	return;
3359 }
3360 
3361 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
cifs_copy_posix_acl(char * trgt,char * src,const int buflen,const int acl_type,const int size_of_data_area)3362 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3363 			       const int acl_type, const int size_of_data_area)
3364 {
3365 	int size =  0;
3366 	int i;
3367 	__u16 count;
3368 	struct cifs_posix_ace *pACE;
3369 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3370 	posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3371 
3372 	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3373 		return -EOPNOTSUPP;
3374 
3375 	if (acl_type & ACL_TYPE_ACCESS) {
3376 		count = le16_to_cpu(cifs_acl->access_entry_count);
3377 		pACE = &cifs_acl->ace_array[0];
3378 		size = sizeof(struct cifs_posix_acl);
3379 		size += sizeof(struct cifs_posix_ace) * count;
3380 		/* check if we would go beyond end of SMB */
3381 		if (size_of_data_area < size) {
3382 			cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3383 				size_of_data_area, size);
3384 			return -EINVAL;
3385 		}
3386 	} else if (acl_type & ACL_TYPE_DEFAULT) {
3387 		count = le16_to_cpu(cifs_acl->access_entry_count);
3388 		size = sizeof(struct cifs_posix_acl);
3389 		size += sizeof(struct cifs_posix_ace) * count;
3390 /* skip past access ACEs to get to default ACEs */
3391 		pACE = &cifs_acl->ace_array[count];
3392 		count = le16_to_cpu(cifs_acl->default_entry_count);
3393 		size += sizeof(struct cifs_posix_ace) * count;
3394 		/* check if we would go beyond end of SMB */
3395 		if (size_of_data_area < size)
3396 			return -EINVAL;
3397 	} else {
3398 		/* illegal type */
3399 		return -EINVAL;
3400 	}
3401 
3402 	size = posix_acl_xattr_size(count);
3403 	if ((buflen == 0) || (local_acl == NULL)) {
3404 		/* used to query ACL EA size */
3405 	} else if (size > buflen) {
3406 		return -ERANGE;
3407 	} else /* buffer big enough */ {
3408 		local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3409 		for (i = 0; i < count ; i++) {
3410 			cifs_convert_ace(&local_acl->a_entries[i], pACE);
3411 			pACE++;
3412 		}
3413 	}
3414 	return size;
3415 }
3416 
convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,const posix_acl_xattr_entry * local_ace)3417 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3418 				     const posix_acl_xattr_entry *local_ace)
3419 {
3420 	__u16 rc = 0; /* 0 = ACL converted ok */
3421 
3422 	cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3423 	cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3424 	/* BB is there a better way to handle the large uid? */
3425 	if (local_ace->e_id == cpu_to_le32(-1)) {
3426 	/* Probably no need to le convert -1 on any arch but can not hurt */
3427 		cifs_ace->cifs_uid = cpu_to_le64(-1);
3428 	} else
3429 		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3430 	/*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3431 	return rc;
3432 }
3433 
3434 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,const int acl_type)3435 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3436 			       const int buflen, const int acl_type)
3437 {
3438 	__u16 rc = 0;
3439 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3440 	posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3441 	int count;
3442 	int i;
3443 
3444 	if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3445 		return 0;
3446 
3447 	count = posix_acl_xattr_count((size_t)buflen);
3448 	cFYI(1, "setting acl with %d entries from buf of length %d and "
3449 		"version of %d",
3450 		count, buflen, le32_to_cpu(local_acl->a_version));
3451 	if (le32_to_cpu(local_acl->a_version) != 2) {
3452 		cFYI(1, "unknown POSIX ACL version %d",
3453 		     le32_to_cpu(local_acl->a_version));
3454 		return 0;
3455 	}
3456 	cifs_acl->version = cpu_to_le16(1);
3457 	if (acl_type == ACL_TYPE_ACCESS)
3458 		cifs_acl->access_entry_count = cpu_to_le16(count);
3459 	else if (acl_type == ACL_TYPE_DEFAULT)
3460 		cifs_acl->default_entry_count = cpu_to_le16(count);
3461 	else {
3462 		cFYI(1, "unknown ACL type %d", acl_type);
3463 		return 0;
3464 	}
3465 	for (i = 0; i < count; i++) {
3466 		rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3467 					&local_acl->a_entries[i]);
3468 		if (rc != 0) {
3469 			/* ACE not converted */
3470 			break;
3471 		}
3472 	}
3473 	if (rc == 0) {
3474 		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3475 		rc += sizeof(struct cifs_posix_acl);
3476 		/* BB add check to make sure ACL does not overflow SMB */
3477 	}
3478 	return rc;
3479 }
3480 
3481 int
CIFSSMBGetPosixACL(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char * acl_inf,const int buflen,const int acl_type,const struct nls_table * nls_codepage,int remap)3482 CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3483 		   const unsigned char *searchName,
3484 		   char *acl_inf, const int buflen, const int acl_type,
3485 		   const struct nls_table *nls_codepage, int remap)
3486 {
3487 /* SMB_QUERY_POSIX_ACL */
3488 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3489 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3490 	int rc = 0;
3491 	int bytes_returned;
3492 	int name_len;
3493 	__u16 params, byte_count;
3494 
3495 	cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3496 
3497 queryAclRetry:
3498 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3499 		(void **) &pSMBr);
3500 	if (rc)
3501 		return rc;
3502 
3503 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3504 		name_len =
3505 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3506 					   searchName, PATH_MAX, nls_codepage,
3507 					   remap);
3508 		name_len++;     /* trailing null */
3509 		name_len *= 2;
3510 		pSMB->FileName[name_len] = 0;
3511 		pSMB->FileName[name_len+1] = 0;
3512 	} else {	/* BB improve the check for buffer overruns BB */
3513 		name_len = strnlen(searchName, PATH_MAX);
3514 		name_len++;     /* trailing null */
3515 		strncpy(pSMB->FileName, searchName, name_len);
3516 	}
3517 
3518 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3519 	pSMB->TotalDataCount = 0;
3520 	pSMB->MaxParameterCount = cpu_to_le16(2);
3521 	/* BB find exact max data count below from sess structure BB */
3522 	pSMB->MaxDataCount = cpu_to_le16(4000);
3523 	pSMB->MaxSetupCount = 0;
3524 	pSMB->Reserved = 0;
3525 	pSMB->Flags = 0;
3526 	pSMB->Timeout = 0;
3527 	pSMB->Reserved2 = 0;
3528 	pSMB->ParameterOffset = cpu_to_le16(
3529 		offsetof(struct smb_com_transaction2_qpi_req,
3530 			 InformationLevel) - 4);
3531 	pSMB->DataCount = 0;
3532 	pSMB->DataOffset = 0;
3533 	pSMB->SetupCount = 1;
3534 	pSMB->Reserved3 = 0;
3535 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3536 	byte_count = params + 1 /* pad */ ;
3537 	pSMB->TotalParameterCount = cpu_to_le16(params);
3538 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3539 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3540 	pSMB->Reserved4 = 0;
3541 	inc_rfc1001_len(pSMB, byte_count);
3542 	pSMB->ByteCount = cpu_to_le16(byte_count);
3543 
3544 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3545 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3546 	cifs_stats_inc(&tcon->num_acl_get);
3547 	if (rc) {
3548 		cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3549 	} else {
3550 		/* decode response */
3551 
3552 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3553 		/* BB also check enough total bytes returned */
3554 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3555 			rc = -EIO;      /* bad smb */
3556 		else {
3557 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3558 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3559 			rc = cifs_copy_posix_acl(acl_inf,
3560 				(char *)&pSMBr->hdr.Protocol+data_offset,
3561 				buflen, acl_type, count);
3562 		}
3563 	}
3564 	cifs_buf_release(pSMB);
3565 	if (rc == -EAGAIN)
3566 		goto queryAclRetry;
3567 	return rc;
3568 }
3569 
3570 int
CIFSSMBSetPosixACL(const int xid,struct cifs_tcon * tcon,const unsigned char * fileName,const char * local_acl,const int buflen,const int acl_type,const struct nls_table * nls_codepage,int remap)3571 CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3572 		   const unsigned char *fileName,
3573 		   const char *local_acl, const int buflen,
3574 		   const int acl_type,
3575 		   const struct nls_table *nls_codepage, int remap)
3576 {
3577 	struct smb_com_transaction2_spi_req *pSMB = NULL;
3578 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3579 	char *parm_data;
3580 	int name_len;
3581 	int rc = 0;
3582 	int bytes_returned = 0;
3583 	__u16 params, byte_count, data_count, param_offset, offset;
3584 
3585 	cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3586 setAclRetry:
3587 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3588 		      (void **) &pSMBr);
3589 	if (rc)
3590 		return rc;
3591 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3592 		name_len =
3593 			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3594 					   PATH_MAX, nls_codepage, remap);
3595 		name_len++;     /* trailing null */
3596 		name_len *= 2;
3597 	} else {	/* BB improve the check for buffer overruns BB */
3598 		name_len = strnlen(fileName, PATH_MAX);
3599 		name_len++;     /* trailing null */
3600 		strncpy(pSMB->FileName, fileName, name_len);
3601 	}
3602 	params = 6 + name_len;
3603 	pSMB->MaxParameterCount = cpu_to_le16(2);
3604 	/* BB find max SMB size from sess */
3605 	pSMB->MaxDataCount = cpu_to_le16(1000);
3606 	pSMB->MaxSetupCount = 0;
3607 	pSMB->Reserved = 0;
3608 	pSMB->Flags = 0;
3609 	pSMB->Timeout = 0;
3610 	pSMB->Reserved2 = 0;
3611 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3612 				InformationLevel) - 4;
3613 	offset = param_offset + params;
3614 	parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3615 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3616 
3617 	/* convert to on the wire format for POSIX ACL */
3618 	data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3619 
3620 	if (data_count == 0) {
3621 		rc = -EOPNOTSUPP;
3622 		goto setACLerrorExit;
3623 	}
3624 	pSMB->DataOffset = cpu_to_le16(offset);
3625 	pSMB->SetupCount = 1;
3626 	pSMB->Reserved3 = 0;
3627 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3628 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3629 	byte_count = 3 /* pad */  + params + data_count;
3630 	pSMB->DataCount = cpu_to_le16(data_count);
3631 	pSMB->TotalDataCount = pSMB->DataCount;
3632 	pSMB->ParameterCount = cpu_to_le16(params);
3633 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3634 	pSMB->Reserved4 = 0;
3635 	inc_rfc1001_len(pSMB, byte_count);
3636 	pSMB->ByteCount = cpu_to_le16(byte_count);
3637 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3638 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3639 	if (rc)
3640 		cFYI(1, "Set POSIX ACL returned %d", rc);
3641 
3642 setACLerrorExit:
3643 	cifs_buf_release(pSMB);
3644 	if (rc == -EAGAIN)
3645 		goto setAclRetry;
3646 	return rc;
3647 }
3648 
3649 /* BB fix tabs in this function FIXME BB */
3650 int
CIFSGetExtAttr(const int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3651 CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3652 	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3653 {
3654 	int rc = 0;
3655 	struct smb_t2_qfi_req *pSMB = NULL;
3656 	struct smb_t2_qfi_rsp *pSMBr = NULL;
3657 	int bytes_returned;
3658 	__u16 params, byte_count;
3659 
3660 	cFYI(1, "In GetExtAttr");
3661 	if (tcon == NULL)
3662 		return -ENODEV;
3663 
3664 GetExtAttrRetry:
3665 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3666 			(void **) &pSMBr);
3667 	if (rc)
3668 		return rc;
3669 
3670 	params = 2 /* level */ + 2 /* fid */;
3671 	pSMB->t2.TotalDataCount = 0;
3672 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3673 	/* BB find exact max data count below from sess structure BB */
3674 	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3675 	pSMB->t2.MaxSetupCount = 0;
3676 	pSMB->t2.Reserved = 0;
3677 	pSMB->t2.Flags = 0;
3678 	pSMB->t2.Timeout = 0;
3679 	pSMB->t2.Reserved2 = 0;
3680 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3681 					       Fid) - 4);
3682 	pSMB->t2.DataCount = 0;
3683 	pSMB->t2.DataOffset = 0;
3684 	pSMB->t2.SetupCount = 1;
3685 	pSMB->t2.Reserved3 = 0;
3686 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3687 	byte_count = params + 1 /* pad */ ;
3688 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3689 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3690 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3691 	pSMB->Pad = 0;
3692 	pSMB->Fid = netfid;
3693 	inc_rfc1001_len(pSMB, byte_count);
3694 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3695 
3696 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3697 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3698 	if (rc) {
3699 		cFYI(1, "error %d in GetExtAttr", rc);
3700 	} else {
3701 		/* decode response */
3702 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3703 		/* BB also check enough total bytes returned */
3704 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3705 			/* If rc should we check for EOPNOSUPP and
3706 			   disable the srvino flag? or in caller? */
3707 			rc = -EIO;      /* bad smb */
3708 		else {
3709 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3710 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3711 			struct file_chattr_info *pfinfo;
3712 			/* BB Do we need a cast or hash here ? */
3713 			if (count != 16) {
3714 				cFYI(1, "Illegal size ret in GetExtAttr");
3715 				rc = -EIO;
3716 				goto GetExtAttrOut;
3717 			}
3718 			pfinfo = (struct file_chattr_info *)
3719 				 (data_offset + (char *) &pSMBr->hdr.Protocol);
3720 			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
3721 			*pMask = le64_to_cpu(pfinfo->mask);
3722 		}
3723 	}
3724 GetExtAttrOut:
3725 	cifs_buf_release(pSMB);
3726 	if (rc == -EAGAIN)
3727 		goto GetExtAttrRetry;
3728 	return rc;
3729 }
3730 
3731 #endif /* CONFIG_POSIX */
3732 
3733 #ifdef CONFIG_CIFS_ACL
3734 /*
3735  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3736  * all NT TRANSACTS that we init here have total parm and data under about 400
3737  * bytes (to fit in small cifs buffer size), which is the case so far, it
3738  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3739  * returned setup area) and MaxParameterCount (returned parms size) must be set
3740  * by caller
3741  */
3742 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3743 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3744 		   const int parm_len, struct cifs_tcon *tcon,
3745 		   void **ret_buf)
3746 {
3747 	int rc;
3748 	__u32 temp_offset;
3749 	struct smb_com_ntransact_req *pSMB;
3750 
3751 	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3752 				(void **)&pSMB);
3753 	if (rc)
3754 		return rc;
3755 	*ret_buf = (void *)pSMB;
3756 	pSMB->Reserved = 0;
3757 	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3758 	pSMB->TotalDataCount  = 0;
3759 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3760 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3761 	pSMB->DataCount  = pSMB->TotalDataCount;
3762 	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3763 			(setup_count * 2) - 4 /* for rfc1001 length itself */;
3764 	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3765 	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3766 	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3767 	pSMB->SubCommand = cpu_to_le16(sub_command);
3768 	return 0;
3769 }
3770 
3771 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3772 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3773 		   __u32 *pparmlen, __u32 *pdatalen)
3774 {
3775 	char *end_of_smb;
3776 	__u32 data_count, data_offset, parm_count, parm_offset;
3777 	struct smb_com_ntransact_rsp *pSMBr;
3778 	u16 bcc;
3779 
3780 	*pdatalen = 0;
3781 	*pparmlen = 0;
3782 
3783 	if (buf == NULL)
3784 		return -EINVAL;
3785 
3786 	pSMBr = (struct smb_com_ntransact_rsp *)buf;
3787 
3788 	bcc = get_bcc(&pSMBr->hdr);
3789 	end_of_smb = 2 /* sizeof byte count */ + bcc +
3790 			(char *)&pSMBr->ByteCount;
3791 
3792 	data_offset = le32_to_cpu(pSMBr->DataOffset);
3793 	data_count = le32_to_cpu(pSMBr->DataCount);
3794 	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3795 	parm_count = le32_to_cpu(pSMBr->ParameterCount);
3796 
3797 	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3798 	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3799 
3800 	/* should we also check that parm and data areas do not overlap? */
3801 	if (*ppparm > end_of_smb) {
3802 		cFYI(1, "parms start after end of smb");
3803 		return -EINVAL;
3804 	} else if (parm_count + *ppparm > end_of_smb) {
3805 		cFYI(1, "parm end after end of smb");
3806 		return -EINVAL;
3807 	} else if (*ppdata > end_of_smb) {
3808 		cFYI(1, "data starts after end of smb");
3809 		return -EINVAL;
3810 	} else if (data_count + *ppdata > end_of_smb) {
3811 		cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3812 			*ppdata, data_count, (data_count + *ppdata),
3813 			end_of_smb, pSMBr);
3814 		return -EINVAL;
3815 	} else if (parm_count + data_count > bcc) {
3816 		cFYI(1, "parm count and data count larger than SMB");
3817 		return -EINVAL;
3818 	}
3819 	*pdatalen = data_count;
3820 	*pparmlen = parm_count;
3821 	return 0;
3822 }
3823 
3824 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3825 int
CIFSSMBGetCIFSACL(const int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd ** acl_inf,__u32 * pbuflen)3826 CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3827 		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3828 {
3829 	int rc = 0;
3830 	int buf_type = 0;
3831 	QUERY_SEC_DESC_REQ *pSMB;
3832 	struct kvec iov[1];
3833 
3834 	cFYI(1, "GetCifsACL");
3835 
3836 	*pbuflen = 0;
3837 	*acl_inf = NULL;
3838 
3839 	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3840 			8 /* parm len */, tcon, (void **) &pSMB);
3841 	if (rc)
3842 		return rc;
3843 
3844 	pSMB->MaxParameterCount = cpu_to_le32(4);
3845 	/* BB TEST with big acls that might need to be e.g. larger than 16K */
3846 	pSMB->MaxSetupCount = 0;
3847 	pSMB->Fid = fid; /* file handle always le */
3848 	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3849 				     CIFS_ACL_DACL);
3850 	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3851 	inc_rfc1001_len(pSMB, 11);
3852 	iov[0].iov_base = (char *)pSMB;
3853 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3854 
3855 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3856 			 0);
3857 	cifs_stats_inc(&tcon->num_acl_get);
3858 	if (rc) {
3859 		cFYI(1, "Send error in QuerySecDesc = %d", rc);
3860 	} else {                /* decode response */
3861 		__le32 *parm;
3862 		__u32 parm_len;
3863 		__u32 acl_len;
3864 		struct smb_com_ntransact_rsp *pSMBr;
3865 		char *pdata;
3866 
3867 /* validate_nttransact */
3868 		rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3869 					&pdata, &parm_len, pbuflen);
3870 		if (rc)
3871 			goto qsec_out;
3872 		pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3873 
3874 		cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3875 
3876 		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3877 			rc = -EIO;      /* bad smb */
3878 			*pbuflen = 0;
3879 			goto qsec_out;
3880 		}
3881 
3882 /* BB check that data area is minimum length and as big as acl_len */
3883 
3884 		acl_len = le32_to_cpu(*parm);
3885 		if (acl_len != *pbuflen) {
3886 			cERROR(1, "acl length %d does not match %d",
3887 				   acl_len, *pbuflen);
3888 			if (*pbuflen > acl_len)
3889 				*pbuflen = acl_len;
3890 		}
3891 
3892 		/* check if buffer is big enough for the acl
3893 		   header followed by the smallest SID */
3894 		if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3895 		    (*pbuflen >= 64 * 1024)) {
3896 			cERROR(1, "bad acl length %d", *pbuflen);
3897 			rc = -EINVAL;
3898 			*pbuflen = 0;
3899 		} else {
3900 			*acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3901 			if (*acl_inf == NULL) {
3902 				*pbuflen = 0;
3903 				rc = -ENOMEM;
3904 			}
3905 			memcpy(*acl_inf, pdata, *pbuflen);
3906 		}
3907 	}
3908 qsec_out:
3909 	if (buf_type == CIFS_SMALL_BUFFER)
3910 		cifs_small_buf_release(iov[0].iov_base);
3911 	else if (buf_type == CIFS_LARGE_BUFFER)
3912 		cifs_buf_release(iov[0].iov_base);
3913 /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3914 	return rc;
3915 }
3916 
3917 int
CIFSSMBSetCIFSACL(const int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd * pntsd,__u32 acllen,int aclflag)3918 CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3919 			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3920 {
3921 	__u16 byte_count, param_count, data_count, param_offset, data_offset;
3922 	int rc = 0;
3923 	int bytes_returned = 0;
3924 	SET_SEC_DESC_REQ *pSMB = NULL;
3925 	void *pSMBr;
3926 
3927 setCifsAclRetry:
3928 	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3929 	if (rc)
3930 		return rc;
3931 
3932 	pSMB->MaxSetupCount = 0;
3933 	pSMB->Reserved = 0;
3934 
3935 	param_count = 8;
3936 	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3937 	data_count = acllen;
3938 	data_offset = param_offset + param_count;
3939 	byte_count = 3 /* pad */  + param_count;
3940 
3941 	pSMB->DataCount = cpu_to_le32(data_count);
3942 	pSMB->TotalDataCount = pSMB->DataCount;
3943 	pSMB->MaxParameterCount = cpu_to_le32(4);
3944 	pSMB->MaxDataCount = cpu_to_le32(16384);
3945 	pSMB->ParameterCount = cpu_to_le32(param_count);
3946 	pSMB->ParameterOffset = cpu_to_le32(param_offset);
3947 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3948 	pSMB->DataOffset = cpu_to_le32(data_offset);
3949 	pSMB->SetupCount = 0;
3950 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3951 	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3952 
3953 	pSMB->Fid = fid; /* file handle always le */
3954 	pSMB->Reserved2 = 0;
3955 	pSMB->AclFlags = cpu_to_le32(aclflag);
3956 
3957 	if (pntsd && acllen) {
3958 		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3959 				data_offset, pntsd, acllen);
3960 		inc_rfc1001_len(pSMB, byte_count + data_count);
3961 	} else
3962 		inc_rfc1001_len(pSMB, byte_count);
3963 
3964 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3965 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3966 
3967 	cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3968 	if (rc)
3969 		cFYI(1, "Set CIFS ACL returned %d", rc);
3970 	cifs_buf_release(pSMB);
3971 
3972 	if (rc == -EAGAIN)
3973 		goto setCifsAclRetry;
3974 
3975 	return (rc);
3976 }
3977 
3978 #endif /* CONFIG_CIFS_ACL */
3979 
3980 /* Legacy Query Path Information call for lookup to old servers such
3981    as Win9x/WinME */
SMBQueryInformation(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,FILE_ALL_INFO * pFinfo,const struct nls_table * nls_codepage,int remap)3982 int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3983 			const unsigned char *searchName,
3984 			FILE_ALL_INFO *pFinfo,
3985 			const struct nls_table *nls_codepage, int remap)
3986 {
3987 	QUERY_INFORMATION_REQ *pSMB;
3988 	QUERY_INFORMATION_RSP *pSMBr;
3989 	int rc = 0;
3990 	int bytes_returned;
3991 	int name_len;
3992 
3993 	cFYI(1, "In SMBQPath path %s", searchName);
3994 QInfRetry:
3995 	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3996 		      (void **) &pSMBr);
3997 	if (rc)
3998 		return rc;
3999 
4000 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4001 		name_len =
4002 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4003 					   searchName, PATH_MAX, nls_codepage,
4004 					   remap);
4005 		name_len++;     /* trailing null */
4006 		name_len *= 2;
4007 	} else {
4008 		name_len = strnlen(searchName, PATH_MAX);
4009 		name_len++;     /* trailing null */
4010 		strncpy(pSMB->FileName, searchName, name_len);
4011 	}
4012 	pSMB->BufferFormat = 0x04;
4013 	name_len++; /* account for buffer type byte */
4014 	inc_rfc1001_len(pSMB, (__u16)name_len);
4015 	pSMB->ByteCount = cpu_to_le16(name_len);
4016 
4017 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4018 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4019 	if (rc) {
4020 		cFYI(1, "Send error in QueryInfo = %d", rc);
4021 	} else if (pFinfo) {
4022 		struct timespec ts;
4023 		__u32 time = le32_to_cpu(pSMBr->last_write_time);
4024 
4025 		/* decode response */
4026 		/* BB FIXME - add time zone adjustment BB */
4027 		memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
4028 		ts.tv_nsec = 0;
4029 		ts.tv_sec = time;
4030 		/* decode time fields */
4031 		pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4032 		pFinfo->LastWriteTime = pFinfo->ChangeTime;
4033 		pFinfo->LastAccessTime = 0;
4034 		pFinfo->AllocationSize =
4035 			cpu_to_le64(le32_to_cpu(pSMBr->size));
4036 		pFinfo->EndOfFile = pFinfo->AllocationSize;
4037 		pFinfo->Attributes =
4038 			cpu_to_le32(le16_to_cpu(pSMBr->attr));
4039 	} else
4040 		rc = -EIO; /* bad buffer passed in */
4041 
4042 	cifs_buf_release(pSMB);
4043 
4044 	if (rc == -EAGAIN)
4045 		goto QInfRetry;
4046 
4047 	return rc;
4048 }
4049 
4050 int
CIFSSMBQFileInfo(const int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)4051 CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
4052 		 u16 netfid, FILE_ALL_INFO *pFindData)
4053 {
4054 	struct smb_t2_qfi_req *pSMB = NULL;
4055 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4056 	int rc = 0;
4057 	int bytes_returned;
4058 	__u16 params, byte_count;
4059 
4060 QFileInfoRetry:
4061 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4062 		      (void **) &pSMBr);
4063 	if (rc)
4064 		return rc;
4065 
4066 	params = 2 /* level */ + 2 /* fid */;
4067 	pSMB->t2.TotalDataCount = 0;
4068 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4069 	/* BB find exact max data count below from sess structure BB */
4070 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4071 	pSMB->t2.MaxSetupCount = 0;
4072 	pSMB->t2.Reserved = 0;
4073 	pSMB->t2.Flags = 0;
4074 	pSMB->t2.Timeout = 0;
4075 	pSMB->t2.Reserved2 = 0;
4076 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4077 					       Fid) - 4);
4078 	pSMB->t2.DataCount = 0;
4079 	pSMB->t2.DataOffset = 0;
4080 	pSMB->t2.SetupCount = 1;
4081 	pSMB->t2.Reserved3 = 0;
4082 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4083 	byte_count = params + 1 /* pad */ ;
4084 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4085 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4086 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4087 	pSMB->Pad = 0;
4088 	pSMB->Fid = netfid;
4089 	inc_rfc1001_len(pSMB, byte_count);
4090 
4091 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4092 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4093 	if (rc) {
4094 		cFYI(1, "Send error in QPathInfo = %d", rc);
4095 	} else {		/* decode response */
4096 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4097 
4098 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4099 			rc = -EIO;
4100 		else if (get_bcc(&pSMBr->hdr) < 40)
4101 			rc = -EIO;	/* bad smb */
4102 		else if (pFindData) {
4103 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4104 			memcpy((char *) pFindData,
4105 			       (char *) &pSMBr->hdr.Protocol +
4106 			       data_offset, sizeof(FILE_ALL_INFO));
4107 		} else
4108 		    rc = -ENOMEM;
4109 	}
4110 	cifs_buf_release(pSMB);
4111 	if (rc == -EAGAIN)
4112 		goto QFileInfoRetry;
4113 
4114 	return rc;
4115 }
4116 
4117 int
CIFSSMBQPathInfo(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,FILE_ALL_INFO * pFindData,int legacy,const struct nls_table * nls_codepage,int remap)4118 CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
4119 		 const unsigned char *searchName,
4120 		 FILE_ALL_INFO *pFindData,
4121 		 int legacy /* old style infolevel */,
4122 		 const struct nls_table *nls_codepage, int remap)
4123 {
4124 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4125 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4126 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4127 	int rc = 0;
4128 	int bytes_returned;
4129 	int name_len;
4130 	__u16 params, byte_count;
4131 
4132 /* cFYI(1, "In QPathInfo path %s", searchName); */
4133 QPathInfoRetry:
4134 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4135 		      (void **) &pSMBr);
4136 	if (rc)
4137 		return rc;
4138 
4139 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4140 		name_len =
4141 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4142 				       PATH_MAX, nls_codepage, remap);
4143 		name_len++;	/* trailing null */
4144 		name_len *= 2;
4145 	} else {	/* BB improve the check for buffer overruns BB */
4146 		name_len = strnlen(searchName, PATH_MAX);
4147 		name_len++;	/* trailing null */
4148 		strncpy(pSMB->FileName, searchName, name_len);
4149 	}
4150 
4151 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4152 	pSMB->TotalDataCount = 0;
4153 	pSMB->MaxParameterCount = cpu_to_le16(2);
4154 	/* BB find exact max SMB PDU from sess structure BB */
4155 	pSMB->MaxDataCount = cpu_to_le16(4000);
4156 	pSMB->MaxSetupCount = 0;
4157 	pSMB->Reserved = 0;
4158 	pSMB->Flags = 0;
4159 	pSMB->Timeout = 0;
4160 	pSMB->Reserved2 = 0;
4161 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4162 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4163 	pSMB->DataCount = 0;
4164 	pSMB->DataOffset = 0;
4165 	pSMB->SetupCount = 1;
4166 	pSMB->Reserved3 = 0;
4167 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4168 	byte_count = params + 1 /* pad */ ;
4169 	pSMB->TotalParameterCount = cpu_to_le16(params);
4170 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4171 	if (legacy)
4172 		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4173 	else
4174 		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4175 	pSMB->Reserved4 = 0;
4176 	inc_rfc1001_len(pSMB, byte_count);
4177 	pSMB->ByteCount = cpu_to_le16(byte_count);
4178 
4179 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4180 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4181 	if (rc) {
4182 		cFYI(1, "Send error in QPathInfo = %d", rc);
4183 	} else {		/* decode response */
4184 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4185 
4186 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4187 			rc = -EIO;
4188 		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4189 			rc = -EIO;	/* bad smb */
4190 		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4191 			rc = -EIO;  /* 24 or 26 expected but we do not read
4192 					last field */
4193 		else if (pFindData) {
4194 			int size;
4195 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4196 
4197 			/* On legacy responses we do not read the last field,
4198 			EAsize, fortunately since it varies by subdialect and
4199 			also note it differs on Set vs. Get, ie two bytes or 4
4200 			bytes depending but we don't care here */
4201 			if (legacy)
4202 				size = sizeof(FILE_INFO_STANDARD);
4203 			else
4204 				size = sizeof(FILE_ALL_INFO);
4205 			memcpy((char *) pFindData,
4206 			       (char *) &pSMBr->hdr.Protocol +
4207 			       data_offset, size);
4208 		} else
4209 		    rc = -ENOMEM;
4210 	}
4211 	cifs_buf_release(pSMB);
4212 	if (rc == -EAGAIN)
4213 		goto QPathInfoRetry;
4214 
4215 	return rc;
4216 }
4217 
4218 int
CIFSSMBUnixQFileInfo(const int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)4219 CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
4220 		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4221 {
4222 	struct smb_t2_qfi_req *pSMB = NULL;
4223 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4224 	int rc = 0;
4225 	int bytes_returned;
4226 	__u16 params, byte_count;
4227 
4228 UnixQFileInfoRetry:
4229 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4230 		      (void **) &pSMBr);
4231 	if (rc)
4232 		return rc;
4233 
4234 	params = 2 /* level */ + 2 /* fid */;
4235 	pSMB->t2.TotalDataCount = 0;
4236 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4237 	/* BB find exact max data count below from sess structure BB */
4238 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4239 	pSMB->t2.MaxSetupCount = 0;
4240 	pSMB->t2.Reserved = 0;
4241 	pSMB->t2.Flags = 0;
4242 	pSMB->t2.Timeout = 0;
4243 	pSMB->t2.Reserved2 = 0;
4244 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4245 					       Fid) - 4);
4246 	pSMB->t2.DataCount = 0;
4247 	pSMB->t2.DataOffset = 0;
4248 	pSMB->t2.SetupCount = 1;
4249 	pSMB->t2.Reserved3 = 0;
4250 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4251 	byte_count = params + 1 /* pad */ ;
4252 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4253 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4254 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4255 	pSMB->Pad = 0;
4256 	pSMB->Fid = netfid;
4257 	inc_rfc1001_len(pSMB, byte_count);
4258 
4259 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4260 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4261 	if (rc) {
4262 		cFYI(1, "Send error in QPathInfo = %d", rc);
4263 	} else {		/* decode response */
4264 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4265 
4266 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4267 			cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4268 				   "Unix Extensions can be disabled on mount "
4269 				   "by specifying the nosfu mount option.");
4270 			rc = -EIO;	/* bad smb */
4271 		} else {
4272 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4273 			memcpy((char *) pFindData,
4274 			       (char *) &pSMBr->hdr.Protocol +
4275 			       data_offset,
4276 			       sizeof(FILE_UNIX_BASIC_INFO));
4277 		}
4278 	}
4279 
4280 	cifs_buf_release(pSMB);
4281 	if (rc == -EAGAIN)
4282 		goto UnixQFileInfoRetry;
4283 
4284 	return rc;
4285 }
4286 
4287 int
CIFSSMBUnixQPathInfo(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,FILE_UNIX_BASIC_INFO * pFindData,const struct nls_table * nls_codepage,int remap)4288 CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
4289 		     const unsigned char *searchName,
4290 		     FILE_UNIX_BASIC_INFO *pFindData,
4291 		     const struct nls_table *nls_codepage, int remap)
4292 {
4293 /* SMB_QUERY_FILE_UNIX_BASIC */
4294 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4295 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4296 	int rc = 0;
4297 	int bytes_returned = 0;
4298 	int name_len;
4299 	__u16 params, byte_count;
4300 
4301 	cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4302 UnixQPathInfoRetry:
4303 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4304 		      (void **) &pSMBr);
4305 	if (rc)
4306 		return rc;
4307 
4308 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4309 		name_len =
4310 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4311 				       PATH_MAX, nls_codepage, remap);
4312 		name_len++;	/* trailing null */
4313 		name_len *= 2;
4314 	} else {	/* BB improve the check for buffer overruns BB */
4315 		name_len = strnlen(searchName, PATH_MAX);
4316 		name_len++;	/* trailing null */
4317 		strncpy(pSMB->FileName, searchName, name_len);
4318 	}
4319 
4320 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4321 	pSMB->TotalDataCount = 0;
4322 	pSMB->MaxParameterCount = cpu_to_le16(2);
4323 	/* BB find exact max SMB PDU from sess structure BB */
4324 	pSMB->MaxDataCount = cpu_to_le16(4000);
4325 	pSMB->MaxSetupCount = 0;
4326 	pSMB->Reserved = 0;
4327 	pSMB->Flags = 0;
4328 	pSMB->Timeout = 0;
4329 	pSMB->Reserved2 = 0;
4330 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4331 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4332 	pSMB->DataCount = 0;
4333 	pSMB->DataOffset = 0;
4334 	pSMB->SetupCount = 1;
4335 	pSMB->Reserved3 = 0;
4336 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4337 	byte_count = params + 1 /* pad */ ;
4338 	pSMB->TotalParameterCount = cpu_to_le16(params);
4339 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4340 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4341 	pSMB->Reserved4 = 0;
4342 	inc_rfc1001_len(pSMB, byte_count);
4343 	pSMB->ByteCount = cpu_to_le16(byte_count);
4344 
4345 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4346 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4347 	if (rc) {
4348 		cFYI(1, "Send error in QPathInfo = %d", rc);
4349 	} else {		/* decode response */
4350 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4351 
4352 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4353 			cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4354 				   "Unix Extensions can be disabled on mount "
4355 				   "by specifying the nosfu mount option.");
4356 			rc = -EIO;	/* bad smb */
4357 		} else {
4358 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4359 			memcpy((char *) pFindData,
4360 			       (char *) &pSMBr->hdr.Protocol +
4361 			       data_offset,
4362 			       sizeof(FILE_UNIX_BASIC_INFO));
4363 		}
4364 	}
4365 	cifs_buf_release(pSMB);
4366 	if (rc == -EAGAIN)
4367 		goto UnixQPathInfoRetry;
4368 
4369 	return rc;
4370 }
4371 
4372 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4373 int
CIFSFindFirst(const int xid,struct cifs_tcon * tcon,const char * searchName,const struct nls_table * nls_codepage,__u16 * pnetfid,__u16 search_flags,struct cifs_search_info * psrch_inf,int remap,const char dirsep)4374 CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4375 	      const char *searchName,
4376 	      const struct nls_table *nls_codepage,
4377 	      __u16 *pnetfid, __u16 search_flags,
4378 	      struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4379 {
4380 /* level 257 SMB_ */
4381 	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4382 	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4383 	T2_FFIRST_RSP_PARMS *parms;
4384 	int rc = 0;
4385 	int bytes_returned = 0;
4386 	int name_len;
4387 	__u16 params, byte_count;
4388 
4389 	cFYI(1, "In FindFirst for %s", searchName);
4390 
4391 findFirstRetry:
4392 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4393 		      (void **) &pSMBr);
4394 	if (rc)
4395 		return rc;
4396 
4397 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4398 		name_len =
4399 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4400 				       PATH_MAX, nls_codepage, remap);
4401 		/* We can not add the asterik earlier in case
4402 		it got remapped to 0xF03A as if it were part of the
4403 		directory name instead of a wildcard */
4404 		name_len *= 2;
4405 		pSMB->FileName[name_len] = dirsep;
4406 		pSMB->FileName[name_len+1] = 0;
4407 		pSMB->FileName[name_len+2] = '*';
4408 		pSMB->FileName[name_len+3] = 0;
4409 		name_len += 4; /* now the trailing null */
4410 		pSMB->FileName[name_len] = 0; /* null terminate just in case */
4411 		pSMB->FileName[name_len+1] = 0;
4412 		name_len += 2;
4413 	} else {	/* BB add check for overrun of SMB buf BB */
4414 		name_len = strnlen(searchName, PATH_MAX);
4415 /* BB fix here and in unicode clause above ie
4416 		if (name_len > buffersize-header)
4417 			free buffer exit; BB */
4418 		strncpy(pSMB->FileName, searchName, name_len);
4419 		pSMB->FileName[name_len] = dirsep;
4420 		pSMB->FileName[name_len+1] = '*';
4421 		pSMB->FileName[name_len+2] = 0;
4422 		name_len += 3;
4423 	}
4424 
4425 	params = 12 + name_len /* includes null */ ;
4426 	pSMB->TotalDataCount = 0;	/* no EAs */
4427 	pSMB->MaxParameterCount = cpu_to_le16(10);
4428 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4429 	pSMB->MaxSetupCount = 0;
4430 	pSMB->Reserved = 0;
4431 	pSMB->Flags = 0;
4432 	pSMB->Timeout = 0;
4433 	pSMB->Reserved2 = 0;
4434 	byte_count = params + 1 /* pad */ ;
4435 	pSMB->TotalParameterCount = cpu_to_le16(params);
4436 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4437 	pSMB->ParameterOffset = cpu_to_le16(
4438 	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4439 		- 4);
4440 	pSMB->DataCount = 0;
4441 	pSMB->DataOffset = 0;
4442 	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
4443 	pSMB->Reserved3 = 0;
4444 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4445 	pSMB->SearchAttributes =
4446 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4447 			ATTR_DIRECTORY);
4448 	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4449 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4450 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4451 
4452 	/* BB what should we set StorageType to? Does it matter? BB */
4453 	pSMB->SearchStorageType = 0;
4454 	inc_rfc1001_len(pSMB, byte_count);
4455 	pSMB->ByteCount = cpu_to_le16(byte_count);
4456 
4457 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4458 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4459 	cifs_stats_inc(&tcon->num_ffirst);
4460 
4461 	if (rc) {/* BB add logic to retry regular search if Unix search
4462 			rejected unexpectedly by server */
4463 		/* BB Add code to handle unsupported level rc */
4464 		cFYI(1, "Error in FindFirst = %d", rc);
4465 
4466 		cifs_buf_release(pSMB);
4467 
4468 		/* BB eventually could optimize out free and realloc of buf */
4469 		/*    for this case */
4470 		if (rc == -EAGAIN)
4471 			goto findFirstRetry;
4472 	} else { /* decode response */
4473 		/* BB remember to free buffer if error BB */
4474 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4475 		if (rc == 0) {
4476 			unsigned int lnoff;
4477 
4478 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4479 				psrch_inf->unicode = true;
4480 			else
4481 				psrch_inf->unicode = false;
4482 
4483 			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4484 			psrch_inf->smallBuf = 0;
4485 			psrch_inf->srch_entries_start =
4486 				(char *) &pSMBr->hdr.Protocol +
4487 					le16_to_cpu(pSMBr->t2.DataOffset);
4488 			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4489 			       le16_to_cpu(pSMBr->t2.ParameterOffset));
4490 
4491 			if (parms->EndofSearch)
4492 				psrch_inf->endOfSearch = true;
4493 			else
4494 				psrch_inf->endOfSearch = false;
4495 
4496 			psrch_inf->entries_in_buffer =
4497 					le16_to_cpu(parms->SearchCount);
4498 			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4499 				psrch_inf->entries_in_buffer;
4500 			lnoff = le16_to_cpu(parms->LastNameOffset);
4501 			if (CIFSMaxBufSize < lnoff) {
4502 				cERROR(1, "ignoring corrupt resume name");
4503 				psrch_inf->last_entry = NULL;
4504 				return rc;
4505 			}
4506 
4507 			psrch_inf->last_entry = psrch_inf->srch_entries_start +
4508 							lnoff;
4509 
4510 			*pnetfid = parms->SearchHandle;
4511 		} else {
4512 			cifs_buf_release(pSMB);
4513 		}
4514 	}
4515 
4516 	return rc;
4517 }
4518 
CIFSFindNext(const int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4519 int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
4520 		 __u16 search_flags, struct cifs_search_info *psrch_inf)
4521 {
4522 	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4523 	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4524 	T2_FNEXT_RSP_PARMS *parms;
4525 	char *response_data;
4526 	int rc = 0;
4527 	int bytes_returned;
4528 	unsigned int name_len;
4529 	__u16 params, byte_count;
4530 
4531 	cFYI(1, "In FindNext");
4532 
4533 	if (psrch_inf->endOfSearch)
4534 		return -ENOENT;
4535 
4536 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4537 		(void **) &pSMBr);
4538 	if (rc)
4539 		return rc;
4540 
4541 	params = 14; /* includes 2 bytes of null string, converted to LE below*/
4542 	byte_count = 0;
4543 	pSMB->TotalDataCount = 0;       /* no EAs */
4544 	pSMB->MaxParameterCount = cpu_to_le16(8);
4545 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4546 	pSMB->MaxSetupCount = 0;
4547 	pSMB->Reserved = 0;
4548 	pSMB->Flags = 0;
4549 	pSMB->Timeout = 0;
4550 	pSMB->Reserved2 = 0;
4551 	pSMB->ParameterOffset =  cpu_to_le16(
4552 	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4553 	pSMB->DataCount = 0;
4554 	pSMB->DataOffset = 0;
4555 	pSMB->SetupCount = 1;
4556 	pSMB->Reserved3 = 0;
4557 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4558 	pSMB->SearchHandle = searchHandle;      /* always kept as le */
4559 	pSMB->SearchCount =
4560 		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4561 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4562 	pSMB->ResumeKey = psrch_inf->resume_key;
4563 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4564 
4565 	name_len = psrch_inf->resume_name_len;
4566 	params += name_len;
4567 	if (name_len < PATH_MAX) {
4568 		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4569 		byte_count += name_len;
4570 		/* 14 byte parm len above enough for 2 byte null terminator */
4571 		pSMB->ResumeFileName[name_len] = 0;
4572 		pSMB->ResumeFileName[name_len+1] = 0;
4573 	} else {
4574 		rc = -EINVAL;
4575 		goto FNext2_err_exit;
4576 	}
4577 	byte_count = params + 1 /* pad */ ;
4578 	pSMB->TotalParameterCount = cpu_to_le16(params);
4579 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4580 	inc_rfc1001_len(pSMB, byte_count);
4581 	pSMB->ByteCount = cpu_to_le16(byte_count);
4582 
4583 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4584 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4585 	cifs_stats_inc(&tcon->num_fnext);
4586 	if (rc) {
4587 		if (rc == -EBADF) {
4588 			psrch_inf->endOfSearch = true;
4589 			cifs_buf_release(pSMB);
4590 			rc = 0; /* search probably was closed at end of search*/
4591 		} else
4592 			cFYI(1, "FindNext returned = %d", rc);
4593 	} else {                /* decode response */
4594 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4595 
4596 		if (rc == 0) {
4597 			unsigned int lnoff;
4598 
4599 			/* BB fixme add lock for file (srch_info) struct here */
4600 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4601 				psrch_inf->unicode = true;
4602 			else
4603 				psrch_inf->unicode = false;
4604 			response_data = (char *) &pSMBr->hdr.Protocol +
4605 			       le16_to_cpu(pSMBr->t2.ParameterOffset);
4606 			parms = (T2_FNEXT_RSP_PARMS *)response_data;
4607 			response_data = (char *)&pSMBr->hdr.Protocol +
4608 				le16_to_cpu(pSMBr->t2.DataOffset);
4609 			if (psrch_inf->smallBuf)
4610 				cifs_small_buf_release(
4611 					psrch_inf->ntwrk_buf_start);
4612 			else
4613 				cifs_buf_release(psrch_inf->ntwrk_buf_start);
4614 			psrch_inf->srch_entries_start = response_data;
4615 			psrch_inf->ntwrk_buf_start = (char *)pSMB;
4616 			psrch_inf->smallBuf = 0;
4617 			if (parms->EndofSearch)
4618 				psrch_inf->endOfSearch = true;
4619 			else
4620 				psrch_inf->endOfSearch = false;
4621 			psrch_inf->entries_in_buffer =
4622 						le16_to_cpu(parms->SearchCount);
4623 			psrch_inf->index_of_last_entry +=
4624 				psrch_inf->entries_in_buffer;
4625 			lnoff = le16_to_cpu(parms->LastNameOffset);
4626 			if (CIFSMaxBufSize < lnoff) {
4627 				cERROR(1, "ignoring corrupt resume name");
4628 				psrch_inf->last_entry = NULL;
4629 				return rc;
4630 			} else
4631 				psrch_inf->last_entry =
4632 					psrch_inf->srch_entries_start + lnoff;
4633 
4634 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4635 	    psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4636 
4637 			/* BB fixme add unlock here */
4638 		}
4639 
4640 	}
4641 
4642 	/* BB On error, should we leave previous search buf (and count and
4643 	last entry fields) intact or free the previous one? */
4644 
4645 	/* Note: On -EAGAIN error only caller can retry on handle based calls
4646 	since file handle passed in no longer valid */
4647 FNext2_err_exit:
4648 	if (rc != 0)
4649 		cifs_buf_release(pSMB);
4650 	return rc;
4651 }
4652 
4653 int
CIFSFindClose(const int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4654 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4655 	      const __u16 searchHandle)
4656 {
4657 	int rc = 0;
4658 	FINDCLOSE_REQ *pSMB = NULL;
4659 
4660 	cFYI(1, "In CIFSSMBFindClose");
4661 	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4662 
4663 	/* no sense returning error if session restarted
4664 		as file handle has been closed */
4665 	if (rc == -EAGAIN)
4666 		return 0;
4667 	if (rc)
4668 		return rc;
4669 
4670 	pSMB->FileID = searchHandle;
4671 	pSMB->ByteCount = 0;
4672 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4673 	if (rc)
4674 		cERROR(1, "Send error in FindClose = %d", rc);
4675 
4676 	cifs_stats_inc(&tcon->num_fclose);
4677 
4678 	/* Since session is dead, search handle closed on server already */
4679 	if (rc == -EAGAIN)
4680 		rc = 0;
4681 
4682 	return rc;
4683 }
4684 
4685 int
CIFSGetSrvInodeNumber(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,__u64 * inode_number,const struct nls_table * nls_codepage,int remap)4686 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4687 		      const unsigned char *searchName,
4688 		      __u64 *inode_number,
4689 		      const struct nls_table *nls_codepage, int remap)
4690 {
4691 	int rc = 0;
4692 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4693 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4694 	int name_len, bytes_returned;
4695 	__u16 params, byte_count;
4696 
4697 	cFYI(1, "In GetSrvInodeNum for %s", searchName);
4698 	if (tcon == NULL)
4699 		return -ENODEV;
4700 
4701 GetInodeNumberRetry:
4702 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4703 		      (void **) &pSMBr);
4704 	if (rc)
4705 		return rc;
4706 
4707 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4708 		name_len =
4709 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4710 					   searchName, PATH_MAX, nls_codepage,
4711 					   remap);
4712 		name_len++;     /* trailing null */
4713 		name_len *= 2;
4714 	} else {	/* BB improve the check for buffer overruns BB */
4715 		name_len = strnlen(searchName, PATH_MAX);
4716 		name_len++;     /* trailing null */
4717 		strncpy(pSMB->FileName, searchName, name_len);
4718 	}
4719 
4720 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4721 	pSMB->TotalDataCount = 0;
4722 	pSMB->MaxParameterCount = cpu_to_le16(2);
4723 	/* BB find exact max data count below from sess structure BB */
4724 	pSMB->MaxDataCount = cpu_to_le16(4000);
4725 	pSMB->MaxSetupCount = 0;
4726 	pSMB->Reserved = 0;
4727 	pSMB->Flags = 0;
4728 	pSMB->Timeout = 0;
4729 	pSMB->Reserved2 = 0;
4730 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4731 		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4732 	pSMB->DataCount = 0;
4733 	pSMB->DataOffset = 0;
4734 	pSMB->SetupCount = 1;
4735 	pSMB->Reserved3 = 0;
4736 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4737 	byte_count = params + 1 /* pad */ ;
4738 	pSMB->TotalParameterCount = cpu_to_le16(params);
4739 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4740 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4741 	pSMB->Reserved4 = 0;
4742 	inc_rfc1001_len(pSMB, byte_count);
4743 	pSMB->ByteCount = cpu_to_le16(byte_count);
4744 
4745 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4746 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4747 	if (rc) {
4748 		cFYI(1, "error %d in QueryInternalInfo", rc);
4749 	} else {
4750 		/* decode response */
4751 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4752 		/* BB also check enough total bytes returned */
4753 		if (rc || get_bcc(&pSMBr->hdr) < 2)
4754 			/* If rc should we check for EOPNOSUPP and
4755 			disable the srvino flag? or in caller? */
4756 			rc = -EIO;      /* bad smb */
4757 		else {
4758 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4759 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4760 			struct file_internal_info *pfinfo;
4761 			/* BB Do we need a cast or hash here ? */
4762 			if (count < 8) {
4763 				cFYI(1, "Illegal size ret in QryIntrnlInf");
4764 				rc = -EIO;
4765 				goto GetInodeNumOut;
4766 			}
4767 			pfinfo = (struct file_internal_info *)
4768 				(data_offset + (char *) &pSMBr->hdr.Protocol);
4769 			*inode_number = le64_to_cpu(pfinfo->UniqueId);
4770 		}
4771 	}
4772 GetInodeNumOut:
4773 	cifs_buf_release(pSMB);
4774 	if (rc == -EAGAIN)
4775 		goto GetInodeNumberRetry;
4776 	return rc;
4777 }
4778 
4779 /* parses DFS refferal V3 structure
4780  * caller is responsible for freeing target_nodes
4781  * returns:
4782  * 	on success - 0
4783  *	on failure - errno
4784  */
4785 static int
parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP * pSMBr,unsigned int * num_of_nodes,struct dfs_info3_param ** target_nodes,const struct nls_table * nls_codepage,int remap,const char * searchName)4786 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4787 		unsigned int *num_of_nodes,
4788 		struct dfs_info3_param **target_nodes,
4789 		const struct nls_table *nls_codepage, int remap,
4790 		const char *searchName)
4791 {
4792 	int i, rc = 0;
4793 	char *data_end;
4794 	bool is_unicode;
4795 	struct dfs_referral_level_3 *ref;
4796 
4797 	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4798 		is_unicode = true;
4799 	else
4800 		is_unicode = false;
4801 	*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4802 
4803 	if (*num_of_nodes < 1) {
4804 		cERROR(1, "num_referrals: must be at least > 0,"
4805 			"but we get num_referrals = %d\n", *num_of_nodes);
4806 		rc = -EINVAL;
4807 		goto parse_DFS_referrals_exit;
4808 	}
4809 
4810 	ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4811 	if (ref->VersionNumber != cpu_to_le16(3)) {
4812 		cERROR(1, "Referrals of V%d version are not supported,"
4813 			"should be V3", le16_to_cpu(ref->VersionNumber));
4814 		rc = -EINVAL;
4815 		goto parse_DFS_referrals_exit;
4816 	}
4817 
4818 	/* get the upper boundary of the resp buffer */
4819 	data_end = (char *)(&(pSMBr->PathConsumed)) +
4820 				le16_to_cpu(pSMBr->t2.DataCount);
4821 
4822 	cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4823 			*num_of_nodes,
4824 			le32_to_cpu(pSMBr->DFSFlags));
4825 
4826 	*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4827 			*num_of_nodes, GFP_KERNEL);
4828 	if (*target_nodes == NULL) {
4829 		cERROR(1, "Failed to allocate buffer for target_nodes\n");
4830 		rc = -ENOMEM;
4831 		goto parse_DFS_referrals_exit;
4832 	}
4833 
4834 	/* collect necessary data from referrals */
4835 	for (i = 0; i < *num_of_nodes; i++) {
4836 		char *temp;
4837 		int max_len;
4838 		struct dfs_info3_param *node = (*target_nodes)+i;
4839 
4840 		node->flags = le32_to_cpu(pSMBr->DFSFlags);
4841 		if (is_unicode) {
4842 			__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4843 						GFP_KERNEL);
4844 			if (tmp == NULL) {
4845 				rc = -ENOMEM;
4846 				goto parse_DFS_referrals_exit;
4847 			}
4848 			cifsConvertToUTF16((__le16 *) tmp, searchName,
4849 					   PATH_MAX, nls_codepage, remap);
4850 			node->path_consumed = cifs_utf16_bytes(tmp,
4851 					le16_to_cpu(pSMBr->PathConsumed),
4852 					nls_codepage);
4853 			kfree(tmp);
4854 		} else
4855 			node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4856 
4857 		node->server_type = le16_to_cpu(ref->ServerType);
4858 		node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4859 
4860 		/* copy DfsPath */
4861 		temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4862 		max_len = data_end - temp;
4863 		node->path_name = cifs_strndup_from_utf16(temp, max_len,
4864 						is_unicode, nls_codepage);
4865 		if (!node->path_name) {
4866 			rc = -ENOMEM;
4867 			goto parse_DFS_referrals_exit;
4868 		}
4869 
4870 		/* copy link target UNC */
4871 		temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4872 		max_len = data_end - temp;
4873 		node->node_name = cifs_strndup_from_utf16(temp, max_len,
4874 						is_unicode, nls_codepage);
4875 		if (!node->node_name) {
4876 			rc = -ENOMEM;
4877 			goto parse_DFS_referrals_exit;
4878 		}
4879 
4880 		ref++;
4881 	}
4882 
4883 parse_DFS_referrals_exit:
4884 	if (rc) {
4885 		free_dfs_info_array(*target_nodes, *num_of_nodes);
4886 		*target_nodes = NULL;
4887 		*num_of_nodes = 0;
4888 	}
4889 	return rc;
4890 }
4891 
4892 int
CIFSGetDFSRefer(const int xid,struct cifs_ses * ses,const unsigned char * searchName,struct dfs_info3_param ** target_nodes,unsigned int * num_of_nodes,const struct nls_table * nls_codepage,int remap)4893 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4894 		const unsigned char *searchName,
4895 		struct dfs_info3_param **target_nodes,
4896 		unsigned int *num_of_nodes,
4897 		const struct nls_table *nls_codepage, int remap)
4898 {
4899 /* TRANS2_GET_DFS_REFERRAL */
4900 	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4901 	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4902 	int rc = 0;
4903 	int bytes_returned;
4904 	int name_len;
4905 	__u16 params, byte_count;
4906 	*num_of_nodes = 0;
4907 	*target_nodes = NULL;
4908 
4909 	cFYI(1, "In GetDFSRefer the path %s", searchName);
4910 	if (ses == NULL)
4911 		return -ENODEV;
4912 getDFSRetry:
4913 	rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4914 		      (void **) &pSMBr);
4915 	if (rc)
4916 		return rc;
4917 
4918 	/* server pointer checked in called function,
4919 	but should never be null here anyway */
4920 	pSMB->hdr.Mid = GetNextMid(ses->server);
4921 	pSMB->hdr.Tid = ses->ipc_tid;
4922 	pSMB->hdr.Uid = ses->Suid;
4923 	if (ses->capabilities & CAP_STATUS32)
4924 		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4925 	if (ses->capabilities & CAP_DFS)
4926 		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4927 
4928 	if (ses->capabilities & CAP_UNICODE) {
4929 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4930 		name_len =
4931 		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4932 				       searchName, PATH_MAX, nls_codepage,
4933 				       remap);
4934 		name_len++;	/* trailing null */
4935 		name_len *= 2;
4936 	} else {	/* BB improve the check for buffer overruns BB */
4937 		name_len = strnlen(searchName, PATH_MAX);
4938 		name_len++;	/* trailing null */
4939 		strncpy(pSMB->RequestFileName, searchName, name_len);
4940 	}
4941 
4942 	if (ses->server) {
4943 		if (ses->server->sec_mode &
4944 		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4945 			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4946 	}
4947 
4948 	pSMB->hdr.Uid = ses->Suid;
4949 
4950 	params = 2 /* level */  + name_len /*includes null */ ;
4951 	pSMB->TotalDataCount = 0;
4952 	pSMB->DataCount = 0;
4953 	pSMB->DataOffset = 0;
4954 	pSMB->MaxParameterCount = 0;
4955 	/* BB find exact max SMB PDU from sess structure BB */
4956 	pSMB->MaxDataCount = cpu_to_le16(4000);
4957 	pSMB->MaxSetupCount = 0;
4958 	pSMB->Reserved = 0;
4959 	pSMB->Flags = 0;
4960 	pSMB->Timeout = 0;
4961 	pSMB->Reserved2 = 0;
4962 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4963 	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4964 	pSMB->SetupCount = 1;
4965 	pSMB->Reserved3 = 0;
4966 	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4967 	byte_count = params + 3 /* pad */ ;
4968 	pSMB->ParameterCount = cpu_to_le16(params);
4969 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4970 	pSMB->MaxReferralLevel = cpu_to_le16(3);
4971 	inc_rfc1001_len(pSMB, byte_count);
4972 	pSMB->ByteCount = cpu_to_le16(byte_count);
4973 
4974 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4975 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4976 	if (rc) {
4977 		cFYI(1, "Send error in GetDFSRefer = %d", rc);
4978 		goto GetDFSRefExit;
4979 	}
4980 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4981 
4982 	/* BB Also check if enough total bytes returned? */
4983 	if (rc || get_bcc(&pSMBr->hdr) < 17) {
4984 		rc = -EIO;      /* bad smb */
4985 		goto GetDFSRefExit;
4986 	}
4987 
4988 	cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4989 				get_bcc(&pSMBr->hdr),
4990 				le16_to_cpu(pSMBr->t2.DataOffset));
4991 
4992 	/* parse returned result into more usable form */
4993 	rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4994 				 target_nodes, nls_codepage, remap,
4995 				 searchName);
4996 
4997 GetDFSRefExit:
4998 	cifs_buf_release(pSMB);
4999 
5000 	if (rc == -EAGAIN)
5001 		goto getDFSRetry;
5002 
5003 	return rc;
5004 }
5005 
5006 /* Query File System Info such as free space to old servers such as Win 9x */
5007 int
SMBOldQFSInfo(const int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5008 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
5009 {
5010 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
5011 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5012 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5013 	FILE_SYSTEM_ALLOC_INFO *response_data;
5014 	int rc = 0;
5015 	int bytes_returned = 0;
5016 	__u16 params, byte_count;
5017 
5018 	cFYI(1, "OldQFSInfo");
5019 oldQFSInfoRetry:
5020 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5021 		(void **) &pSMBr);
5022 	if (rc)
5023 		return rc;
5024 
5025 	params = 2;     /* level */
5026 	pSMB->TotalDataCount = 0;
5027 	pSMB->MaxParameterCount = cpu_to_le16(2);
5028 	pSMB->MaxDataCount = cpu_to_le16(1000);
5029 	pSMB->MaxSetupCount = 0;
5030 	pSMB->Reserved = 0;
5031 	pSMB->Flags = 0;
5032 	pSMB->Timeout = 0;
5033 	pSMB->Reserved2 = 0;
5034 	byte_count = params + 1 /* pad */ ;
5035 	pSMB->TotalParameterCount = cpu_to_le16(params);
5036 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5037 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5038 	struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5039 	pSMB->DataCount = 0;
5040 	pSMB->DataOffset = 0;
5041 	pSMB->SetupCount = 1;
5042 	pSMB->Reserved3 = 0;
5043 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5044 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
5045 	inc_rfc1001_len(pSMB, byte_count);
5046 	pSMB->ByteCount = cpu_to_le16(byte_count);
5047 
5048 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5049 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
5050 	if (rc) {
5051 		cFYI(1, "Send error in QFSInfo = %d", rc);
5052 	} else {                /* decode response */
5053 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5054 
5055 		if (rc || get_bcc(&pSMBr->hdr) < 18)
5056 			rc = -EIO;      /* bad smb */
5057 		else {
5058 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5059 			cFYI(1, "qfsinf resp BCC: %d  Offset %d",
5060 				 get_bcc(&pSMBr->hdr), data_offset);
5061 
5062 			response_data = (FILE_SYSTEM_ALLOC_INFO *)
5063 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
5064 			FSData->f_bsize =
5065 				le16_to_cpu(response_data->BytesPerSector) *
5066 				le32_to_cpu(response_data->
5067 					SectorsPerAllocationUnit);
5068 			FSData->f_blocks =
5069 			       le32_to_cpu(response_data->TotalAllocationUnits);
5070 			FSData->f_bfree = FSData->f_bavail =
5071 				le32_to_cpu(response_data->FreeAllocationUnits);
5072 			cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5073 			     (unsigned long long)FSData->f_blocks,
5074 			     (unsigned long long)FSData->f_bfree,
5075 			     FSData->f_bsize);
5076 		}
5077 	}
5078 	cifs_buf_release(pSMB);
5079 
5080 	if (rc == -EAGAIN)
5081 		goto oldQFSInfoRetry;
5082 
5083 	return rc;
5084 }
5085 
5086 int
CIFSSMBQFSInfo(const int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5087 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
5088 {
5089 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5090 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5091 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5092 	FILE_SYSTEM_INFO *response_data;
5093 	int rc = 0;
5094 	int bytes_returned = 0;
5095 	__u16 params, byte_count;
5096 
5097 	cFYI(1, "In QFSInfo");
5098 QFSInfoRetry:
5099 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5100 		      (void **) &pSMBr);
5101 	if (rc)
5102 		return rc;
5103 
5104 	params = 2;	/* level */
5105 	pSMB->TotalDataCount = 0;
5106 	pSMB->MaxParameterCount = cpu_to_le16(2);
5107 	pSMB->MaxDataCount = cpu_to_le16(1000);
5108 	pSMB->MaxSetupCount = 0;
5109 	pSMB->Reserved = 0;
5110 	pSMB->Flags = 0;
5111 	pSMB->Timeout = 0;
5112 	pSMB->Reserved2 = 0;
5113 	byte_count = params + 1 /* pad */ ;
5114 	pSMB->TotalParameterCount = cpu_to_le16(params);
5115 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5116 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5117 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5118 	pSMB->DataCount = 0;
5119 	pSMB->DataOffset = 0;
5120 	pSMB->SetupCount = 1;
5121 	pSMB->Reserved3 = 0;
5122 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5123 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5124 	inc_rfc1001_len(pSMB, byte_count);
5125 	pSMB->ByteCount = cpu_to_le16(byte_count);
5126 
5127 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5128 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5129 	if (rc) {
5130 		cFYI(1, "Send error in QFSInfo = %d", rc);
5131 	} else {		/* decode response */
5132 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5133 
5134 		if (rc || get_bcc(&pSMBr->hdr) < 24)
5135 			rc = -EIO;	/* bad smb */
5136 		else {
5137 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5138 
5139 			response_data =
5140 			    (FILE_SYSTEM_INFO
5141 			     *) (((char *) &pSMBr->hdr.Protocol) +
5142 				 data_offset);
5143 			FSData->f_bsize =
5144 			    le32_to_cpu(response_data->BytesPerSector) *
5145 			    le32_to_cpu(response_data->
5146 					SectorsPerAllocationUnit);
5147 			FSData->f_blocks =
5148 			    le64_to_cpu(response_data->TotalAllocationUnits);
5149 			FSData->f_bfree = FSData->f_bavail =
5150 			    le64_to_cpu(response_data->FreeAllocationUnits);
5151 			cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5152 			     (unsigned long long)FSData->f_blocks,
5153 			     (unsigned long long)FSData->f_bfree,
5154 			     FSData->f_bsize);
5155 		}
5156 	}
5157 	cifs_buf_release(pSMB);
5158 
5159 	if (rc == -EAGAIN)
5160 		goto QFSInfoRetry;
5161 
5162 	return rc;
5163 }
5164 
5165 int
CIFSSMBQFSAttributeInfo(const int xid,struct cifs_tcon * tcon)5166 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
5167 {
5168 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5169 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5170 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5171 	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5172 	int rc = 0;
5173 	int bytes_returned = 0;
5174 	__u16 params, byte_count;
5175 
5176 	cFYI(1, "In QFSAttributeInfo");
5177 QFSAttributeRetry:
5178 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5179 		      (void **) &pSMBr);
5180 	if (rc)
5181 		return rc;
5182 
5183 	params = 2;	/* level */
5184 	pSMB->TotalDataCount = 0;
5185 	pSMB->MaxParameterCount = cpu_to_le16(2);
5186 	/* BB find exact max SMB PDU from sess structure BB */
5187 	pSMB->MaxDataCount = cpu_to_le16(1000);
5188 	pSMB->MaxSetupCount = 0;
5189 	pSMB->Reserved = 0;
5190 	pSMB->Flags = 0;
5191 	pSMB->Timeout = 0;
5192 	pSMB->Reserved2 = 0;
5193 	byte_count = params + 1 /* pad */ ;
5194 	pSMB->TotalParameterCount = cpu_to_le16(params);
5195 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5196 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5197 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5198 	pSMB->DataCount = 0;
5199 	pSMB->DataOffset = 0;
5200 	pSMB->SetupCount = 1;
5201 	pSMB->Reserved3 = 0;
5202 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5203 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5204 	inc_rfc1001_len(pSMB, byte_count);
5205 	pSMB->ByteCount = cpu_to_le16(byte_count);
5206 
5207 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5208 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5209 	if (rc) {
5210 		cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5211 	} else {		/* decode response */
5212 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5213 
5214 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5215 			/* BB also check if enough bytes returned */
5216 			rc = -EIO;	/* bad smb */
5217 		} else {
5218 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5219 			response_data =
5220 			    (FILE_SYSTEM_ATTRIBUTE_INFO
5221 			     *) (((char *) &pSMBr->hdr.Protocol) +
5222 				 data_offset);
5223 			memcpy(&tcon->fsAttrInfo, response_data,
5224 			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5225 		}
5226 	}
5227 	cifs_buf_release(pSMB);
5228 
5229 	if (rc == -EAGAIN)
5230 		goto QFSAttributeRetry;
5231 
5232 	return rc;
5233 }
5234 
5235 int
CIFSSMBQFSDeviceInfo(const int xid,struct cifs_tcon * tcon)5236 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
5237 {
5238 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5239 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5240 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5241 	FILE_SYSTEM_DEVICE_INFO *response_data;
5242 	int rc = 0;
5243 	int bytes_returned = 0;
5244 	__u16 params, byte_count;
5245 
5246 	cFYI(1, "In QFSDeviceInfo");
5247 QFSDeviceRetry:
5248 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5249 		      (void **) &pSMBr);
5250 	if (rc)
5251 		return rc;
5252 
5253 	params = 2;	/* level */
5254 	pSMB->TotalDataCount = 0;
5255 	pSMB->MaxParameterCount = cpu_to_le16(2);
5256 	/* BB find exact max SMB PDU from sess structure BB */
5257 	pSMB->MaxDataCount = cpu_to_le16(1000);
5258 	pSMB->MaxSetupCount = 0;
5259 	pSMB->Reserved = 0;
5260 	pSMB->Flags = 0;
5261 	pSMB->Timeout = 0;
5262 	pSMB->Reserved2 = 0;
5263 	byte_count = params + 1 /* pad */ ;
5264 	pSMB->TotalParameterCount = cpu_to_le16(params);
5265 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5266 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5267 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5268 
5269 	pSMB->DataCount = 0;
5270 	pSMB->DataOffset = 0;
5271 	pSMB->SetupCount = 1;
5272 	pSMB->Reserved3 = 0;
5273 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5274 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5275 	inc_rfc1001_len(pSMB, byte_count);
5276 	pSMB->ByteCount = cpu_to_le16(byte_count);
5277 
5278 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5279 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5280 	if (rc) {
5281 		cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5282 	} else {		/* decode response */
5283 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5284 
5285 		if (rc || get_bcc(&pSMBr->hdr) <
5286 			  sizeof(FILE_SYSTEM_DEVICE_INFO))
5287 			rc = -EIO;	/* bad smb */
5288 		else {
5289 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5290 			response_data =
5291 			    (FILE_SYSTEM_DEVICE_INFO *)
5292 				(((char *) &pSMBr->hdr.Protocol) +
5293 				 data_offset);
5294 			memcpy(&tcon->fsDevInfo, response_data,
5295 			       sizeof(FILE_SYSTEM_DEVICE_INFO));
5296 		}
5297 	}
5298 	cifs_buf_release(pSMB);
5299 
5300 	if (rc == -EAGAIN)
5301 		goto QFSDeviceRetry;
5302 
5303 	return rc;
5304 }
5305 
5306 int
CIFSSMBQFSUnixInfo(const int xid,struct cifs_tcon * tcon)5307 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
5308 {
5309 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5310 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5311 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5312 	FILE_SYSTEM_UNIX_INFO *response_data;
5313 	int rc = 0;
5314 	int bytes_returned = 0;
5315 	__u16 params, byte_count;
5316 
5317 	cFYI(1, "In QFSUnixInfo");
5318 QFSUnixRetry:
5319 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5320 				   (void **) &pSMB, (void **) &pSMBr);
5321 	if (rc)
5322 		return rc;
5323 
5324 	params = 2;	/* level */
5325 	pSMB->TotalDataCount = 0;
5326 	pSMB->DataCount = 0;
5327 	pSMB->DataOffset = 0;
5328 	pSMB->MaxParameterCount = cpu_to_le16(2);
5329 	/* BB find exact max SMB PDU from sess structure BB */
5330 	pSMB->MaxDataCount = cpu_to_le16(100);
5331 	pSMB->MaxSetupCount = 0;
5332 	pSMB->Reserved = 0;
5333 	pSMB->Flags = 0;
5334 	pSMB->Timeout = 0;
5335 	pSMB->Reserved2 = 0;
5336 	byte_count = params + 1 /* pad */ ;
5337 	pSMB->ParameterCount = cpu_to_le16(params);
5338 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5339 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5340 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5341 	pSMB->SetupCount = 1;
5342 	pSMB->Reserved3 = 0;
5343 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5344 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5345 	inc_rfc1001_len(pSMB, byte_count);
5346 	pSMB->ByteCount = cpu_to_le16(byte_count);
5347 
5348 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5349 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5350 	if (rc) {
5351 		cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5352 	} else {		/* decode response */
5353 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5354 
5355 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5356 			rc = -EIO;	/* bad smb */
5357 		} else {
5358 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5359 			response_data =
5360 			    (FILE_SYSTEM_UNIX_INFO
5361 			     *) (((char *) &pSMBr->hdr.Protocol) +
5362 				 data_offset);
5363 			memcpy(&tcon->fsUnixInfo, response_data,
5364 			       sizeof(FILE_SYSTEM_UNIX_INFO));
5365 		}
5366 	}
5367 	cifs_buf_release(pSMB);
5368 
5369 	if (rc == -EAGAIN)
5370 		goto QFSUnixRetry;
5371 
5372 
5373 	return rc;
5374 }
5375 
5376 int
CIFSSMBSetFSUnixInfo(const int xid,struct cifs_tcon * tcon,__u64 cap)5377 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
5378 {
5379 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5380 	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5381 	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5382 	int rc = 0;
5383 	int bytes_returned = 0;
5384 	__u16 params, param_offset, offset, byte_count;
5385 
5386 	cFYI(1, "In SETFSUnixInfo");
5387 SETFSUnixRetry:
5388 	/* BB switch to small buf init to save memory */
5389 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5390 					(void **) &pSMB, (void **) &pSMBr);
5391 	if (rc)
5392 		return rc;
5393 
5394 	params = 4;	/* 2 bytes zero followed by info level. */
5395 	pSMB->MaxSetupCount = 0;
5396 	pSMB->Reserved = 0;
5397 	pSMB->Flags = 0;
5398 	pSMB->Timeout = 0;
5399 	pSMB->Reserved2 = 0;
5400 	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5401 				- 4;
5402 	offset = param_offset + params;
5403 
5404 	pSMB->MaxParameterCount = cpu_to_le16(4);
5405 	/* BB find exact max SMB PDU from sess structure BB */
5406 	pSMB->MaxDataCount = cpu_to_le16(100);
5407 	pSMB->SetupCount = 1;
5408 	pSMB->Reserved3 = 0;
5409 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5410 	byte_count = 1 /* pad */ + params + 12;
5411 
5412 	pSMB->DataCount = cpu_to_le16(12);
5413 	pSMB->ParameterCount = cpu_to_le16(params);
5414 	pSMB->TotalDataCount = pSMB->DataCount;
5415 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5416 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5417 	pSMB->DataOffset = cpu_to_le16(offset);
5418 
5419 	/* Params. */
5420 	pSMB->FileNum = 0;
5421 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5422 
5423 	/* Data. */
5424 	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5425 	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5426 	pSMB->ClientUnixCap = cpu_to_le64(cap);
5427 
5428 	inc_rfc1001_len(pSMB, byte_count);
5429 	pSMB->ByteCount = cpu_to_le16(byte_count);
5430 
5431 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5432 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5433 	if (rc) {
5434 		cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5435 	} else {		/* decode response */
5436 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5437 		if (rc)
5438 			rc = -EIO;	/* bad smb */
5439 	}
5440 	cifs_buf_release(pSMB);
5441 
5442 	if (rc == -EAGAIN)
5443 		goto SETFSUnixRetry;
5444 
5445 	return rc;
5446 }
5447 
5448 
5449 
5450 int
CIFSSMBQFSPosixInfo(const int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5451 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5452 		   struct kstatfs *FSData)
5453 {
5454 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5455 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5456 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5457 	FILE_SYSTEM_POSIX_INFO *response_data;
5458 	int rc = 0;
5459 	int bytes_returned = 0;
5460 	__u16 params, byte_count;
5461 
5462 	cFYI(1, "In QFSPosixInfo");
5463 QFSPosixRetry:
5464 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5465 		      (void **) &pSMBr);
5466 	if (rc)
5467 		return rc;
5468 
5469 	params = 2;	/* level */
5470 	pSMB->TotalDataCount = 0;
5471 	pSMB->DataCount = 0;
5472 	pSMB->DataOffset = 0;
5473 	pSMB->MaxParameterCount = cpu_to_le16(2);
5474 	/* BB find exact max SMB PDU from sess structure BB */
5475 	pSMB->MaxDataCount = cpu_to_le16(100);
5476 	pSMB->MaxSetupCount = 0;
5477 	pSMB->Reserved = 0;
5478 	pSMB->Flags = 0;
5479 	pSMB->Timeout = 0;
5480 	pSMB->Reserved2 = 0;
5481 	byte_count = params + 1 /* pad */ ;
5482 	pSMB->ParameterCount = cpu_to_le16(params);
5483 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5484 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5485 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5486 	pSMB->SetupCount = 1;
5487 	pSMB->Reserved3 = 0;
5488 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5489 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5490 	inc_rfc1001_len(pSMB, byte_count);
5491 	pSMB->ByteCount = cpu_to_le16(byte_count);
5492 
5493 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5494 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5495 	if (rc) {
5496 		cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5497 	} else {		/* decode response */
5498 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5499 
5500 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5501 			rc = -EIO;	/* bad smb */
5502 		} else {
5503 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5504 			response_data =
5505 			    (FILE_SYSTEM_POSIX_INFO
5506 			     *) (((char *) &pSMBr->hdr.Protocol) +
5507 				 data_offset);
5508 			FSData->f_bsize =
5509 					le32_to_cpu(response_data->BlockSize);
5510 			FSData->f_blocks =
5511 					le64_to_cpu(response_data->TotalBlocks);
5512 			FSData->f_bfree =
5513 			    le64_to_cpu(response_data->BlocksAvail);
5514 			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5515 				FSData->f_bavail = FSData->f_bfree;
5516 			} else {
5517 				FSData->f_bavail =
5518 				    le64_to_cpu(response_data->UserBlocksAvail);
5519 			}
5520 			if (response_data->TotalFileNodes != cpu_to_le64(-1))
5521 				FSData->f_files =
5522 				     le64_to_cpu(response_data->TotalFileNodes);
5523 			if (response_data->FreeFileNodes != cpu_to_le64(-1))
5524 				FSData->f_ffree =
5525 				      le64_to_cpu(response_data->FreeFileNodes);
5526 		}
5527 	}
5528 	cifs_buf_release(pSMB);
5529 
5530 	if (rc == -EAGAIN)
5531 		goto QFSPosixRetry;
5532 
5533 	return rc;
5534 }
5535 
5536 
5537 /* We can not use write of zero bytes trick to
5538    set file size due to need for large file support.  Also note that
5539    this SetPathInfo is preferred to SetFileInfo based method in next
5540    routine which is only needed to work around a sharing violation bug
5541    in Samba which this routine can run into */
5542 
5543 int
CIFSSMBSetEOF(const int xid,struct cifs_tcon * tcon,const char * fileName,__u64 size,bool SetAllocation,const struct nls_table * nls_codepage,int remap)5544 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5545 	      __u64 size, bool SetAllocation,
5546 	      const struct nls_table *nls_codepage, int remap)
5547 {
5548 	struct smb_com_transaction2_spi_req *pSMB = NULL;
5549 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5550 	struct file_end_of_file_info *parm_data;
5551 	int name_len;
5552 	int rc = 0;
5553 	int bytes_returned = 0;
5554 	__u16 params, byte_count, data_count, param_offset, offset;
5555 
5556 	cFYI(1, "In SetEOF");
5557 SetEOFRetry:
5558 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5559 		      (void **) &pSMBr);
5560 	if (rc)
5561 		return rc;
5562 
5563 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5564 		name_len =
5565 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5566 				       PATH_MAX, nls_codepage, remap);
5567 		name_len++;	/* trailing null */
5568 		name_len *= 2;
5569 	} else {	/* BB improve the check for buffer overruns BB */
5570 		name_len = strnlen(fileName, PATH_MAX);
5571 		name_len++;	/* trailing null */
5572 		strncpy(pSMB->FileName, fileName, name_len);
5573 	}
5574 	params = 6 + name_len;
5575 	data_count = sizeof(struct file_end_of_file_info);
5576 	pSMB->MaxParameterCount = cpu_to_le16(2);
5577 	pSMB->MaxDataCount = cpu_to_le16(4100);
5578 	pSMB->MaxSetupCount = 0;
5579 	pSMB->Reserved = 0;
5580 	pSMB->Flags = 0;
5581 	pSMB->Timeout = 0;
5582 	pSMB->Reserved2 = 0;
5583 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5584 				InformationLevel) - 4;
5585 	offset = param_offset + params;
5586 	if (SetAllocation) {
5587 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5588 			pSMB->InformationLevel =
5589 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5590 		else
5591 			pSMB->InformationLevel =
5592 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5593 	} else /* Set File Size */  {
5594 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5595 		    pSMB->InformationLevel =
5596 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5597 	    else
5598 		    pSMB->InformationLevel =
5599 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5600 	}
5601 
5602 	parm_data =
5603 	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5604 				       offset);
5605 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5606 	pSMB->DataOffset = cpu_to_le16(offset);
5607 	pSMB->SetupCount = 1;
5608 	pSMB->Reserved3 = 0;
5609 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5610 	byte_count = 3 /* pad */  + params + data_count;
5611 	pSMB->DataCount = cpu_to_le16(data_count);
5612 	pSMB->TotalDataCount = pSMB->DataCount;
5613 	pSMB->ParameterCount = cpu_to_le16(params);
5614 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5615 	pSMB->Reserved4 = 0;
5616 	inc_rfc1001_len(pSMB, byte_count);
5617 	parm_data->FileSize = cpu_to_le64(size);
5618 	pSMB->ByteCount = cpu_to_le16(byte_count);
5619 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5620 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5621 	if (rc)
5622 		cFYI(1, "SetPathInfo (file size) returned %d", rc);
5623 
5624 	cifs_buf_release(pSMB);
5625 
5626 	if (rc == -EAGAIN)
5627 		goto SetEOFRetry;
5628 
5629 	return rc;
5630 }
5631 
5632 int
CIFSSMBSetFileSize(const int xid,struct cifs_tcon * tcon,__u64 size,__u16 fid,__u32 pid_of_opener,bool SetAllocation)5633 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5634 		   __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5635 {
5636 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5637 	struct file_end_of_file_info *parm_data;
5638 	int rc = 0;
5639 	__u16 params, param_offset, offset, byte_count, count;
5640 
5641 	cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5642 			(long long)size);
5643 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5644 
5645 	if (rc)
5646 		return rc;
5647 
5648 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5649 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5650 
5651 	params = 6;
5652 	pSMB->MaxSetupCount = 0;
5653 	pSMB->Reserved = 0;
5654 	pSMB->Flags = 0;
5655 	pSMB->Timeout = 0;
5656 	pSMB->Reserved2 = 0;
5657 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5658 	offset = param_offset + params;
5659 
5660 	count = sizeof(struct file_end_of_file_info);
5661 	pSMB->MaxParameterCount = cpu_to_le16(2);
5662 	/* BB find exact max SMB PDU from sess structure BB */
5663 	pSMB->MaxDataCount = cpu_to_le16(1000);
5664 	pSMB->SetupCount = 1;
5665 	pSMB->Reserved3 = 0;
5666 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5667 	byte_count = 3 /* pad */  + params + count;
5668 	pSMB->DataCount = cpu_to_le16(count);
5669 	pSMB->ParameterCount = cpu_to_le16(params);
5670 	pSMB->TotalDataCount = pSMB->DataCount;
5671 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5672 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5673 	parm_data =
5674 		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5675 				+ offset);
5676 	pSMB->DataOffset = cpu_to_le16(offset);
5677 	parm_data->FileSize = cpu_to_le64(size);
5678 	pSMB->Fid = fid;
5679 	if (SetAllocation) {
5680 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5681 			pSMB->InformationLevel =
5682 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5683 		else
5684 			pSMB->InformationLevel =
5685 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5686 	} else /* Set File Size */  {
5687 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5688 		    pSMB->InformationLevel =
5689 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5690 	    else
5691 		    pSMB->InformationLevel =
5692 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5693 	}
5694 	pSMB->Reserved4 = 0;
5695 	inc_rfc1001_len(pSMB, byte_count);
5696 	pSMB->ByteCount = cpu_to_le16(byte_count);
5697 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5698 	if (rc) {
5699 		cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5700 	}
5701 
5702 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5703 		since file handle passed in no longer valid */
5704 
5705 	return rc;
5706 }
5707 
5708 /* Some legacy servers such as NT4 require that the file times be set on
5709    an open handle, rather than by pathname - this is awkward due to
5710    potential access conflicts on the open, but it is unavoidable for these
5711    old servers since the only other choice is to go from 100 nanosecond DCE
5712    time and resort to the original setpathinfo level which takes the ancient
5713    DOS time format with 2 second granularity */
5714 int
CIFSSMBSetFileInfo(const int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5715 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5716 		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5717 {
5718 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5719 	char *data_offset;
5720 	int rc = 0;
5721 	__u16 params, param_offset, offset, byte_count, count;
5722 
5723 	cFYI(1, "Set Times (via SetFileInfo)");
5724 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5725 
5726 	if (rc)
5727 		return rc;
5728 
5729 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5730 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5731 
5732 	params = 6;
5733 	pSMB->MaxSetupCount = 0;
5734 	pSMB->Reserved = 0;
5735 	pSMB->Flags = 0;
5736 	pSMB->Timeout = 0;
5737 	pSMB->Reserved2 = 0;
5738 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5739 	offset = param_offset + params;
5740 
5741 	data_offset = (char *)pSMB +
5742 			offsetof(struct smb_hdr, Protocol) + offset;
5743 
5744 	count = sizeof(FILE_BASIC_INFO);
5745 	pSMB->MaxParameterCount = cpu_to_le16(2);
5746 	/* BB find max SMB PDU from sess */
5747 	pSMB->MaxDataCount = cpu_to_le16(1000);
5748 	pSMB->SetupCount = 1;
5749 	pSMB->Reserved3 = 0;
5750 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5751 	byte_count = 3 /* pad */  + params + count;
5752 	pSMB->DataCount = cpu_to_le16(count);
5753 	pSMB->ParameterCount = cpu_to_le16(params);
5754 	pSMB->TotalDataCount = pSMB->DataCount;
5755 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5756 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5757 	pSMB->DataOffset = cpu_to_le16(offset);
5758 	pSMB->Fid = fid;
5759 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5760 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5761 	else
5762 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5763 	pSMB->Reserved4 = 0;
5764 	inc_rfc1001_len(pSMB, byte_count);
5765 	pSMB->ByteCount = cpu_to_le16(byte_count);
5766 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5767 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5768 	if (rc)
5769 		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5770 
5771 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5772 		since file handle passed in no longer valid */
5773 
5774 	return rc;
5775 }
5776 
5777 int
CIFSSMBSetFileDisposition(const int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5778 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5779 			  bool delete_file, __u16 fid, __u32 pid_of_opener)
5780 {
5781 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5782 	char *data_offset;
5783 	int rc = 0;
5784 	__u16 params, param_offset, offset, byte_count, count;
5785 
5786 	cFYI(1, "Set File Disposition (via SetFileInfo)");
5787 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5788 
5789 	if (rc)
5790 		return rc;
5791 
5792 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5793 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5794 
5795 	params = 6;
5796 	pSMB->MaxSetupCount = 0;
5797 	pSMB->Reserved = 0;
5798 	pSMB->Flags = 0;
5799 	pSMB->Timeout = 0;
5800 	pSMB->Reserved2 = 0;
5801 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5802 	offset = param_offset + params;
5803 
5804 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5805 
5806 	count = 1;
5807 	pSMB->MaxParameterCount = cpu_to_le16(2);
5808 	/* BB find max SMB PDU from sess */
5809 	pSMB->MaxDataCount = cpu_to_le16(1000);
5810 	pSMB->SetupCount = 1;
5811 	pSMB->Reserved3 = 0;
5812 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5813 	byte_count = 3 /* pad */  + params + count;
5814 	pSMB->DataCount = cpu_to_le16(count);
5815 	pSMB->ParameterCount = cpu_to_le16(params);
5816 	pSMB->TotalDataCount = pSMB->DataCount;
5817 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5818 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5819 	pSMB->DataOffset = cpu_to_le16(offset);
5820 	pSMB->Fid = fid;
5821 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5822 	pSMB->Reserved4 = 0;
5823 	inc_rfc1001_len(pSMB, byte_count);
5824 	pSMB->ByteCount = cpu_to_le16(byte_count);
5825 	*data_offset = delete_file ? 1 : 0;
5826 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5827 	if (rc)
5828 		cFYI(1, "Send error in SetFileDisposition = %d", rc);
5829 
5830 	return rc;
5831 }
5832 
5833 int
CIFSSMBSetPathInfo(const int xid,struct cifs_tcon * tcon,const char * fileName,const FILE_BASIC_INFO * data,const struct nls_table * nls_codepage,int remap)5834 CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
5835 		   const char *fileName, const FILE_BASIC_INFO *data,
5836 		   const struct nls_table *nls_codepage, int remap)
5837 {
5838 	TRANSACTION2_SPI_REQ *pSMB = NULL;
5839 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5840 	int name_len;
5841 	int rc = 0;
5842 	int bytes_returned = 0;
5843 	char *data_offset;
5844 	__u16 params, param_offset, offset, byte_count, count;
5845 
5846 	cFYI(1, "In SetTimes");
5847 
5848 SetTimesRetry:
5849 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5850 		      (void **) &pSMBr);
5851 	if (rc)
5852 		return rc;
5853 
5854 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5855 		name_len =
5856 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5857 				       PATH_MAX, nls_codepage, remap);
5858 		name_len++;	/* trailing null */
5859 		name_len *= 2;
5860 	} else {	/* BB improve the check for buffer overruns BB */
5861 		name_len = strnlen(fileName, PATH_MAX);
5862 		name_len++;	/* trailing null */
5863 		strncpy(pSMB->FileName, fileName, name_len);
5864 	}
5865 
5866 	params = 6 + name_len;
5867 	count = sizeof(FILE_BASIC_INFO);
5868 	pSMB->MaxParameterCount = cpu_to_le16(2);
5869 	/* BB find max SMB PDU from sess structure BB */
5870 	pSMB->MaxDataCount = cpu_to_le16(1000);
5871 	pSMB->MaxSetupCount = 0;
5872 	pSMB->Reserved = 0;
5873 	pSMB->Flags = 0;
5874 	pSMB->Timeout = 0;
5875 	pSMB->Reserved2 = 0;
5876 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5877 				InformationLevel) - 4;
5878 	offset = param_offset + params;
5879 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5880 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5881 	pSMB->DataOffset = cpu_to_le16(offset);
5882 	pSMB->SetupCount = 1;
5883 	pSMB->Reserved3 = 0;
5884 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5885 	byte_count = 3 /* pad */  + params + count;
5886 
5887 	pSMB->DataCount = cpu_to_le16(count);
5888 	pSMB->ParameterCount = cpu_to_le16(params);
5889 	pSMB->TotalDataCount = pSMB->DataCount;
5890 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5891 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5892 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5893 	else
5894 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5895 	pSMB->Reserved4 = 0;
5896 	inc_rfc1001_len(pSMB, byte_count);
5897 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5898 	pSMB->ByteCount = cpu_to_le16(byte_count);
5899 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5900 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5901 	if (rc)
5902 		cFYI(1, "SetPathInfo (times) returned %d", rc);
5903 
5904 	cifs_buf_release(pSMB);
5905 
5906 	if (rc == -EAGAIN)
5907 		goto SetTimesRetry;
5908 
5909 	return rc;
5910 }
5911 
5912 /* Can not be used to set time stamps yet (due to old DOS time format) */
5913 /* Can be used to set attributes */
5914 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5915 	  handling it anyway and NT4 was what we thought it would be needed for
5916 	  Do not delete it until we prove whether needed for Win9x though */
5917 int
5918 CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
5919 		__u16 dos_attrs, const struct nls_table *nls_codepage)
5920 {
5921 	SETATTR_REQ *pSMB = NULL;
5922 	SETATTR_RSP *pSMBr = NULL;
5923 	int rc = 0;
5924 	int bytes_returned;
5925 	int name_len;
5926 
5927 	cFYI(1, "In SetAttrLegacy");
5928 
5929 SetAttrLgcyRetry:
5930 	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5931 		      (void **) &pSMBr);
5932 	if (rc)
5933 		return rc;
5934 
5935 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5936 		name_len =
5937 			ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5938 				       PATH_MAX, nls_codepage);
5939 		name_len++;     /* trailing null */
5940 		name_len *= 2;
5941 	} else {	/* BB improve the check for buffer overruns BB */
5942 		name_len = strnlen(fileName, PATH_MAX);
5943 		name_len++;     /* trailing null */
5944 		strncpy(pSMB->fileName, fileName, name_len);
5945 	}
5946 	pSMB->attr = cpu_to_le16(dos_attrs);
5947 	pSMB->BufferFormat = 0x04;
5948 	inc_rfc1001_len(pSMB, name_len + 1);
5949 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
5950 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5951 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5952 	if (rc)
5953 		cFYI(1, "Error in LegacySetAttr = %d", rc);
5954 
5955 	cifs_buf_release(pSMB);
5956 
5957 	if (rc == -EAGAIN)
5958 		goto SetAttrLgcyRetry;
5959 
5960 	return rc;
5961 }
5962 #endif /* temporarily unneeded SetAttr legacy function */
5963 
5964 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5965 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5966 			const struct cifs_unix_set_info_args *args)
5967 {
5968 	u64 mode = args->mode;
5969 
5970 	/*
5971 	 * Samba server ignores set of file size to zero due to bugs in some
5972 	 * older clients, but we should be precise - we use SetFileSize to
5973 	 * set file size and do not want to truncate file size to zero
5974 	 * accidentally as happened on one Samba server beta by putting
5975 	 * zero instead of -1 here
5976 	 */
5977 	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5978 	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5979 	data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5980 	data_offset->LastAccessTime = cpu_to_le64(args->atime);
5981 	data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5982 	data_offset->Uid = cpu_to_le64(args->uid);
5983 	data_offset->Gid = cpu_to_le64(args->gid);
5984 	/* better to leave device as zero when it is  */
5985 	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5986 	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5987 	data_offset->Permissions = cpu_to_le64(mode);
5988 
5989 	if (S_ISREG(mode))
5990 		data_offset->Type = cpu_to_le32(UNIX_FILE);
5991 	else if (S_ISDIR(mode))
5992 		data_offset->Type = cpu_to_le32(UNIX_DIR);
5993 	else if (S_ISLNK(mode))
5994 		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5995 	else if (S_ISCHR(mode))
5996 		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5997 	else if (S_ISBLK(mode))
5998 		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5999 	else if (S_ISFIFO(mode))
6000 		data_offset->Type = cpu_to_le32(UNIX_FIFO);
6001 	else if (S_ISSOCK(mode))
6002 		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
6003 }
6004 
6005 int
CIFSSMBUnixSetFileInfo(const int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)6006 CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
6007 		       const struct cifs_unix_set_info_args *args,
6008 		       u16 fid, u32 pid_of_opener)
6009 {
6010 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
6011 	char *data_offset;
6012 	int rc = 0;
6013 	u16 params, param_offset, offset, byte_count, count;
6014 
6015 	cFYI(1, "Set Unix Info (via SetFileInfo)");
6016 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
6017 
6018 	if (rc)
6019 		return rc;
6020 
6021 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
6022 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
6023 
6024 	params = 6;
6025 	pSMB->MaxSetupCount = 0;
6026 	pSMB->Reserved = 0;
6027 	pSMB->Flags = 0;
6028 	pSMB->Timeout = 0;
6029 	pSMB->Reserved2 = 0;
6030 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6031 	offset = param_offset + params;
6032 
6033 	data_offset = (char *)pSMB +
6034 			offsetof(struct smb_hdr, Protocol) + offset;
6035 
6036 	count = sizeof(FILE_UNIX_BASIC_INFO);
6037 
6038 	pSMB->MaxParameterCount = cpu_to_le16(2);
6039 	/* BB find max SMB PDU from sess */
6040 	pSMB->MaxDataCount = cpu_to_le16(1000);
6041 	pSMB->SetupCount = 1;
6042 	pSMB->Reserved3 = 0;
6043 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6044 	byte_count = 3 /* pad */  + params + count;
6045 	pSMB->DataCount = cpu_to_le16(count);
6046 	pSMB->ParameterCount = cpu_to_le16(params);
6047 	pSMB->TotalDataCount = pSMB->DataCount;
6048 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6049 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6050 	pSMB->DataOffset = cpu_to_le16(offset);
6051 	pSMB->Fid = fid;
6052 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6053 	pSMB->Reserved4 = 0;
6054 	inc_rfc1001_len(pSMB, byte_count);
6055 	pSMB->ByteCount = cpu_to_le16(byte_count);
6056 
6057 	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6058 
6059 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6060 	if (rc)
6061 		cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
6062 
6063 	/* Note: On -EAGAIN error only caller can retry on handle based calls
6064 		since file handle passed in no longer valid */
6065 
6066 	return rc;
6067 }
6068 
6069 int
CIFSSMBUnixSetPathInfo(const int xid,struct cifs_tcon * tcon,char * fileName,const struct cifs_unix_set_info_args * args,const struct nls_table * nls_codepage,int remap)6070 CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
6071 		       const struct cifs_unix_set_info_args *args,
6072 		       const struct nls_table *nls_codepage, int remap)
6073 {
6074 	TRANSACTION2_SPI_REQ *pSMB = NULL;
6075 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
6076 	int name_len;
6077 	int rc = 0;
6078 	int bytes_returned = 0;
6079 	FILE_UNIX_BASIC_INFO *data_offset;
6080 	__u16 params, param_offset, offset, count, byte_count;
6081 
6082 	cFYI(1, "In SetUID/GID/Mode");
6083 setPermsRetry:
6084 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6085 		      (void **) &pSMBr);
6086 	if (rc)
6087 		return rc;
6088 
6089 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6090 		name_len =
6091 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6092 				       PATH_MAX, nls_codepage, remap);
6093 		name_len++;	/* trailing null */
6094 		name_len *= 2;
6095 	} else {	/* BB improve the check for buffer overruns BB */
6096 		name_len = strnlen(fileName, PATH_MAX);
6097 		name_len++;	/* trailing null */
6098 		strncpy(pSMB->FileName, fileName, name_len);
6099 	}
6100 
6101 	params = 6 + name_len;
6102 	count = sizeof(FILE_UNIX_BASIC_INFO);
6103 	pSMB->MaxParameterCount = cpu_to_le16(2);
6104 	/* BB find max SMB PDU from sess structure BB */
6105 	pSMB->MaxDataCount = cpu_to_le16(1000);
6106 	pSMB->MaxSetupCount = 0;
6107 	pSMB->Reserved = 0;
6108 	pSMB->Flags = 0;
6109 	pSMB->Timeout = 0;
6110 	pSMB->Reserved2 = 0;
6111 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6112 				InformationLevel) - 4;
6113 	offset = param_offset + params;
6114 	data_offset =
6115 	    (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6116 				      offset);
6117 	memset(data_offset, 0, count);
6118 	pSMB->DataOffset = cpu_to_le16(offset);
6119 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6120 	pSMB->SetupCount = 1;
6121 	pSMB->Reserved3 = 0;
6122 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6123 	byte_count = 3 /* pad */  + params + count;
6124 	pSMB->ParameterCount = cpu_to_le16(params);
6125 	pSMB->DataCount = cpu_to_le16(count);
6126 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6127 	pSMB->TotalDataCount = pSMB->DataCount;
6128 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6129 	pSMB->Reserved4 = 0;
6130 	inc_rfc1001_len(pSMB, byte_count);
6131 
6132 	cifs_fill_unix_set_info(data_offset, args);
6133 
6134 	pSMB->ByteCount = cpu_to_le16(byte_count);
6135 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6136 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6137 	if (rc)
6138 		cFYI(1, "SetPathInfo (perms) returned %d", rc);
6139 
6140 	cifs_buf_release(pSMB);
6141 	if (rc == -EAGAIN)
6142 		goto setPermsRetry;
6143 	return rc;
6144 }
6145 
6146 #ifdef CONFIG_CIFS_XATTR
6147 /*
6148  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6149  * function used by listxattr and getxattr type calls. When ea_name is set,
6150  * it looks for that attribute name and stuffs that value into the EAData
6151  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6152  * buffer. In both cases, the return value is either the length of the
6153  * resulting data or a negative error code. If EAData is a NULL pointer then
6154  * the data isn't copied to it, but the length is returned.
6155  */
6156 ssize_t
CIFSSMBQAllEAs(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,const unsigned char * ea_name,char * EAData,size_t buf_size,const struct nls_table * nls_codepage,int remap)6157 CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
6158 		const unsigned char *searchName, const unsigned char *ea_name,
6159 		char *EAData, size_t buf_size,
6160 		const struct nls_table *nls_codepage, int remap)
6161 {
6162 		/* BB assumes one setup word */
6163 	TRANSACTION2_QPI_REQ *pSMB = NULL;
6164 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
6165 	int rc = 0;
6166 	int bytes_returned;
6167 	int list_len;
6168 	struct fealist *ea_response_data;
6169 	struct fea *temp_fea;
6170 	char *temp_ptr;
6171 	char *end_of_smb;
6172 	__u16 params, byte_count, data_offset;
6173 	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6174 
6175 	cFYI(1, "In Query All EAs path %s", searchName);
6176 QAllEAsRetry:
6177 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6178 		      (void **) &pSMBr);
6179 	if (rc)
6180 		return rc;
6181 
6182 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6183 		list_len =
6184 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6185 				       PATH_MAX, nls_codepage, remap);
6186 		list_len++;	/* trailing null */
6187 		list_len *= 2;
6188 	} else {	/* BB improve the check for buffer overruns BB */
6189 		list_len = strnlen(searchName, PATH_MAX);
6190 		list_len++;	/* trailing null */
6191 		strncpy(pSMB->FileName, searchName, list_len);
6192 	}
6193 
6194 	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6195 	pSMB->TotalDataCount = 0;
6196 	pSMB->MaxParameterCount = cpu_to_le16(2);
6197 	/* BB find exact max SMB PDU from sess structure BB */
6198 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6199 	pSMB->MaxSetupCount = 0;
6200 	pSMB->Reserved = 0;
6201 	pSMB->Flags = 0;
6202 	pSMB->Timeout = 0;
6203 	pSMB->Reserved2 = 0;
6204 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
6205 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6206 	pSMB->DataCount = 0;
6207 	pSMB->DataOffset = 0;
6208 	pSMB->SetupCount = 1;
6209 	pSMB->Reserved3 = 0;
6210 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6211 	byte_count = params + 1 /* pad */ ;
6212 	pSMB->TotalParameterCount = cpu_to_le16(params);
6213 	pSMB->ParameterCount = pSMB->TotalParameterCount;
6214 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6215 	pSMB->Reserved4 = 0;
6216 	inc_rfc1001_len(pSMB, byte_count);
6217 	pSMB->ByteCount = cpu_to_le16(byte_count);
6218 
6219 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6220 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6221 	if (rc) {
6222 		cFYI(1, "Send error in QueryAllEAs = %d", rc);
6223 		goto QAllEAsOut;
6224 	}
6225 
6226 
6227 	/* BB also check enough total bytes returned */
6228 	/* BB we need to improve the validity checking
6229 	of these trans2 responses */
6230 
6231 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6232 	if (rc || get_bcc(&pSMBr->hdr) < 4) {
6233 		rc = -EIO;	/* bad smb */
6234 		goto QAllEAsOut;
6235 	}
6236 
6237 	/* check that length of list is not more than bcc */
6238 	/* check that each entry does not go beyond length
6239 	   of list */
6240 	/* check that each element of each entry does not
6241 	   go beyond end of list */
6242 	/* validate_trans2_offsets() */
6243 	/* BB check if start of smb + data_offset > &bcc+ bcc */
6244 
6245 	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6246 	ea_response_data = (struct fealist *)
6247 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
6248 
6249 	list_len = le32_to_cpu(ea_response_data->list_len);
6250 	cFYI(1, "ea length %d", list_len);
6251 	if (list_len <= 8) {
6252 		cFYI(1, "empty EA list returned from server");
6253 		goto QAllEAsOut;
6254 	}
6255 
6256 	/* make sure list_len doesn't go past end of SMB */
6257 	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6258 	if ((char *)ea_response_data + list_len > end_of_smb) {
6259 		cFYI(1, "EA list appears to go beyond SMB");
6260 		rc = -EIO;
6261 		goto QAllEAsOut;
6262 	}
6263 
6264 	/* account for ea list len */
6265 	list_len -= 4;
6266 	temp_fea = ea_response_data->list;
6267 	temp_ptr = (char *)temp_fea;
6268 	while (list_len > 0) {
6269 		unsigned int name_len;
6270 		__u16 value_len;
6271 
6272 		list_len -= 4;
6273 		temp_ptr += 4;
6274 		/* make sure we can read name_len and value_len */
6275 		if (list_len < 0) {
6276 			cFYI(1, "EA entry goes beyond length of list");
6277 			rc = -EIO;
6278 			goto QAllEAsOut;
6279 		}
6280 
6281 		name_len = temp_fea->name_len;
6282 		value_len = le16_to_cpu(temp_fea->value_len);
6283 		list_len -= name_len + 1 + value_len;
6284 		if (list_len < 0) {
6285 			cFYI(1, "EA entry goes beyond length of list");
6286 			rc = -EIO;
6287 			goto QAllEAsOut;
6288 		}
6289 
6290 		if (ea_name) {
6291 			if (ea_name_len == name_len &&
6292 			    memcmp(ea_name, temp_ptr, name_len) == 0) {
6293 				temp_ptr += name_len + 1;
6294 				rc = value_len;
6295 				if (buf_size == 0)
6296 					goto QAllEAsOut;
6297 				if ((size_t)value_len > buf_size) {
6298 					rc = -ERANGE;
6299 					goto QAllEAsOut;
6300 				}
6301 				memcpy(EAData, temp_ptr, value_len);
6302 				goto QAllEAsOut;
6303 			}
6304 		} else {
6305 			/* account for prefix user. and trailing null */
6306 			rc += (5 + 1 + name_len);
6307 			if (rc < (int) buf_size) {
6308 				memcpy(EAData, "user.", 5);
6309 				EAData += 5;
6310 				memcpy(EAData, temp_ptr, name_len);
6311 				EAData += name_len;
6312 				/* null terminate name */
6313 				*EAData = 0;
6314 				++EAData;
6315 			} else if (buf_size == 0) {
6316 				/* skip copy - calc size only */
6317 			} else {
6318 				/* stop before overrun buffer */
6319 				rc = -ERANGE;
6320 				break;
6321 			}
6322 		}
6323 		temp_ptr += name_len + 1 + value_len;
6324 		temp_fea = (struct fea *)temp_ptr;
6325 	}
6326 
6327 	/* didn't find the named attribute */
6328 	if (ea_name)
6329 		rc = -ENODATA;
6330 
6331 QAllEAsOut:
6332 	cifs_buf_release(pSMB);
6333 	if (rc == -EAGAIN)
6334 		goto QAllEAsRetry;
6335 
6336 	return (ssize_t)rc;
6337 }
6338 
6339 int
CIFSSMBSetEA(const int xid,struct cifs_tcon * tcon,const char * fileName,const char * ea_name,const void * ea_value,const __u16 ea_value_len,const struct nls_table * nls_codepage,int remap)6340 CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
6341 	     const char *ea_name, const void *ea_value,
6342 	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
6343 	     int remap)
6344 {
6345 	struct smb_com_transaction2_spi_req *pSMB = NULL;
6346 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6347 	struct fealist *parm_data;
6348 	int name_len;
6349 	int rc = 0;
6350 	int bytes_returned = 0;
6351 	__u16 params, param_offset, byte_count, offset, count;
6352 
6353 	cFYI(1, "In SetEA");
6354 SetEARetry:
6355 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6356 		      (void **) &pSMBr);
6357 	if (rc)
6358 		return rc;
6359 
6360 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6361 		name_len =
6362 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6363 				       PATH_MAX, nls_codepage, remap);
6364 		name_len++;	/* trailing null */
6365 		name_len *= 2;
6366 	} else {	/* BB improve the check for buffer overruns BB */
6367 		name_len = strnlen(fileName, PATH_MAX);
6368 		name_len++;	/* trailing null */
6369 		strncpy(pSMB->FileName, fileName, name_len);
6370 	}
6371 
6372 	params = 6 + name_len;
6373 
6374 	/* done calculating parms using name_len of file name,
6375 	now use name_len to calculate length of ea name
6376 	we are going to create in the inode xattrs */
6377 	if (ea_name == NULL)
6378 		name_len = 0;
6379 	else
6380 		name_len = strnlen(ea_name, 255);
6381 
6382 	count = sizeof(*parm_data) + ea_value_len + name_len;
6383 	pSMB->MaxParameterCount = cpu_to_le16(2);
6384 	/* BB find max SMB PDU from sess */
6385 	pSMB->MaxDataCount = cpu_to_le16(1000);
6386 	pSMB->MaxSetupCount = 0;
6387 	pSMB->Reserved = 0;
6388 	pSMB->Flags = 0;
6389 	pSMB->Timeout = 0;
6390 	pSMB->Reserved2 = 0;
6391 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6392 				InformationLevel) - 4;
6393 	offset = param_offset + params;
6394 	pSMB->InformationLevel =
6395 		cpu_to_le16(SMB_SET_FILE_EA);
6396 
6397 	parm_data =
6398 		(struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6399 				       offset);
6400 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6401 	pSMB->DataOffset = cpu_to_le16(offset);
6402 	pSMB->SetupCount = 1;
6403 	pSMB->Reserved3 = 0;
6404 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6405 	byte_count = 3 /* pad */  + params + count;
6406 	pSMB->DataCount = cpu_to_le16(count);
6407 	parm_data->list_len = cpu_to_le32(count);
6408 	parm_data->list[0].EA_flags = 0;
6409 	/* we checked above that name len is less than 255 */
6410 	parm_data->list[0].name_len = (__u8)name_len;
6411 	/* EA names are always ASCII */
6412 	if (ea_name)
6413 		strncpy(parm_data->list[0].name, ea_name, name_len);
6414 	parm_data->list[0].name[name_len] = 0;
6415 	parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6416 	/* caller ensures that ea_value_len is less than 64K but
6417 	we need to ensure that it fits within the smb */
6418 
6419 	/*BB add length check to see if it would fit in
6420 	     negotiated SMB buffer size BB */
6421 	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
6422 	if (ea_value_len)
6423 		memcpy(parm_data->list[0].name+name_len+1,
6424 		       ea_value, ea_value_len);
6425 
6426 	pSMB->TotalDataCount = pSMB->DataCount;
6427 	pSMB->ParameterCount = cpu_to_le16(params);
6428 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6429 	pSMB->Reserved4 = 0;
6430 	inc_rfc1001_len(pSMB, byte_count);
6431 	pSMB->ByteCount = cpu_to_le16(byte_count);
6432 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6433 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6434 	if (rc)
6435 		cFYI(1, "SetPathInfo (EA) returned %d", rc);
6436 
6437 	cifs_buf_release(pSMB);
6438 
6439 	if (rc == -EAGAIN)
6440 		goto SetEARetry;
6441 
6442 	return rc;
6443 }
6444 #endif
6445 
6446 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6447 /*
6448  *	Years ago the kernel added a "dnotify" function for Samba server,
6449  *	to allow network clients (such as Windows) to display updated
6450  *	lists of files in directory listings automatically when
6451  *	files are added by one user when another user has the
6452  *	same directory open on their desktop.  The Linux cifs kernel
6453  *	client hooked into the kernel side of this interface for
6454  *	the same reason, but ironically when the VFS moved from
6455  *	"dnotify" to "inotify" it became harder to plug in Linux
6456  *	network file system clients (the most obvious use case
6457  *	for notify interfaces is when multiple users can update
6458  *	the contents of the same directory - exactly what network
6459  *	file systems can do) although the server (Samba) could
6460  *	still use it.  For the short term we leave the worker
6461  *	function ifdeffed out (below) until inotify is fixed
6462  *	in the VFS to make it easier to plug in network file
6463  *	system clients.  If inotify turns out to be permanently
6464  *	incompatible for network fs clients, we could instead simply
6465  *	expose this config flag by adding a future cifs (and smb2) notify ioctl.
6466  */
CIFSSMBNotify(const int xid,struct cifs_tcon * tcon,const int notify_subdirs,const __u16 netfid,__u32 filter,struct file * pfile,int multishot,const struct nls_table * nls_codepage)6467 int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
6468 		  const int notify_subdirs, const __u16 netfid,
6469 		  __u32 filter, struct file *pfile, int multishot,
6470 		  const struct nls_table *nls_codepage)
6471 {
6472 	int rc = 0;
6473 	struct smb_com_transaction_change_notify_req *pSMB = NULL;
6474 	struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6475 	struct dir_notify_req *dnotify_req;
6476 	int bytes_returned;
6477 
6478 	cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6479 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6480 		      (void **) &pSMBr);
6481 	if (rc)
6482 		return rc;
6483 
6484 	pSMB->TotalParameterCount = 0 ;
6485 	pSMB->TotalDataCount = 0;
6486 	pSMB->MaxParameterCount = cpu_to_le32(2);
6487 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6488 	pSMB->MaxSetupCount = 4;
6489 	pSMB->Reserved = 0;
6490 	pSMB->ParameterOffset = 0;
6491 	pSMB->DataCount = 0;
6492 	pSMB->DataOffset = 0;
6493 	pSMB->SetupCount = 4; /* single byte does not need le conversion */
6494 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6495 	pSMB->ParameterCount = pSMB->TotalParameterCount;
6496 	if (notify_subdirs)
6497 		pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6498 	pSMB->Reserved2 = 0;
6499 	pSMB->CompletionFilter = cpu_to_le32(filter);
6500 	pSMB->Fid = netfid; /* file handle always le */
6501 	pSMB->ByteCount = 0;
6502 
6503 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6504 			 (struct smb_hdr *)pSMBr, &bytes_returned,
6505 			 CIFS_ASYNC_OP);
6506 	if (rc) {
6507 		cFYI(1, "Error in Notify = %d", rc);
6508 	} else {
6509 		/* Add file to outstanding requests */
6510 		/* BB change to kmem cache alloc */
6511 		dnotify_req = kmalloc(
6512 						sizeof(struct dir_notify_req),
6513 						 GFP_KERNEL);
6514 		if (dnotify_req) {
6515 			dnotify_req->Pid = pSMB->hdr.Pid;
6516 			dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6517 			dnotify_req->Mid = pSMB->hdr.Mid;
6518 			dnotify_req->Tid = pSMB->hdr.Tid;
6519 			dnotify_req->Uid = pSMB->hdr.Uid;
6520 			dnotify_req->netfid = netfid;
6521 			dnotify_req->pfile = pfile;
6522 			dnotify_req->filter = filter;
6523 			dnotify_req->multishot = multishot;
6524 			spin_lock(&GlobalMid_Lock);
6525 			list_add_tail(&dnotify_req->lhead,
6526 					&GlobalDnotifyReqList);
6527 			spin_unlock(&GlobalMid_Lock);
6528 		} else
6529 			rc = -ENOMEM;
6530 	}
6531 	cifs_buf_release(pSMB);
6532 	return rc;
6533 }
6534 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
6535