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