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