• 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 
1493 	/* Let caller know file was created so we can set the mode. */
1494 	/* Do we care about the CreateAction in any other cases? */
1495 	if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1496 		*oplock |= CIFS_CREATE_ACTION;
1497 
1498 	if (buf) {
1499 		/* copy from CreationTime to Attributes */
1500 		memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1501 		/* the file_info buf is endian converted by caller */
1502 		buf->AllocationSize = rsp->AllocationSize;
1503 		buf->EndOfFile = rsp->EndOfFile;
1504 		buf->NumberOfLinks = cpu_to_le32(1);
1505 		buf->DeletePending = 0;
1506 	}
1507 
1508 	cifs_buf_release(req);
1509 	return rc;
1510 }
1511 
1512 /*
1513  * Discard any remaining data in the current SMB. To do this, we borrow the
1514  * current bigbuf.
1515  */
1516 int
cifs_discard_remaining_data(struct TCP_Server_Info * server)1517 cifs_discard_remaining_data(struct TCP_Server_Info *server)
1518 {
1519 	unsigned int rfclen = server->pdu_size;
1520 	int remaining = rfclen + server->vals->header_preamble_size -
1521 		server->total_read;
1522 
1523 	while (remaining > 0) {
1524 		int length;
1525 
1526 		length = cifs_read_from_socket(server, server->bigbuf,
1527 				min_t(unsigned int, remaining,
1528 				    CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1529 		if (length < 0)
1530 			return length;
1531 		server->total_read += length;
1532 		remaining -= length;
1533 	}
1534 
1535 	return 0;
1536 }
1537 
1538 static int
__cifs_readv_discard(struct TCP_Server_Info * server,struct mid_q_entry * mid,bool malformed)1539 __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
1540 		     bool malformed)
1541 {
1542 	int length;
1543 
1544 	length = cifs_discard_remaining_data(server);
1545 	dequeue_mid(mid, malformed);
1546 	mid->resp_buf = server->smallbuf;
1547 	server->smallbuf = NULL;
1548 	return length;
1549 }
1550 
1551 static int
cifs_readv_discard(struct TCP_Server_Info * server,struct mid_q_entry * mid)1552 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1553 {
1554 	struct cifs_readdata *rdata = mid->callback_data;
1555 
1556 	return  __cifs_readv_discard(server, mid, rdata->result);
1557 }
1558 
1559 int
cifs_readv_receive(struct TCP_Server_Info * server,struct mid_q_entry * mid)1560 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1561 {
1562 	int length, len;
1563 	unsigned int data_offset, data_len;
1564 	struct cifs_readdata *rdata = mid->callback_data;
1565 	char *buf = server->smallbuf;
1566 	unsigned int buflen = server->pdu_size +
1567 		server->vals->header_preamble_size;
1568 	bool use_rdma_mr = false;
1569 
1570 	cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1571 		 __func__, mid->mid, rdata->offset, rdata->bytes);
1572 
1573 	/*
1574 	 * read the rest of READ_RSP header (sans Data array), or whatever we
1575 	 * can if there's not enough data. At this point, we've read down to
1576 	 * the Mid.
1577 	 */
1578 	len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1579 							HEADER_SIZE(server) + 1;
1580 
1581 	length = cifs_read_from_socket(server,
1582 				       buf + HEADER_SIZE(server) - 1, len);
1583 	if (length < 0)
1584 		return length;
1585 	server->total_read += length;
1586 
1587 	if (server->ops->is_session_expired &&
1588 	    server->ops->is_session_expired(buf)) {
1589 		cifs_reconnect(server);
1590 		wake_up(&server->response_q);
1591 		return -1;
1592 	}
1593 
1594 	if (server->ops->is_status_pending &&
1595 	    server->ops->is_status_pending(buf, server)) {
1596 		cifs_discard_remaining_data(server);
1597 		return -1;
1598 	}
1599 
1600 	/* set up first two iov for signature check and to get credits */
1601 	rdata->iov[0].iov_base = buf;
1602 	rdata->iov[0].iov_len = server->vals->header_preamble_size;
1603 	rdata->iov[1].iov_base = buf + server->vals->header_preamble_size;
1604 	rdata->iov[1].iov_len =
1605 		server->total_read - server->vals->header_preamble_size;
1606 	cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
1607 		 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1608 	cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
1609 		 rdata->iov[1].iov_base, rdata->iov[1].iov_len);
1610 
1611 	/* Was the SMB read successful? */
1612 	rdata->result = server->ops->map_error(buf, false);
1613 	if (rdata->result != 0) {
1614 		cifs_dbg(FYI, "%s: server returned error %d\n",
1615 			 __func__, rdata->result);
1616 		/* normal error on read response */
1617 		return __cifs_readv_discard(server, mid, false);
1618 	}
1619 
1620 	/* Is there enough to get to the rest of the READ_RSP header? */
1621 	if (server->total_read < server->vals->read_rsp_size) {
1622 		cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1623 			 __func__, server->total_read,
1624 			 server->vals->read_rsp_size);
1625 		rdata->result = -EIO;
1626 		return cifs_readv_discard(server, mid);
1627 	}
1628 
1629 	data_offset = server->ops->read_data_offset(buf) +
1630 		server->vals->header_preamble_size;
1631 	if (data_offset < server->total_read) {
1632 		/*
1633 		 * win2k8 sometimes sends an offset of 0 when the read
1634 		 * is beyond the EOF. Treat it as if the data starts just after
1635 		 * the header.
1636 		 */
1637 		cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1638 			 __func__, data_offset);
1639 		data_offset = server->total_read;
1640 	} else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1641 		/* data_offset is beyond the end of smallbuf */
1642 		cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1643 			 __func__, data_offset);
1644 		rdata->result = -EIO;
1645 		return cifs_readv_discard(server, mid);
1646 	}
1647 
1648 	cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1649 		 __func__, server->total_read, data_offset);
1650 
1651 	len = data_offset - server->total_read;
1652 	if (len > 0) {
1653 		/* read any junk before data into the rest of smallbuf */
1654 		length = cifs_read_from_socket(server,
1655 					       buf + server->total_read, len);
1656 		if (length < 0)
1657 			return length;
1658 		server->total_read += length;
1659 	}
1660 
1661 	/* how much data is in the response? */
1662 #ifdef CONFIG_CIFS_SMB_DIRECT
1663 	use_rdma_mr = rdata->mr;
1664 #endif
1665 	data_len = server->ops->read_data_length(buf, use_rdma_mr);
1666 	if (!use_rdma_mr && (data_offset + data_len > buflen)) {
1667 		/* data_len is corrupt -- discard frame */
1668 		rdata->result = -EIO;
1669 		return cifs_readv_discard(server, mid);
1670 	}
1671 
1672 	length = rdata->read_into_pages(server, rdata, data_len);
1673 	if (length < 0)
1674 		return length;
1675 
1676 	server->total_read += length;
1677 
1678 	cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1679 		 server->total_read, buflen, data_len);
1680 
1681 	/* discard anything left over */
1682 	if (server->total_read < buflen)
1683 		return cifs_readv_discard(server, mid);
1684 
1685 	dequeue_mid(mid, false);
1686 	mid->resp_buf = server->smallbuf;
1687 	server->smallbuf = NULL;
1688 	return length;
1689 }
1690 
1691 static void
cifs_readv_callback(struct mid_q_entry * mid)1692 cifs_readv_callback(struct mid_q_entry *mid)
1693 {
1694 	struct cifs_readdata *rdata = mid->callback_data;
1695 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1696 	struct TCP_Server_Info *server = tcon->ses->server;
1697 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1698 				 .rq_nvec = 2,
1699 				 .rq_pages = rdata->pages,
1700 				 .rq_offset = rdata->page_offset,
1701 				 .rq_npages = rdata->nr_pages,
1702 				 .rq_pagesz = rdata->pagesz,
1703 				 .rq_tailsz = rdata->tailsz };
1704 	struct cifs_credits credits = { .value = 1, .instance = 0 };
1705 
1706 	cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1707 		 __func__, mid->mid, mid->mid_state, rdata->result,
1708 		 rdata->bytes);
1709 
1710 	switch (mid->mid_state) {
1711 	case MID_RESPONSE_RECEIVED:
1712 		/* result already set, check signature */
1713 		if (server->sign) {
1714 			int rc = 0;
1715 
1716 			rc = cifs_verify_signature(&rqst, server,
1717 						  mid->sequence_number);
1718 			if (rc)
1719 				cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1720 					 rc);
1721 		}
1722 		/* FIXME: should this be counted toward the initiating task? */
1723 		task_io_account_read(rdata->got_bytes);
1724 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1725 		break;
1726 	case MID_REQUEST_SUBMITTED:
1727 	case MID_RETRY_NEEDED:
1728 		rdata->result = -EAGAIN;
1729 		if (server->sign && rdata->got_bytes)
1730 			/* reset bytes number since we can not check a sign */
1731 			rdata->got_bytes = 0;
1732 		/* FIXME: should this be counted toward the initiating task? */
1733 		task_io_account_read(rdata->got_bytes);
1734 		cifs_stats_bytes_read(tcon, rdata->got_bytes);
1735 		break;
1736 	default:
1737 		rdata->result = -EIO;
1738 	}
1739 
1740 	queue_work(cifsiod_wq, &rdata->work);
1741 	DeleteMidQEntry(mid);
1742 	add_credits(server, &credits, 0);
1743 }
1744 
1745 /* cifs_async_readv - send an async write, and set up mid to handle result */
1746 int
cifs_async_readv(struct cifs_readdata * rdata)1747 cifs_async_readv(struct cifs_readdata *rdata)
1748 {
1749 	int rc;
1750 	READ_REQ *smb = NULL;
1751 	int wct;
1752 	struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1753 	struct smb_rqst rqst = { .rq_iov = rdata->iov,
1754 				 .rq_nvec = 2 };
1755 
1756 	cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1757 		 __func__, rdata->offset, rdata->bytes);
1758 
1759 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1760 		wct = 12;
1761 	else {
1762 		wct = 10; /* old style read */
1763 		if ((rdata->offset >> 32) > 0)  {
1764 			/* can not handle this big offset for old */
1765 			return -EIO;
1766 		}
1767 	}
1768 
1769 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1770 	if (rc)
1771 		return rc;
1772 
1773 	smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1774 	smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1775 
1776 	smb->AndXCommand = 0xFF;	/* none */
1777 	smb->Fid = rdata->cfile->fid.netfid;
1778 	smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1779 	if (wct == 12)
1780 		smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1781 	smb->Remaining = 0;
1782 	smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1783 	smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1784 	if (wct == 12)
1785 		smb->ByteCount = 0;
1786 	else {
1787 		/* old style read */
1788 		struct smb_com_readx_req *smbr =
1789 			(struct smb_com_readx_req *)smb;
1790 		smbr->ByteCount = 0;
1791 	}
1792 
1793 	/* 4 for RFC1001 length + 1 for BCC */
1794 	rdata->iov[0].iov_base = smb;
1795 	rdata->iov[0].iov_len = 4;
1796 	rdata->iov[1].iov_base = (char *)smb + 4;
1797 	rdata->iov[1].iov_len = get_rfc1002_length(smb);
1798 
1799 	kref_get(&rdata->refcount);
1800 	rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1801 			     cifs_readv_callback, NULL, rdata, 0, NULL);
1802 
1803 	if (rc == 0)
1804 		cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1805 	else
1806 		kref_put(&rdata->refcount, cifs_readdata_release);
1807 
1808 	cifs_small_buf_release(smb);
1809 	return rc;
1810 }
1811 
1812 int
CIFSSMBRead(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,char ** buf,int * pbuf_type)1813 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1814 	    unsigned int *nbytes, char **buf, int *pbuf_type)
1815 {
1816 	int rc = -EACCES;
1817 	READ_REQ *pSMB = NULL;
1818 	READ_RSP *pSMBr = NULL;
1819 	char *pReadData = NULL;
1820 	int wct;
1821 	int resp_buf_type = 0;
1822 	struct kvec iov[1];
1823 	struct kvec rsp_iov;
1824 	__u32 pid = io_parms->pid;
1825 	__u16 netfid = io_parms->netfid;
1826 	__u64 offset = io_parms->offset;
1827 	struct cifs_tcon *tcon = io_parms->tcon;
1828 	unsigned int count = io_parms->length;
1829 
1830 	cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1831 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1832 		wct = 12;
1833 	else {
1834 		wct = 10; /* old style read */
1835 		if ((offset >> 32) > 0)  {
1836 			/* can not handle this big offset for old */
1837 			return -EIO;
1838 		}
1839 	}
1840 
1841 	*nbytes = 0;
1842 	rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1843 	if (rc)
1844 		return rc;
1845 
1846 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1847 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1848 
1849 	/* tcon and ses pointer are checked in smb_init */
1850 	if (tcon->ses->server == NULL)
1851 		return -ECONNABORTED;
1852 
1853 	pSMB->AndXCommand = 0xFF;       /* none */
1854 	pSMB->Fid = netfid;
1855 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1856 	if (wct == 12)
1857 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1858 
1859 	pSMB->Remaining = 0;
1860 	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1861 	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1862 	if (wct == 12)
1863 		pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1864 	else {
1865 		/* old style read */
1866 		struct smb_com_readx_req *pSMBW =
1867 			(struct smb_com_readx_req *)pSMB;
1868 		pSMBW->ByteCount = 0;
1869 	}
1870 
1871 	iov[0].iov_base = (char *)pSMB;
1872 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1873 	rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1874 			  CIFS_LOG_ERROR, &rsp_iov);
1875 	cifs_small_buf_release(pSMB);
1876 	cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1877 	pSMBr = (READ_RSP *)rsp_iov.iov_base;
1878 	if (rc) {
1879 		cifs_dbg(VFS, "Send error in read = %d\n", rc);
1880 	} else {
1881 		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1882 		data_length = data_length << 16;
1883 		data_length += le16_to_cpu(pSMBr->DataLength);
1884 		*nbytes = data_length;
1885 
1886 		/*check that DataLength would not go beyond end of SMB */
1887 		if ((data_length > CIFSMaxBufSize)
1888 				|| (data_length > count)) {
1889 			cifs_dbg(FYI, "bad length %d for count %d\n",
1890 				 data_length, count);
1891 			rc = -EIO;
1892 			*nbytes = 0;
1893 		} else {
1894 			pReadData = (char *) (&pSMBr->hdr.Protocol) +
1895 					le16_to_cpu(pSMBr->DataOffset);
1896 /*			if (rc = copy_to_user(buf, pReadData, data_length)) {
1897 				cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1898 				rc = -EFAULT;
1899 			}*/ /* can not use copy_to_user when using page cache*/
1900 			if (*buf)
1901 				memcpy(*buf, pReadData, data_length);
1902 		}
1903 	}
1904 
1905 	if (*buf) {
1906 		free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1907 	} else if (resp_buf_type != CIFS_NO_BUFFER) {
1908 		/* return buffer to caller to free */
1909 		*buf = rsp_iov.iov_base;
1910 		if (resp_buf_type == CIFS_SMALL_BUFFER)
1911 			*pbuf_type = CIFS_SMALL_BUFFER;
1912 		else if (resp_buf_type == CIFS_LARGE_BUFFER)
1913 			*pbuf_type = CIFS_LARGE_BUFFER;
1914 	} /* else no valid buffer on return - leave as null */
1915 
1916 	/* Note: On -EAGAIN error only caller can retry on handle based calls
1917 		since file handle passed in no longer valid */
1918 	return rc;
1919 }
1920 
1921 
1922 int
CIFSSMBWrite(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,const char * buf)1923 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1924 	     unsigned int *nbytes, const char *buf)
1925 {
1926 	int rc = -EACCES;
1927 	WRITE_REQ *pSMB = NULL;
1928 	WRITE_RSP *pSMBr = NULL;
1929 	int bytes_returned, wct;
1930 	__u32 bytes_sent;
1931 	__u16 byte_count;
1932 	__u32 pid = io_parms->pid;
1933 	__u16 netfid = io_parms->netfid;
1934 	__u64 offset = io_parms->offset;
1935 	struct cifs_tcon *tcon = io_parms->tcon;
1936 	unsigned int count = io_parms->length;
1937 
1938 	*nbytes = 0;
1939 
1940 	/* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1941 	if (tcon->ses == NULL)
1942 		return -ECONNABORTED;
1943 
1944 	if (tcon->ses->capabilities & CAP_LARGE_FILES)
1945 		wct = 14;
1946 	else {
1947 		wct = 12;
1948 		if ((offset >> 32) > 0) {
1949 			/* can not handle big offset for old srv */
1950 			return -EIO;
1951 		}
1952 	}
1953 
1954 	rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1955 		      (void **) &pSMBr);
1956 	if (rc)
1957 		return rc;
1958 
1959 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1960 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1961 
1962 	/* tcon and ses pointer are checked in smb_init */
1963 	if (tcon->ses->server == NULL)
1964 		return -ECONNABORTED;
1965 
1966 	pSMB->AndXCommand = 0xFF;	/* none */
1967 	pSMB->Fid = netfid;
1968 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1969 	if (wct == 14)
1970 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1971 
1972 	pSMB->Reserved = 0xFFFFFFFF;
1973 	pSMB->WriteMode = 0;
1974 	pSMB->Remaining = 0;
1975 
1976 	/* Can increase buffer size if buffer is big enough in some cases ie we
1977 	can send more if LARGE_WRITE_X capability returned by the server and if
1978 	our buffer is big enough or if we convert to iovecs on socket writes
1979 	and eliminate the copy to the CIFS buffer */
1980 	if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1981 		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1982 	} else {
1983 		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1984 			 & ~0xFF;
1985 	}
1986 
1987 	if (bytes_sent > count)
1988 		bytes_sent = count;
1989 	pSMB->DataOffset =
1990 		cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1991 	if (buf)
1992 		memcpy(pSMB->Data, buf, bytes_sent);
1993 	else if (count != 0) {
1994 		/* No buffer */
1995 		cifs_buf_release(pSMB);
1996 		return -EINVAL;
1997 	} /* else setting file size with write of zero bytes */
1998 	if (wct == 14)
1999 		byte_count = bytes_sent + 1; /* pad */
2000 	else /* wct == 12 */
2001 		byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
2002 
2003 	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
2004 	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
2005 	inc_rfc1001_len(pSMB, byte_count);
2006 
2007 	if (wct == 14)
2008 		pSMB->ByteCount = cpu_to_le16(byte_count);
2009 	else { /* old style write has byte count 4 bytes earlier
2010 		  so 4 bytes pad  */
2011 		struct smb_com_writex_req *pSMBW =
2012 			(struct smb_com_writex_req *)pSMB;
2013 		pSMBW->ByteCount = cpu_to_le16(byte_count);
2014 	}
2015 
2016 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2017 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2018 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2019 	if (rc) {
2020 		cifs_dbg(FYI, "Send error in write = %d\n", rc);
2021 	} else {
2022 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
2023 		*nbytes = (*nbytes) << 16;
2024 		*nbytes += le16_to_cpu(pSMBr->Count);
2025 
2026 		/*
2027 		 * Mask off high 16 bits when bytes written as returned by the
2028 		 * server is greater than bytes requested by the client. Some
2029 		 * OS/2 servers are known to set incorrect CountHigh values.
2030 		 */
2031 		if (*nbytes > count)
2032 			*nbytes &= 0xFFFF;
2033 	}
2034 
2035 	cifs_buf_release(pSMB);
2036 
2037 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2038 		since file handle passed in no longer valid */
2039 
2040 	return rc;
2041 }
2042 
2043 void
cifs_writedata_release(struct kref * refcount)2044 cifs_writedata_release(struct kref *refcount)
2045 {
2046 	struct cifs_writedata *wdata = container_of(refcount,
2047 					struct cifs_writedata, refcount);
2048 #ifdef CONFIG_CIFS_SMB_DIRECT
2049 	if (wdata->mr) {
2050 		smbd_deregister_mr(wdata->mr);
2051 		wdata->mr = NULL;
2052 	}
2053 #endif
2054 
2055 	if (wdata->cfile)
2056 		cifsFileInfo_put(wdata->cfile);
2057 
2058 	kvfree(wdata->pages);
2059 	kfree(wdata);
2060 }
2061 
2062 /*
2063  * Write failed with a retryable error. Resend the write request. It's also
2064  * possible that the page was redirtied so re-clean the page.
2065  */
2066 static void
cifs_writev_requeue(struct cifs_writedata * wdata)2067 cifs_writev_requeue(struct cifs_writedata *wdata)
2068 {
2069 	int i, rc = 0;
2070 	struct inode *inode = d_inode(wdata->cfile->dentry);
2071 	struct TCP_Server_Info *server;
2072 	unsigned int rest_len;
2073 
2074 	server = tlink_tcon(wdata->cfile->tlink)->ses->server;
2075 	i = 0;
2076 	rest_len = wdata->bytes;
2077 	do {
2078 		struct cifs_writedata *wdata2;
2079 		unsigned int j, nr_pages, wsize, tailsz, cur_len;
2080 
2081 		wsize = server->ops->wp_retry_size(inode);
2082 		if (wsize < rest_len) {
2083 			nr_pages = wsize / PAGE_SIZE;
2084 			if (!nr_pages) {
2085 				rc = -ENOTSUPP;
2086 				break;
2087 			}
2088 			cur_len = nr_pages * PAGE_SIZE;
2089 			tailsz = PAGE_SIZE;
2090 		} else {
2091 			nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
2092 			cur_len = rest_len;
2093 			tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
2094 		}
2095 
2096 		wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
2097 		if (!wdata2) {
2098 			rc = -ENOMEM;
2099 			break;
2100 		}
2101 
2102 		for (j = 0; j < nr_pages; j++) {
2103 			wdata2->pages[j] = wdata->pages[i + j];
2104 			lock_page(wdata2->pages[j]);
2105 			clear_page_dirty_for_io(wdata2->pages[j]);
2106 		}
2107 
2108 		wdata2->sync_mode = wdata->sync_mode;
2109 		wdata2->nr_pages = nr_pages;
2110 		wdata2->offset = page_offset(wdata2->pages[0]);
2111 		wdata2->pagesz = PAGE_SIZE;
2112 		wdata2->tailsz = tailsz;
2113 		wdata2->bytes = cur_len;
2114 
2115 		rc = cifs_get_writable_file(CIFS_I(inode), false,
2116 					    &wdata2->cfile);
2117 		if (!wdata2->cfile) {
2118 			cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
2119 				 rc);
2120 			if (!is_retryable_error(rc))
2121 				rc = -EBADF;
2122 		} else {
2123 			wdata2->pid = wdata2->cfile->pid;
2124 			rc = server->ops->async_writev(wdata2,
2125 						       cifs_writedata_release);
2126 		}
2127 
2128 		for (j = 0; j < nr_pages; j++) {
2129 			unlock_page(wdata2->pages[j]);
2130 			if (rc != 0 && !is_retryable_error(rc)) {
2131 				SetPageError(wdata2->pages[j]);
2132 				end_page_writeback(wdata2->pages[j]);
2133 				put_page(wdata2->pages[j]);
2134 			}
2135 		}
2136 
2137 		if (rc) {
2138 			kref_put(&wdata2->refcount, cifs_writedata_release);
2139 			if (is_retryable_error(rc))
2140 				continue;
2141 			i += nr_pages;
2142 			break;
2143 		}
2144 
2145 		rest_len -= cur_len;
2146 		i += nr_pages;
2147 	} while (i < wdata->nr_pages);
2148 
2149 	/* cleanup remaining pages from the original wdata */
2150 	for (; i < wdata->nr_pages; i++) {
2151 		SetPageError(wdata->pages[i]);
2152 		end_page_writeback(wdata->pages[i]);
2153 		put_page(wdata->pages[i]);
2154 	}
2155 
2156 	if (rc != 0 && !is_retryable_error(rc))
2157 		mapping_set_error(inode->i_mapping, rc);
2158 	kref_put(&wdata->refcount, cifs_writedata_release);
2159 }
2160 
2161 void
cifs_writev_complete(struct work_struct * work)2162 cifs_writev_complete(struct work_struct *work)
2163 {
2164 	struct cifs_writedata *wdata = container_of(work,
2165 						struct cifs_writedata, work);
2166 	struct inode *inode = d_inode(wdata->cfile->dentry);
2167 	int i = 0;
2168 
2169 	if (wdata->result == 0) {
2170 		spin_lock(&inode->i_lock);
2171 		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2172 		spin_unlock(&inode->i_lock);
2173 		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2174 					 wdata->bytes);
2175 	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2176 		return cifs_writev_requeue(wdata);
2177 
2178 	for (i = 0; i < wdata->nr_pages; i++) {
2179 		struct page *page = wdata->pages[i];
2180 		if (wdata->result == -EAGAIN)
2181 			__set_page_dirty_nobuffers(page);
2182 		else if (wdata->result < 0)
2183 			SetPageError(page);
2184 		end_page_writeback(page);
2185 		put_page(page);
2186 	}
2187 	if (wdata->result != -EAGAIN)
2188 		mapping_set_error(inode->i_mapping, wdata->result);
2189 	kref_put(&wdata->refcount, cifs_writedata_release);
2190 }
2191 
2192 struct cifs_writedata *
cifs_writedata_alloc(unsigned int nr_pages,work_func_t complete)2193 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2194 {
2195 	struct page **pages =
2196 		kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
2197 	if (pages)
2198 		return cifs_writedata_direct_alloc(pages, complete);
2199 
2200 	return NULL;
2201 }
2202 
2203 struct cifs_writedata *
cifs_writedata_direct_alloc(struct page ** pages,work_func_t complete)2204 cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
2205 {
2206 	struct cifs_writedata *wdata;
2207 
2208 	wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
2209 	if (wdata != NULL) {
2210 		wdata->pages = pages;
2211 		kref_init(&wdata->refcount);
2212 		INIT_LIST_HEAD(&wdata->list);
2213 		init_completion(&wdata->done);
2214 		INIT_WORK(&wdata->work, complete);
2215 	}
2216 	return wdata;
2217 }
2218 
2219 /*
2220  * Check the mid_state and signature on received buffer (if any), and queue the
2221  * workqueue completion task.
2222  */
2223 static void
cifs_writev_callback(struct mid_q_entry * mid)2224 cifs_writev_callback(struct mid_q_entry *mid)
2225 {
2226 	struct cifs_writedata *wdata = mid->callback_data;
2227 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2228 	unsigned int written;
2229 	WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2230 	struct cifs_credits credits = { .value = 1, .instance = 0 };
2231 
2232 	switch (mid->mid_state) {
2233 	case MID_RESPONSE_RECEIVED:
2234 		wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2235 		if (wdata->result != 0)
2236 			break;
2237 
2238 		written = le16_to_cpu(smb->CountHigh);
2239 		written <<= 16;
2240 		written += le16_to_cpu(smb->Count);
2241 		/*
2242 		 * Mask off high 16 bits when bytes written as returned
2243 		 * by the server is greater than bytes requested by the
2244 		 * client. OS/2 servers are known to set incorrect
2245 		 * CountHigh values.
2246 		 */
2247 		if (written > wdata->bytes)
2248 			written &= 0xFFFF;
2249 
2250 		if (written < wdata->bytes)
2251 			wdata->result = -ENOSPC;
2252 		else
2253 			wdata->bytes = written;
2254 		break;
2255 	case MID_REQUEST_SUBMITTED:
2256 	case MID_RETRY_NEEDED:
2257 		wdata->result = -EAGAIN;
2258 		break;
2259 	default:
2260 		wdata->result = -EIO;
2261 		break;
2262 	}
2263 
2264 	queue_work(cifsiod_wq, &wdata->work);
2265 	DeleteMidQEntry(mid);
2266 	add_credits(tcon->ses->server, &credits, 0);
2267 }
2268 
2269 /* cifs_async_writev - send an async write, and set up mid to handle result */
2270 int
cifs_async_writev(struct cifs_writedata * wdata,void (* release)(struct kref * kref))2271 cifs_async_writev(struct cifs_writedata *wdata,
2272 		  void (*release)(struct kref *kref))
2273 {
2274 	int rc = -EACCES;
2275 	WRITE_REQ *smb = NULL;
2276 	int wct;
2277 	struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2278 	struct kvec iov[2];
2279 	struct smb_rqst rqst = { };
2280 
2281 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2282 		wct = 14;
2283 	} else {
2284 		wct = 12;
2285 		if (wdata->offset >> 32 > 0) {
2286 			/* can not handle big offset for old srv */
2287 			return -EIO;
2288 		}
2289 	}
2290 
2291 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2292 	if (rc)
2293 		goto async_writev_out;
2294 
2295 	smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2296 	smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2297 
2298 	smb->AndXCommand = 0xFF;	/* none */
2299 	smb->Fid = wdata->cfile->fid.netfid;
2300 	smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2301 	if (wct == 14)
2302 		smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2303 	smb->Reserved = 0xFFFFFFFF;
2304 	smb->WriteMode = 0;
2305 	smb->Remaining = 0;
2306 
2307 	smb->DataOffset =
2308 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2309 
2310 	/* 4 for RFC1001 length + 1 for BCC */
2311 	iov[0].iov_len = 4;
2312 	iov[0].iov_base = smb;
2313 	iov[1].iov_len = get_rfc1002_length(smb) + 1;
2314 	iov[1].iov_base = (char *)smb + 4;
2315 
2316 	rqst.rq_iov = iov;
2317 	rqst.rq_nvec = 2;
2318 	rqst.rq_pages = wdata->pages;
2319 	rqst.rq_offset = wdata->page_offset;
2320 	rqst.rq_npages = wdata->nr_pages;
2321 	rqst.rq_pagesz = wdata->pagesz;
2322 	rqst.rq_tailsz = wdata->tailsz;
2323 
2324 	cifs_dbg(FYI, "async write at %llu %u bytes\n",
2325 		 wdata->offset, wdata->bytes);
2326 
2327 	smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2328 	smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2329 
2330 	if (wct == 14) {
2331 		inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2332 		put_bcc(wdata->bytes + 1, &smb->hdr);
2333 	} else {
2334 		/* wct == 12 */
2335 		struct smb_com_writex_req *smbw =
2336 				(struct smb_com_writex_req *)smb;
2337 		inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2338 		put_bcc(wdata->bytes + 5, &smbw->hdr);
2339 		iov[1].iov_len += 4; /* pad bigger by four bytes */
2340 	}
2341 
2342 	kref_get(&wdata->refcount);
2343 	rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2344 			     cifs_writev_callback, NULL, wdata, 0, NULL);
2345 
2346 	if (rc == 0)
2347 		cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2348 	else
2349 		kref_put(&wdata->refcount, release);
2350 
2351 async_writev_out:
2352 	cifs_small_buf_release(smb);
2353 	return rc;
2354 }
2355 
2356 int
CIFSSMBWrite2(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,struct kvec * iov,int n_vec)2357 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2358 	      unsigned int *nbytes, struct kvec *iov, int n_vec)
2359 {
2360 	int rc = -EACCES;
2361 	WRITE_REQ *pSMB = NULL;
2362 	int wct;
2363 	int smb_hdr_len;
2364 	int resp_buf_type = 0;
2365 	__u32 pid = io_parms->pid;
2366 	__u16 netfid = io_parms->netfid;
2367 	__u64 offset = io_parms->offset;
2368 	struct cifs_tcon *tcon = io_parms->tcon;
2369 	unsigned int count = io_parms->length;
2370 	struct kvec rsp_iov;
2371 
2372 	*nbytes = 0;
2373 
2374 	cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2375 
2376 	if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2377 		wct = 14;
2378 	} else {
2379 		wct = 12;
2380 		if ((offset >> 32) > 0) {
2381 			/* can not handle big offset for old srv */
2382 			return -EIO;
2383 		}
2384 	}
2385 	rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2386 	if (rc)
2387 		return rc;
2388 
2389 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2390 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2391 
2392 	/* tcon and ses pointer are checked in smb_init */
2393 	if (tcon->ses->server == NULL)
2394 		return -ECONNABORTED;
2395 
2396 	pSMB->AndXCommand = 0xFF;	/* none */
2397 	pSMB->Fid = netfid;
2398 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2399 	if (wct == 14)
2400 		pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2401 	pSMB->Reserved = 0xFFFFFFFF;
2402 	pSMB->WriteMode = 0;
2403 	pSMB->Remaining = 0;
2404 
2405 	pSMB->DataOffset =
2406 	    cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2407 
2408 	pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2409 	pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2410 	/* header + 1 byte pad */
2411 	smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2412 	if (wct == 14)
2413 		inc_rfc1001_len(pSMB, count + 1);
2414 	else /* wct == 12 */
2415 		inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2416 	if (wct == 14)
2417 		pSMB->ByteCount = cpu_to_le16(count + 1);
2418 	else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2419 		struct smb_com_writex_req *pSMBW =
2420 				(struct smb_com_writex_req *)pSMB;
2421 		pSMBW->ByteCount = cpu_to_le16(count + 5);
2422 	}
2423 	iov[0].iov_base = pSMB;
2424 	if (wct == 14)
2425 		iov[0].iov_len = smb_hdr_len + 4;
2426 	else /* wct == 12 pad bigger by four bytes */
2427 		iov[0].iov_len = smb_hdr_len + 8;
2428 
2429 	rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2430 			  &rsp_iov);
2431 	cifs_small_buf_release(pSMB);
2432 	cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2433 	if (rc) {
2434 		cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2435 	} else if (resp_buf_type == 0) {
2436 		/* presumably this can not happen, but best to be safe */
2437 		rc = -EIO;
2438 	} else {
2439 		WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2440 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
2441 		*nbytes = (*nbytes) << 16;
2442 		*nbytes += le16_to_cpu(pSMBr->Count);
2443 
2444 		/*
2445 		 * Mask off high 16 bits when bytes written as returned by the
2446 		 * server is greater than bytes requested by the client. OS/2
2447 		 * servers are known to set incorrect CountHigh values.
2448 		 */
2449 		if (*nbytes > count)
2450 			*nbytes &= 0xFFFF;
2451 	}
2452 
2453 	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2454 
2455 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2456 		since file handle passed in no longer valid */
2457 
2458 	return rc;
2459 }
2460 
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)2461 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2462 	       const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2463 	       const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2464 {
2465 	int rc = 0;
2466 	LOCK_REQ *pSMB = NULL;
2467 	struct kvec iov[2];
2468 	struct kvec rsp_iov;
2469 	int resp_buf_type;
2470 	__u16 count;
2471 
2472 	cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2473 		 num_lock, num_unlock);
2474 
2475 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2476 	if (rc)
2477 		return rc;
2478 
2479 	pSMB->Timeout = 0;
2480 	pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2481 	pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2482 	pSMB->LockType = lock_type;
2483 	pSMB->AndXCommand = 0xFF; /* none */
2484 	pSMB->Fid = netfid; /* netfid stays le */
2485 
2486 	count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2487 	inc_rfc1001_len(pSMB, count);
2488 	pSMB->ByteCount = cpu_to_le16(count);
2489 
2490 	iov[0].iov_base = (char *)pSMB;
2491 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2492 			 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2493 	iov[1].iov_base = (char *)buf;
2494 	iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2495 
2496 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2497 	rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type,
2498 			  CIFS_NO_RSP_BUF, &rsp_iov);
2499 	cifs_small_buf_release(pSMB);
2500 	if (rc)
2501 		cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2502 
2503 	return rc;
2504 }
2505 
2506 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)2507 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2508 	    const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2509 	    const __u64 offset, const __u32 numUnlock,
2510 	    const __u32 numLock, const __u8 lockType,
2511 	    const bool waitFlag, const __u8 oplock_level)
2512 {
2513 	int rc = 0;
2514 	LOCK_REQ *pSMB = NULL;
2515 /*	LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2516 	int bytes_returned;
2517 	int flags = 0;
2518 	__u16 count;
2519 
2520 	cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2521 		 (int)waitFlag, numLock);
2522 	rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2523 
2524 	if (rc)
2525 		return rc;
2526 
2527 	if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2528 		/* no response expected */
2529 		flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP;
2530 		pSMB->Timeout = 0;
2531 	} else if (waitFlag) {
2532 		flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2533 		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2534 	} else {
2535 		pSMB->Timeout = 0;
2536 	}
2537 
2538 	pSMB->NumberOfLocks = cpu_to_le16(numLock);
2539 	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2540 	pSMB->LockType = lockType;
2541 	pSMB->OplockLevel = oplock_level;
2542 	pSMB->AndXCommand = 0xFF;	/* none */
2543 	pSMB->Fid = smb_file_id; /* netfid stays le */
2544 
2545 	if ((numLock != 0) || (numUnlock != 0)) {
2546 		pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2547 		/* BB where to store pid high? */
2548 		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2549 		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2550 		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2551 		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2552 		count = sizeof(LOCKING_ANDX_RANGE);
2553 	} else {
2554 		/* oplock break */
2555 		count = 0;
2556 	}
2557 	inc_rfc1001_len(pSMB, count);
2558 	pSMB->ByteCount = cpu_to_le16(count);
2559 
2560 	if (waitFlag)
2561 		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2562 			(struct smb_hdr *) pSMB, &bytes_returned);
2563 	else
2564 		rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2565 	cifs_small_buf_release(pSMB);
2566 	cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2567 	if (rc)
2568 		cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2569 
2570 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2571 	since file handle passed in no longer valid */
2572 	return rc;
2573 }
2574 
2575 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)2576 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2577 		const __u16 smb_file_id, const __u32 netpid,
2578 		const loff_t start_offset, const __u64 len,
2579 		struct file_lock *pLockData, const __u16 lock_type,
2580 		const bool waitFlag)
2581 {
2582 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2583 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2584 	struct cifs_posix_lock *parm_data;
2585 	int rc = 0;
2586 	int timeout = 0;
2587 	int bytes_returned = 0;
2588 	int resp_buf_type = 0;
2589 	__u16 params, param_offset, offset, byte_count, count;
2590 	struct kvec iov[1];
2591 	struct kvec rsp_iov;
2592 
2593 	cifs_dbg(FYI, "Posix Lock\n");
2594 
2595 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2596 
2597 	if (rc)
2598 		return rc;
2599 
2600 	pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2601 
2602 	params = 6;
2603 	pSMB->MaxSetupCount = 0;
2604 	pSMB->Reserved = 0;
2605 	pSMB->Flags = 0;
2606 	pSMB->Reserved2 = 0;
2607 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2608 	offset = param_offset + params;
2609 
2610 	count = sizeof(struct cifs_posix_lock);
2611 	pSMB->MaxParameterCount = cpu_to_le16(2);
2612 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2613 	pSMB->SetupCount = 1;
2614 	pSMB->Reserved3 = 0;
2615 	if (pLockData)
2616 		pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2617 	else
2618 		pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2619 	byte_count = 3 /* pad */  + params + count;
2620 	pSMB->DataCount = cpu_to_le16(count);
2621 	pSMB->ParameterCount = cpu_to_le16(params);
2622 	pSMB->TotalDataCount = pSMB->DataCount;
2623 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2624 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2625 	parm_data = (struct cifs_posix_lock *)
2626 			(((char *) &pSMB->hdr.Protocol) + offset);
2627 
2628 	parm_data->lock_type = cpu_to_le16(lock_type);
2629 	if (waitFlag) {
2630 		timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2631 		parm_data->lock_flags = cpu_to_le16(1);
2632 		pSMB->Timeout = cpu_to_le32(-1);
2633 	} else
2634 		pSMB->Timeout = 0;
2635 
2636 	parm_data->pid = cpu_to_le32(netpid);
2637 	parm_data->start = cpu_to_le64(start_offset);
2638 	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2639 
2640 	pSMB->DataOffset = cpu_to_le16(offset);
2641 	pSMB->Fid = smb_file_id;
2642 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2643 	pSMB->Reserved4 = 0;
2644 	inc_rfc1001_len(pSMB, byte_count);
2645 	pSMB->ByteCount = cpu_to_le16(byte_count);
2646 	if (waitFlag) {
2647 		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2648 			(struct smb_hdr *) pSMBr, &bytes_returned);
2649 	} else {
2650 		iov[0].iov_base = (char *)pSMB;
2651 		iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2652 		rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2653 				&resp_buf_type, timeout, &rsp_iov);
2654 		pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2655 	}
2656 	cifs_small_buf_release(pSMB);
2657 
2658 	if (rc) {
2659 		cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2660 	} else if (pLockData) {
2661 		/* lock structure can be returned on get */
2662 		__u16 data_offset;
2663 		__u16 data_count;
2664 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2665 
2666 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2667 			rc = -EIO;      /* bad smb */
2668 			goto plk_err_exit;
2669 		}
2670 		data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2671 		data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2672 		if (data_count < sizeof(struct cifs_posix_lock)) {
2673 			rc = -EIO;
2674 			goto plk_err_exit;
2675 		}
2676 		parm_data = (struct cifs_posix_lock *)
2677 			((char *)&pSMBr->hdr.Protocol + data_offset);
2678 		if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2679 			pLockData->fl_type = F_UNLCK;
2680 		else {
2681 			if (parm_data->lock_type ==
2682 					cpu_to_le16(CIFS_RDLCK))
2683 				pLockData->fl_type = F_RDLCK;
2684 			else if (parm_data->lock_type ==
2685 					cpu_to_le16(CIFS_WRLCK))
2686 				pLockData->fl_type = F_WRLCK;
2687 
2688 			pLockData->fl_start = le64_to_cpu(parm_data->start);
2689 			pLockData->fl_end = pLockData->fl_start +
2690 					le64_to_cpu(parm_data->length) - 1;
2691 			pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2692 		}
2693 	}
2694 
2695 plk_err_exit:
2696 	free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2697 
2698 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2699 	   since file handle passed in no longer valid */
2700 
2701 	return rc;
2702 }
2703 
2704 
2705 int
CIFSSMBClose(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2706 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2707 {
2708 	int rc = 0;
2709 	CLOSE_REQ *pSMB = NULL;
2710 	cifs_dbg(FYI, "In CIFSSMBClose\n");
2711 
2712 /* do not retry on dead session on close */
2713 	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2714 	if (rc == -EAGAIN)
2715 		return 0;
2716 	if (rc)
2717 		return rc;
2718 
2719 	pSMB->FileID = (__u16) smb_file_id;
2720 	pSMB->LastWriteTime = 0xFFFFFFFF;
2721 	pSMB->ByteCount = 0;
2722 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2723 	cifs_small_buf_release(pSMB);
2724 	cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2725 	if (rc) {
2726 		if (rc != -EINTR) {
2727 			/* EINTR is expected when user ctl-c to kill app */
2728 			cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2729 		}
2730 	}
2731 
2732 	/* Since session is dead, file will be closed on server already */
2733 	if (rc == -EAGAIN)
2734 		rc = 0;
2735 
2736 	return rc;
2737 }
2738 
2739 int
CIFSSMBFlush(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2740 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2741 {
2742 	int rc = 0;
2743 	FLUSH_REQ *pSMB = NULL;
2744 	cifs_dbg(FYI, "In CIFSSMBFlush\n");
2745 
2746 	rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2747 	if (rc)
2748 		return rc;
2749 
2750 	pSMB->FileID = (__u16) smb_file_id;
2751 	pSMB->ByteCount = 0;
2752 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2753 	cifs_small_buf_release(pSMB);
2754 	cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2755 	if (rc)
2756 		cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2757 
2758 	return rc;
2759 }
2760 
2761 int
CIFSSMBRename(const unsigned int xid,struct cifs_tcon * tcon,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)2762 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2763 	      const char *from_name, const char *to_name,
2764 	      struct cifs_sb_info *cifs_sb)
2765 {
2766 	int rc = 0;
2767 	RENAME_REQ *pSMB = NULL;
2768 	RENAME_RSP *pSMBr = NULL;
2769 	int bytes_returned;
2770 	int name_len, name_len2;
2771 	__u16 count;
2772 	int remap = cifs_remap(cifs_sb);
2773 
2774 	cifs_dbg(FYI, "In CIFSSMBRename\n");
2775 renameRetry:
2776 	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2777 		      (void **) &pSMBr);
2778 	if (rc)
2779 		return rc;
2780 
2781 	pSMB->BufferFormat = 0x04;
2782 	pSMB->SearchAttributes =
2783 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2784 			ATTR_DIRECTORY);
2785 
2786 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2787 		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2788 					      from_name, PATH_MAX,
2789 					      cifs_sb->local_nls, remap);
2790 		name_len++;	/* trailing null */
2791 		name_len *= 2;
2792 		pSMB->OldFileName[name_len] = 0x04;	/* pad */
2793 	/* protocol requires ASCII signature byte on Unicode string */
2794 		pSMB->OldFileName[name_len + 1] = 0x00;
2795 		name_len2 =
2796 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2797 				       to_name, PATH_MAX, cifs_sb->local_nls,
2798 				       remap);
2799 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2800 		name_len2 *= 2;	/* convert to bytes */
2801 	} else {
2802 		name_len = copy_path_name(pSMB->OldFileName, from_name);
2803 		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2804 		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2805 		name_len2++;	/* signature byte */
2806 	}
2807 
2808 	count = 1 /* 1st signature byte */  + name_len + name_len2;
2809 	inc_rfc1001_len(pSMB, count);
2810 	pSMB->ByteCount = cpu_to_le16(count);
2811 
2812 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2813 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2814 	cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2815 	if (rc)
2816 		cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2817 
2818 	cifs_buf_release(pSMB);
2819 
2820 	if (rc == -EAGAIN)
2821 		goto renameRetry;
2822 
2823 	return rc;
2824 }
2825 
CIFSSMBRenameOpenFile(const unsigned int xid,struct cifs_tcon * pTcon,int netfid,const char * target_name,const struct nls_table * nls_codepage,int remap)2826 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2827 		int netfid, const char *target_name,
2828 		const struct nls_table *nls_codepage, int remap)
2829 {
2830 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2831 	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2832 	struct set_file_rename *rename_info;
2833 	char *data_offset;
2834 	char dummy_string[30];
2835 	int rc = 0;
2836 	int bytes_returned = 0;
2837 	int len_of_str;
2838 	__u16 params, param_offset, offset, count, byte_count;
2839 
2840 	cifs_dbg(FYI, "Rename to File by handle\n");
2841 	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2842 			(void **) &pSMBr);
2843 	if (rc)
2844 		return rc;
2845 
2846 	params = 6;
2847 	pSMB->MaxSetupCount = 0;
2848 	pSMB->Reserved = 0;
2849 	pSMB->Flags = 0;
2850 	pSMB->Timeout = 0;
2851 	pSMB->Reserved2 = 0;
2852 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2853 	offset = param_offset + params;
2854 
2855 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2856 	rename_info = (struct set_file_rename *) data_offset;
2857 	pSMB->MaxParameterCount = cpu_to_le16(2);
2858 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2859 	pSMB->SetupCount = 1;
2860 	pSMB->Reserved3 = 0;
2861 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2862 	byte_count = 3 /* pad */  + params;
2863 	pSMB->ParameterCount = cpu_to_le16(params);
2864 	pSMB->TotalParameterCount = pSMB->ParameterCount;
2865 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
2866 	pSMB->DataOffset = cpu_to_le16(offset);
2867 	/* construct random name ".cifs_tmp<inodenum><mid>" */
2868 	rename_info->overwrite = cpu_to_le32(1);
2869 	rename_info->root_fid  = 0;
2870 	/* unicode only call */
2871 	if (target_name == NULL) {
2872 		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2873 		len_of_str =
2874 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2875 					dummy_string, 24, nls_codepage, remap);
2876 	} else {
2877 		len_of_str =
2878 			cifsConvertToUTF16((__le16 *)rename_info->target_name,
2879 					target_name, PATH_MAX, nls_codepage,
2880 					remap);
2881 	}
2882 	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2883 	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2884 	byte_count += count;
2885 	pSMB->DataCount = cpu_to_le16(count);
2886 	pSMB->TotalDataCount = pSMB->DataCount;
2887 	pSMB->Fid = netfid;
2888 	pSMB->InformationLevel =
2889 		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2890 	pSMB->Reserved4 = 0;
2891 	inc_rfc1001_len(pSMB, byte_count);
2892 	pSMB->ByteCount = cpu_to_le16(byte_count);
2893 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2894 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2895 	cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2896 	if (rc)
2897 		cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2898 			 rc);
2899 
2900 	cifs_buf_release(pSMB);
2901 
2902 	/* Note: On -EAGAIN error only caller can retry on handle based calls
2903 		since file handle passed in no longer valid */
2904 
2905 	return rc;
2906 }
2907 
2908 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)2909 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2910 	    const char *fromName, const __u16 target_tid, const char *toName,
2911 	    const int flags, const struct nls_table *nls_codepage, int remap)
2912 {
2913 	int rc = 0;
2914 	COPY_REQ *pSMB = NULL;
2915 	COPY_RSP *pSMBr = NULL;
2916 	int bytes_returned;
2917 	int name_len, name_len2;
2918 	__u16 count;
2919 
2920 	cifs_dbg(FYI, "In CIFSSMBCopy\n");
2921 copyRetry:
2922 	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2923 			(void **) &pSMBr);
2924 	if (rc)
2925 		return rc;
2926 
2927 	pSMB->BufferFormat = 0x04;
2928 	pSMB->Tid2 = target_tid;
2929 
2930 	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2931 
2932 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2933 		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2934 					      fromName, PATH_MAX, nls_codepage,
2935 					      remap);
2936 		name_len++;     /* trailing null */
2937 		name_len *= 2;
2938 		pSMB->OldFileName[name_len] = 0x04;     /* pad */
2939 		/* protocol requires ASCII signature byte on Unicode string */
2940 		pSMB->OldFileName[name_len + 1] = 0x00;
2941 		name_len2 =
2942 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2943 				       toName, PATH_MAX, nls_codepage, remap);
2944 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2945 		name_len2 *= 2; /* convert to bytes */
2946 	} else {
2947 		name_len = copy_path_name(pSMB->OldFileName, fromName);
2948 		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2949 		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2950 		name_len2++;    /* signature byte */
2951 	}
2952 
2953 	count = 1 /* 1st signature byte */  + name_len + name_len2;
2954 	inc_rfc1001_len(pSMB, count);
2955 	pSMB->ByteCount = cpu_to_le16(count);
2956 
2957 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2958 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
2959 	if (rc) {
2960 		cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2961 			 rc, le16_to_cpu(pSMBr->CopyCount));
2962 	}
2963 	cifs_buf_release(pSMB);
2964 
2965 	if (rc == -EAGAIN)
2966 		goto copyRetry;
2967 
2968 	return rc;
2969 }
2970 
2971 int
CIFSUnixCreateSymLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2972 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2973 		      const char *fromName, const char *toName,
2974 		      const struct nls_table *nls_codepage, int remap)
2975 {
2976 	TRANSACTION2_SPI_REQ *pSMB = NULL;
2977 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
2978 	char *data_offset;
2979 	int name_len;
2980 	int name_len_target;
2981 	int rc = 0;
2982 	int bytes_returned = 0;
2983 	__u16 params, param_offset, offset, byte_count;
2984 
2985 	cifs_dbg(FYI, "In Symlink Unix style\n");
2986 createSymLinkRetry:
2987 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2988 		      (void **) &pSMBr);
2989 	if (rc)
2990 		return rc;
2991 
2992 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2993 		name_len =
2994 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2995 				/* find define for this maxpathcomponent */
2996 					PATH_MAX, nls_codepage, remap);
2997 		name_len++;	/* trailing null */
2998 		name_len *= 2;
2999 
3000 	} else {
3001 		name_len = copy_path_name(pSMB->FileName, fromName);
3002 	}
3003 	params = 6 + name_len;
3004 	pSMB->MaxSetupCount = 0;
3005 	pSMB->Reserved = 0;
3006 	pSMB->Flags = 0;
3007 	pSMB->Timeout = 0;
3008 	pSMB->Reserved2 = 0;
3009 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3010 				InformationLevel) - 4;
3011 	offset = param_offset + params;
3012 
3013 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3014 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3015 		name_len_target =
3016 		    cifsConvertToUTF16((__le16 *) data_offset, toName,
3017 				/* find define for this maxpathcomponent */
3018 					PATH_MAX, nls_codepage, remap);
3019 		name_len_target++;	/* trailing null */
3020 		name_len_target *= 2;
3021 	} else {
3022 		name_len_target = copy_path_name(data_offset, toName);
3023 	}
3024 
3025 	pSMB->MaxParameterCount = cpu_to_le16(2);
3026 	/* BB find exact max on data count below from sess */
3027 	pSMB->MaxDataCount = cpu_to_le16(1000);
3028 	pSMB->SetupCount = 1;
3029 	pSMB->Reserved3 = 0;
3030 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3031 	byte_count = 3 /* pad */  + params + name_len_target;
3032 	pSMB->DataCount = cpu_to_le16(name_len_target);
3033 	pSMB->ParameterCount = cpu_to_le16(params);
3034 	pSMB->TotalDataCount = pSMB->DataCount;
3035 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3036 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3037 	pSMB->DataOffset = cpu_to_le16(offset);
3038 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
3039 	pSMB->Reserved4 = 0;
3040 	inc_rfc1001_len(pSMB, byte_count);
3041 	pSMB->ByteCount = cpu_to_le16(byte_count);
3042 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3043 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3044 	cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
3045 	if (rc)
3046 		cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
3047 			 rc);
3048 
3049 	cifs_buf_release(pSMB);
3050 
3051 	if (rc == -EAGAIN)
3052 		goto createSymLinkRetry;
3053 
3054 	return rc;
3055 }
3056 
3057 int
CIFSUnixCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)3058 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3059 		       const char *fromName, const char *toName,
3060 		       const struct nls_table *nls_codepage, int remap)
3061 {
3062 	TRANSACTION2_SPI_REQ *pSMB = NULL;
3063 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
3064 	char *data_offset;
3065 	int name_len;
3066 	int name_len_target;
3067 	int rc = 0;
3068 	int bytes_returned = 0;
3069 	__u16 params, param_offset, offset, byte_count;
3070 
3071 	cifs_dbg(FYI, "In Create Hard link Unix style\n");
3072 createHardLinkRetry:
3073 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3074 		      (void **) &pSMBr);
3075 	if (rc)
3076 		return rc;
3077 
3078 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3079 		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
3080 					      PATH_MAX, nls_codepage, remap);
3081 		name_len++;	/* trailing null */
3082 		name_len *= 2;
3083 
3084 	} else {
3085 		name_len = copy_path_name(pSMB->FileName, toName);
3086 	}
3087 	params = 6 + name_len;
3088 	pSMB->MaxSetupCount = 0;
3089 	pSMB->Reserved = 0;
3090 	pSMB->Flags = 0;
3091 	pSMB->Timeout = 0;
3092 	pSMB->Reserved2 = 0;
3093 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3094 				InformationLevel) - 4;
3095 	offset = param_offset + params;
3096 
3097 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3098 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3099 		name_len_target =
3100 		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
3101 				       PATH_MAX, nls_codepage, remap);
3102 		name_len_target++;	/* trailing null */
3103 		name_len_target *= 2;
3104 	} else {
3105 		name_len_target = copy_path_name(data_offset, fromName);
3106 	}
3107 
3108 	pSMB->MaxParameterCount = cpu_to_le16(2);
3109 	/* BB find exact max on data count below from sess*/
3110 	pSMB->MaxDataCount = cpu_to_le16(1000);
3111 	pSMB->SetupCount = 1;
3112 	pSMB->Reserved3 = 0;
3113 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3114 	byte_count = 3 /* pad */  + params + name_len_target;
3115 	pSMB->ParameterCount = cpu_to_le16(params);
3116 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3117 	pSMB->DataCount = cpu_to_le16(name_len_target);
3118 	pSMB->TotalDataCount = pSMB->DataCount;
3119 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3120 	pSMB->DataOffset = cpu_to_le16(offset);
3121 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3122 	pSMB->Reserved4 = 0;
3123 	inc_rfc1001_len(pSMB, byte_count);
3124 	pSMB->ByteCount = cpu_to_le16(byte_count);
3125 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3126 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3127 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3128 	if (rc)
3129 		cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
3130 			 rc);
3131 
3132 	cifs_buf_release(pSMB);
3133 	if (rc == -EAGAIN)
3134 		goto createHardLinkRetry;
3135 
3136 	return rc;
3137 }
3138 
3139 int
CIFSCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)3140 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3141 		   const char *from_name, const char *to_name,
3142 		   struct cifs_sb_info *cifs_sb)
3143 {
3144 	int rc = 0;
3145 	NT_RENAME_REQ *pSMB = NULL;
3146 	RENAME_RSP *pSMBr = NULL;
3147 	int bytes_returned;
3148 	int name_len, name_len2;
3149 	__u16 count;
3150 	int remap = cifs_remap(cifs_sb);
3151 
3152 	cifs_dbg(FYI, "In CIFSCreateHardLink\n");
3153 winCreateHardLinkRetry:
3154 
3155 	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3156 		      (void **) &pSMBr);
3157 	if (rc)
3158 		return rc;
3159 
3160 	pSMB->SearchAttributes =
3161 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3162 			ATTR_DIRECTORY);
3163 	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3164 	pSMB->ClusterCount = 0;
3165 
3166 	pSMB->BufferFormat = 0x04;
3167 
3168 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3169 		name_len =
3170 		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3171 				       PATH_MAX, cifs_sb->local_nls, remap);
3172 		name_len++;	/* trailing null */
3173 		name_len *= 2;
3174 
3175 		/* protocol specifies ASCII buffer format (0x04) for unicode */
3176 		pSMB->OldFileName[name_len] = 0x04;
3177 		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3178 		name_len2 =
3179 		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3180 				       to_name, PATH_MAX, cifs_sb->local_nls,
3181 				       remap);
3182 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
3183 		name_len2 *= 2;	/* convert to bytes */
3184 	} else {
3185 		name_len = copy_path_name(pSMB->OldFileName, from_name);
3186 		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
3187 		name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
3188 		name_len2++;	/* signature byte */
3189 	}
3190 
3191 	count = 1 /* string type byte */  + name_len + name_len2;
3192 	inc_rfc1001_len(pSMB, count);
3193 	pSMB->ByteCount = cpu_to_le16(count);
3194 
3195 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3196 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3197 	cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3198 	if (rc)
3199 		cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3200 
3201 	cifs_buf_release(pSMB);
3202 	if (rc == -EAGAIN)
3203 		goto winCreateHardLinkRetry;
3204 
3205 	return rc;
3206 }
3207 
3208 int
CIFSSMBUnixQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char ** symlinkinfo,const struct nls_table * nls_codepage,int remap)3209 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3210 			const unsigned char *searchName, char **symlinkinfo,
3211 			const struct nls_table *nls_codepage, int remap)
3212 {
3213 /* SMB_QUERY_FILE_UNIX_LINK */
3214 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3215 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3216 	int rc = 0;
3217 	int bytes_returned;
3218 	int name_len;
3219 	__u16 params, byte_count;
3220 	char *data_start;
3221 
3222 	cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3223 
3224 querySymLinkRetry:
3225 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3226 		      (void **) &pSMBr);
3227 	if (rc)
3228 		return rc;
3229 
3230 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3231 		name_len =
3232 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3233 					   searchName, PATH_MAX, nls_codepage,
3234 					   remap);
3235 		name_len++;	/* trailing null */
3236 		name_len *= 2;
3237 	} else {
3238 		name_len = copy_path_name(pSMB->FileName, searchName);
3239 	}
3240 
3241 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3242 	pSMB->TotalDataCount = 0;
3243 	pSMB->MaxParameterCount = cpu_to_le16(2);
3244 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3245 	pSMB->MaxSetupCount = 0;
3246 	pSMB->Reserved = 0;
3247 	pSMB->Flags = 0;
3248 	pSMB->Timeout = 0;
3249 	pSMB->Reserved2 = 0;
3250 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
3251 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3252 	pSMB->DataCount = 0;
3253 	pSMB->DataOffset = 0;
3254 	pSMB->SetupCount = 1;
3255 	pSMB->Reserved3 = 0;
3256 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3257 	byte_count = params + 1 /* pad */ ;
3258 	pSMB->TotalParameterCount = cpu_to_le16(params);
3259 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3260 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3261 	pSMB->Reserved4 = 0;
3262 	inc_rfc1001_len(pSMB, byte_count);
3263 	pSMB->ByteCount = cpu_to_le16(byte_count);
3264 
3265 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3266 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3267 	if (rc) {
3268 		cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3269 	} else {
3270 		/* decode response */
3271 
3272 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3273 		/* BB also check enough total bytes returned */
3274 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3275 			rc = -EIO;
3276 		else {
3277 			bool is_unicode;
3278 			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3279 
3280 			data_start = ((char *) &pSMBr->hdr.Protocol) +
3281 					   le16_to_cpu(pSMBr->t2.DataOffset);
3282 
3283 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3284 				is_unicode = true;
3285 			else
3286 				is_unicode = false;
3287 
3288 			/* BB FIXME investigate remapping reserved chars here */
3289 			*symlinkinfo = cifs_strndup_from_utf16(data_start,
3290 					count, is_unicode, nls_codepage);
3291 			if (!*symlinkinfo)
3292 				rc = -ENOMEM;
3293 		}
3294 	}
3295 	cifs_buf_release(pSMB);
3296 	if (rc == -EAGAIN)
3297 		goto querySymLinkRetry;
3298 	return rc;
3299 }
3300 
3301 /*
3302  *	Recent Windows versions now create symlinks more frequently
3303  *	and they use the "reparse point" mechanism below.  We can of course
3304  *	do symlinks nicely to Samba and other servers which support the
3305  *	CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3306  *	"MF" symlinks optionally, but for recent Windows we really need to
3307  *	reenable the code below and fix the cifs_symlink callers to handle this.
3308  *	In the interim this code has been moved to its own config option so
3309  *	it is not compiled in by default until callers fixed up and more tested.
3310  */
3311 int
CIFSSMBQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,char ** symlinkinfo,const struct nls_table * nls_codepage)3312 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3313 		    __u16 fid, char **symlinkinfo,
3314 		    const struct nls_table *nls_codepage)
3315 {
3316 	int rc = 0;
3317 	int bytes_returned;
3318 	struct smb_com_transaction_ioctl_req *pSMB;
3319 	struct smb_com_transaction_ioctl_rsp *pSMBr;
3320 	bool is_unicode;
3321 	unsigned int sub_len;
3322 	char *sub_start;
3323 	struct reparse_symlink_data *reparse_buf;
3324 	struct reparse_posix_data *posix_buf;
3325 	__u32 data_offset, data_count;
3326 	char *end_of_smb;
3327 
3328 	cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3329 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3330 		      (void **) &pSMBr);
3331 	if (rc)
3332 		return rc;
3333 
3334 	pSMB->TotalParameterCount = 0 ;
3335 	pSMB->TotalDataCount = 0;
3336 	pSMB->MaxParameterCount = cpu_to_le32(2);
3337 	/* BB find exact data count max from sess structure BB */
3338 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3339 	pSMB->MaxSetupCount = 4;
3340 	pSMB->Reserved = 0;
3341 	pSMB->ParameterOffset = 0;
3342 	pSMB->DataCount = 0;
3343 	pSMB->DataOffset = 0;
3344 	pSMB->SetupCount = 4;
3345 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3346 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3347 	pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3348 	pSMB->IsFsctl = 1; /* FSCTL */
3349 	pSMB->IsRootFlag = 0;
3350 	pSMB->Fid = fid; /* file handle always le */
3351 	pSMB->ByteCount = 0;
3352 
3353 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3354 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3355 	if (rc) {
3356 		cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3357 		goto qreparse_out;
3358 	}
3359 
3360 	data_offset = le32_to_cpu(pSMBr->DataOffset);
3361 	data_count = le32_to_cpu(pSMBr->DataCount);
3362 	if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3363 		/* BB also check enough total bytes returned */
3364 		rc = -EIO;	/* bad smb */
3365 		goto qreparse_out;
3366 	}
3367 	if (!data_count || (data_count > 2048)) {
3368 		rc = -EIO;
3369 		cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3370 		goto qreparse_out;
3371 	}
3372 	end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3373 	reparse_buf = (struct reparse_symlink_data *)
3374 				((char *)&pSMBr->hdr.Protocol + data_offset);
3375 	if ((char *)reparse_buf >= end_of_smb) {
3376 		rc = -EIO;
3377 		goto qreparse_out;
3378 	}
3379 	if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3380 		cifs_dbg(FYI, "NFS style reparse tag\n");
3381 		posix_buf =  (struct reparse_posix_data *)reparse_buf;
3382 
3383 		if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3384 			cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3385 				 le64_to_cpu(posix_buf->InodeType));
3386 			rc = -EOPNOTSUPP;
3387 			goto qreparse_out;
3388 		}
3389 		is_unicode = true;
3390 		sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3391 		if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3392 			cifs_dbg(FYI, "reparse buf beyond SMB\n");
3393 			rc = -EIO;
3394 			goto qreparse_out;
3395 		}
3396 		*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3397 				sub_len, is_unicode, nls_codepage);
3398 		goto qreparse_out;
3399 	} else if (reparse_buf->ReparseTag !=
3400 			cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3401 		rc = -EOPNOTSUPP;
3402 		goto qreparse_out;
3403 	}
3404 
3405 	/* Reparse tag is NTFS symlink */
3406 	sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3407 				reparse_buf->PathBuffer;
3408 	sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3409 	if (sub_start + sub_len > end_of_smb) {
3410 		cifs_dbg(FYI, "reparse buf beyond SMB\n");
3411 		rc = -EIO;
3412 		goto qreparse_out;
3413 	}
3414 	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3415 		is_unicode = true;
3416 	else
3417 		is_unicode = false;
3418 
3419 	/* BB FIXME investigate remapping reserved chars here */
3420 	*symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3421 					       nls_codepage);
3422 	if (!*symlinkinfo)
3423 		rc = -ENOMEM;
3424 qreparse_out:
3425 	cifs_buf_release(pSMB);
3426 
3427 	/*
3428 	 * Note: On -EAGAIN error only caller can retry on handle based calls
3429 	 * since file handle passed in no longer valid.
3430 	 */
3431 	return rc;
3432 }
3433 
3434 int
CIFSSMB_set_compression(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid)3435 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3436 		    __u16 fid)
3437 {
3438 	int rc = 0;
3439 	int bytes_returned;
3440 	struct smb_com_transaction_compr_ioctl_req *pSMB;
3441 	struct smb_com_transaction_ioctl_rsp *pSMBr;
3442 
3443 	cifs_dbg(FYI, "Set compression for %u\n", fid);
3444 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3445 		      (void **) &pSMBr);
3446 	if (rc)
3447 		return rc;
3448 
3449 	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3450 
3451 	pSMB->TotalParameterCount = 0;
3452 	pSMB->TotalDataCount = cpu_to_le32(2);
3453 	pSMB->MaxParameterCount = 0;
3454 	pSMB->MaxDataCount = 0;
3455 	pSMB->MaxSetupCount = 4;
3456 	pSMB->Reserved = 0;
3457 	pSMB->ParameterOffset = 0;
3458 	pSMB->DataCount = cpu_to_le32(2);
3459 	pSMB->DataOffset =
3460 		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3461 				compression_state) - 4);  /* 84 */
3462 	pSMB->SetupCount = 4;
3463 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3464 	pSMB->ParameterCount = 0;
3465 	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3466 	pSMB->IsFsctl = 1; /* FSCTL */
3467 	pSMB->IsRootFlag = 0;
3468 	pSMB->Fid = fid; /* file handle always le */
3469 	/* 3 byte pad, followed by 2 byte compress state */
3470 	pSMB->ByteCount = cpu_to_le16(5);
3471 	inc_rfc1001_len(pSMB, 5);
3472 
3473 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3474 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3475 	if (rc)
3476 		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3477 
3478 	cifs_buf_release(pSMB);
3479 
3480 	/*
3481 	 * Note: On -EAGAIN error only caller can retry on handle based calls
3482 	 * since file handle passed in no longer valid.
3483 	 */
3484 	return rc;
3485 }
3486 
3487 
3488 #ifdef CONFIG_CIFS_POSIX
3489 
3490 /*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)3491 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3492 			     struct cifs_posix_ace *cifs_ace)
3493 {
3494 	/* u8 cifs fields do not need le conversion */
3495 	ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3496 	ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3497 	ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3498 /*
3499 	cifs_dbg(FYI, "perm %d tag %d id %d\n",
3500 		 ace->e_perm, ace->e_tag, ace->e_id);
3501 */
3502 
3503 	return;
3504 }
3505 
3506 /* 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)3507 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3508 			       const int acl_type, const int size_of_data_area)
3509 {
3510 	int size =  0;
3511 	int i;
3512 	__u16 count;
3513 	struct cifs_posix_ace *pACE;
3514 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3515 	struct posix_acl_xattr_header *local_acl = (void *)trgt;
3516 
3517 	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3518 		return -EOPNOTSUPP;
3519 
3520 	if (acl_type == ACL_TYPE_ACCESS) {
3521 		count = le16_to_cpu(cifs_acl->access_entry_count);
3522 		pACE = &cifs_acl->ace_array[0];
3523 		size = sizeof(struct cifs_posix_acl);
3524 		size += sizeof(struct cifs_posix_ace) * count;
3525 		/* check if we would go beyond end of SMB */
3526 		if (size_of_data_area < size) {
3527 			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3528 				 size_of_data_area, size);
3529 			return -EINVAL;
3530 		}
3531 	} else if (acl_type == ACL_TYPE_DEFAULT) {
3532 		count = le16_to_cpu(cifs_acl->access_entry_count);
3533 		size = sizeof(struct cifs_posix_acl);
3534 		size += sizeof(struct cifs_posix_ace) * count;
3535 /* skip past access ACEs to get to default ACEs */
3536 		pACE = &cifs_acl->ace_array[count];
3537 		count = le16_to_cpu(cifs_acl->default_entry_count);
3538 		size += sizeof(struct cifs_posix_ace) * count;
3539 		/* check if we would go beyond end of SMB */
3540 		if (size_of_data_area < size)
3541 			return -EINVAL;
3542 	} else {
3543 		/* illegal type */
3544 		return -EINVAL;
3545 	}
3546 
3547 	size = posix_acl_xattr_size(count);
3548 	if ((buflen == 0) || (local_acl == NULL)) {
3549 		/* used to query ACL EA size */
3550 	} else if (size > buflen) {
3551 		return -ERANGE;
3552 	} else /* buffer big enough */ {
3553 		struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3554 
3555 		local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3556 		for (i = 0; i < count ; i++) {
3557 			cifs_convert_ace(&ace[i], pACE);
3558 			pACE++;
3559 		}
3560 	}
3561 	return size;
3562 }
3563 
convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,const struct posix_acl_xattr_entry * local_ace)3564 static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3565 				     const struct posix_acl_xattr_entry *local_ace)
3566 {
3567 	cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3568 	cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3569 	/* BB is there a better way to handle the large uid? */
3570 	if (local_ace->e_id == cpu_to_le32(-1)) {
3571 	/* Probably no need to le convert -1 on any arch but can not hurt */
3572 		cifs_ace->cifs_uid = cpu_to_le64(-1);
3573 	} else
3574 		cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3575 /*
3576 	cifs_dbg(FYI, "perm %d tag %d id %d\n",
3577 		 ace->e_perm, ace->e_tag, ace->e_id);
3578 */
3579 }
3580 
3581 /* 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)3582 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3583 			       const int buflen, const int acl_type)
3584 {
3585 	__u16 rc = 0;
3586 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3587 	struct posix_acl_xattr_header *local_acl = (void *)pACL;
3588 	struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3589 	int count;
3590 	int i;
3591 
3592 	if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3593 		return 0;
3594 
3595 	count = posix_acl_xattr_count((size_t)buflen);
3596 	cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3597 		 count, buflen, le32_to_cpu(local_acl->a_version));
3598 	if (le32_to_cpu(local_acl->a_version) != 2) {
3599 		cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3600 			 le32_to_cpu(local_acl->a_version));
3601 		return 0;
3602 	}
3603 	cifs_acl->version = cpu_to_le16(1);
3604 	if (acl_type == ACL_TYPE_ACCESS) {
3605 		cifs_acl->access_entry_count = cpu_to_le16(count);
3606 		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3607 	} else if (acl_type == ACL_TYPE_DEFAULT) {
3608 		cifs_acl->default_entry_count = cpu_to_le16(count);
3609 		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3610 	} else {
3611 		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3612 		return 0;
3613 	}
3614 	for (i = 0; i < count; i++)
3615 		convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3616 	if (rc == 0) {
3617 		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3618 		rc += sizeof(struct cifs_posix_acl);
3619 		/* BB add check to make sure ACL does not overflow SMB */
3620 	}
3621 	return rc;
3622 }
3623 
3624 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)3625 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3626 		   const unsigned char *searchName,
3627 		   char *acl_inf, const int buflen, const int acl_type,
3628 		   const struct nls_table *nls_codepage, int remap)
3629 {
3630 /* SMB_QUERY_POSIX_ACL */
3631 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3632 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3633 	int rc = 0;
3634 	int bytes_returned;
3635 	int name_len;
3636 	__u16 params, byte_count;
3637 
3638 	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3639 
3640 queryAclRetry:
3641 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3642 		(void **) &pSMBr);
3643 	if (rc)
3644 		return rc;
3645 
3646 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3647 		name_len =
3648 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3649 					   searchName, PATH_MAX, nls_codepage,
3650 					   remap);
3651 		name_len++;     /* trailing null */
3652 		name_len *= 2;
3653 		pSMB->FileName[name_len] = 0;
3654 		pSMB->FileName[name_len+1] = 0;
3655 	} else {
3656 		name_len = copy_path_name(pSMB->FileName, searchName);
3657 	}
3658 
3659 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3660 	pSMB->TotalDataCount = 0;
3661 	pSMB->MaxParameterCount = cpu_to_le16(2);
3662 	/* BB find exact max data count below from sess structure BB */
3663 	pSMB->MaxDataCount = cpu_to_le16(4000);
3664 	pSMB->MaxSetupCount = 0;
3665 	pSMB->Reserved = 0;
3666 	pSMB->Flags = 0;
3667 	pSMB->Timeout = 0;
3668 	pSMB->Reserved2 = 0;
3669 	pSMB->ParameterOffset = cpu_to_le16(
3670 		offsetof(struct smb_com_transaction2_qpi_req,
3671 			 InformationLevel) - 4);
3672 	pSMB->DataCount = 0;
3673 	pSMB->DataOffset = 0;
3674 	pSMB->SetupCount = 1;
3675 	pSMB->Reserved3 = 0;
3676 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3677 	byte_count = params + 1 /* pad */ ;
3678 	pSMB->TotalParameterCount = cpu_to_le16(params);
3679 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3680 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3681 	pSMB->Reserved4 = 0;
3682 	inc_rfc1001_len(pSMB, byte_count);
3683 	pSMB->ByteCount = cpu_to_le16(byte_count);
3684 
3685 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3686 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3687 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3688 	if (rc) {
3689 		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3690 	} else {
3691 		/* decode response */
3692 
3693 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3694 		/* BB also check enough total bytes returned */
3695 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3696 			rc = -EIO;      /* bad smb */
3697 		else {
3698 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3699 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3700 			rc = cifs_copy_posix_acl(acl_inf,
3701 				(char *)&pSMBr->hdr.Protocol+data_offset,
3702 				buflen, acl_type, count);
3703 		}
3704 	}
3705 	cifs_buf_release(pSMB);
3706 	if (rc == -EAGAIN)
3707 		goto queryAclRetry;
3708 	return rc;
3709 }
3710 
3711 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)3712 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3713 		   const unsigned char *fileName,
3714 		   const char *local_acl, const int buflen,
3715 		   const int acl_type,
3716 		   const struct nls_table *nls_codepage, int remap)
3717 {
3718 	struct smb_com_transaction2_spi_req *pSMB = NULL;
3719 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3720 	char *parm_data;
3721 	int name_len;
3722 	int rc = 0;
3723 	int bytes_returned = 0;
3724 	__u16 params, byte_count, data_count, param_offset, offset;
3725 
3726 	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3727 setAclRetry:
3728 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3729 		      (void **) &pSMBr);
3730 	if (rc)
3731 		return rc;
3732 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3733 		name_len =
3734 			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3735 					   PATH_MAX, nls_codepage, remap);
3736 		name_len++;     /* trailing null */
3737 		name_len *= 2;
3738 	} else {
3739 		name_len = copy_path_name(pSMB->FileName, fileName);
3740 	}
3741 	params = 6 + name_len;
3742 	pSMB->MaxParameterCount = cpu_to_le16(2);
3743 	/* BB find max SMB size from sess */
3744 	pSMB->MaxDataCount = cpu_to_le16(1000);
3745 	pSMB->MaxSetupCount = 0;
3746 	pSMB->Reserved = 0;
3747 	pSMB->Flags = 0;
3748 	pSMB->Timeout = 0;
3749 	pSMB->Reserved2 = 0;
3750 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3751 				InformationLevel) - 4;
3752 	offset = param_offset + params;
3753 	parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3754 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3755 
3756 	/* convert to on the wire format for POSIX ACL */
3757 	data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3758 
3759 	if (data_count == 0) {
3760 		rc = -EOPNOTSUPP;
3761 		goto setACLerrorExit;
3762 	}
3763 	pSMB->DataOffset = cpu_to_le16(offset);
3764 	pSMB->SetupCount = 1;
3765 	pSMB->Reserved3 = 0;
3766 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3767 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3768 	byte_count = 3 /* pad */  + params + data_count;
3769 	pSMB->DataCount = cpu_to_le16(data_count);
3770 	pSMB->TotalDataCount = pSMB->DataCount;
3771 	pSMB->ParameterCount = cpu_to_le16(params);
3772 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3773 	pSMB->Reserved4 = 0;
3774 	inc_rfc1001_len(pSMB, byte_count);
3775 	pSMB->ByteCount = cpu_to_le16(byte_count);
3776 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3777 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3778 	if (rc)
3779 		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3780 
3781 setACLerrorExit:
3782 	cifs_buf_release(pSMB);
3783 	if (rc == -EAGAIN)
3784 		goto setAclRetry;
3785 	return rc;
3786 }
3787 
3788 /* BB fix tabs in this function FIXME BB */
3789 int
CIFSGetExtAttr(const unsigned int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3790 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3791 	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3792 {
3793 	int rc = 0;
3794 	struct smb_t2_qfi_req *pSMB = NULL;
3795 	struct smb_t2_qfi_rsp *pSMBr = NULL;
3796 	int bytes_returned;
3797 	__u16 params, byte_count;
3798 
3799 	cifs_dbg(FYI, "In GetExtAttr\n");
3800 	if (tcon == NULL)
3801 		return -ENODEV;
3802 
3803 GetExtAttrRetry:
3804 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3805 			(void **) &pSMBr);
3806 	if (rc)
3807 		return rc;
3808 
3809 	params = 2 /* level */ + 2 /* fid */;
3810 	pSMB->t2.TotalDataCount = 0;
3811 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3812 	/* BB find exact max data count below from sess structure BB */
3813 	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3814 	pSMB->t2.MaxSetupCount = 0;
3815 	pSMB->t2.Reserved = 0;
3816 	pSMB->t2.Flags = 0;
3817 	pSMB->t2.Timeout = 0;
3818 	pSMB->t2.Reserved2 = 0;
3819 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3820 					       Fid) - 4);
3821 	pSMB->t2.DataCount = 0;
3822 	pSMB->t2.DataOffset = 0;
3823 	pSMB->t2.SetupCount = 1;
3824 	pSMB->t2.Reserved3 = 0;
3825 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3826 	byte_count = params + 1 /* pad */ ;
3827 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3828 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3829 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3830 	pSMB->Pad = 0;
3831 	pSMB->Fid = netfid;
3832 	inc_rfc1001_len(pSMB, byte_count);
3833 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3834 
3835 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3836 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3837 	if (rc) {
3838 		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3839 	} else {
3840 		/* decode response */
3841 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3842 		/* BB also check enough total bytes returned */
3843 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3844 			/* If rc should we check for EOPNOSUPP and
3845 			   disable the srvino flag? or in caller? */
3846 			rc = -EIO;      /* bad smb */
3847 		else {
3848 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3849 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3850 			struct file_chattr_info *pfinfo;
3851 			/* BB Do we need a cast or hash here ? */
3852 			if (count != 16) {
3853 				cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3854 				rc = -EIO;
3855 				goto GetExtAttrOut;
3856 			}
3857 			pfinfo = (struct file_chattr_info *)
3858 				 (data_offset + (char *) &pSMBr->hdr.Protocol);
3859 			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
3860 			*pMask = le64_to_cpu(pfinfo->mask);
3861 		}
3862 	}
3863 GetExtAttrOut:
3864 	cifs_buf_release(pSMB);
3865 	if (rc == -EAGAIN)
3866 		goto GetExtAttrRetry;
3867 	return rc;
3868 }
3869 
3870 #endif /* CONFIG_POSIX */
3871 
3872 /*
3873  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3874  * all NT TRANSACTS that we init here have total parm and data under about 400
3875  * bytes (to fit in small cifs buffer size), which is the case so far, it
3876  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3877  * returned setup area) and MaxParameterCount (returned parms size) must be set
3878  * by caller
3879  */
3880 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3881 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3882 		   const int parm_len, struct cifs_tcon *tcon,
3883 		   void **ret_buf)
3884 {
3885 	int rc;
3886 	__u32 temp_offset;
3887 	struct smb_com_ntransact_req *pSMB;
3888 
3889 	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3890 				(void **)&pSMB);
3891 	if (rc)
3892 		return rc;
3893 	*ret_buf = (void *)pSMB;
3894 	pSMB->Reserved = 0;
3895 	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3896 	pSMB->TotalDataCount  = 0;
3897 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3898 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3899 	pSMB->DataCount  = pSMB->TotalDataCount;
3900 	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3901 			(setup_count * 2) - 4 /* for rfc1001 length itself */;
3902 	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3903 	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3904 	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3905 	pSMB->SubCommand = cpu_to_le16(sub_command);
3906 	return 0;
3907 }
3908 
3909 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3910 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3911 		   __u32 *pparmlen, __u32 *pdatalen)
3912 {
3913 	char *end_of_smb;
3914 	__u32 data_count, data_offset, parm_count, parm_offset;
3915 	struct smb_com_ntransact_rsp *pSMBr;
3916 	u16 bcc;
3917 
3918 	*pdatalen = 0;
3919 	*pparmlen = 0;
3920 
3921 	if (buf == NULL)
3922 		return -EINVAL;
3923 
3924 	pSMBr = (struct smb_com_ntransact_rsp *)buf;
3925 
3926 	bcc = get_bcc(&pSMBr->hdr);
3927 	end_of_smb = 2 /* sizeof byte count */ + bcc +
3928 			(char *)&pSMBr->ByteCount;
3929 
3930 	data_offset = le32_to_cpu(pSMBr->DataOffset);
3931 	data_count = le32_to_cpu(pSMBr->DataCount);
3932 	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3933 	parm_count = le32_to_cpu(pSMBr->ParameterCount);
3934 
3935 	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3936 	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3937 
3938 	/* should we also check that parm and data areas do not overlap? */
3939 	if (*ppparm > end_of_smb) {
3940 		cifs_dbg(FYI, "parms start after end of smb\n");
3941 		return -EINVAL;
3942 	} else if (parm_count + *ppparm > end_of_smb) {
3943 		cifs_dbg(FYI, "parm end after end of smb\n");
3944 		return -EINVAL;
3945 	} else if (*ppdata > end_of_smb) {
3946 		cifs_dbg(FYI, "data starts after end of smb\n");
3947 		return -EINVAL;
3948 	} else if (data_count + *ppdata > end_of_smb) {
3949 		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3950 			 *ppdata, data_count, (data_count + *ppdata),
3951 			 end_of_smb, pSMBr);
3952 		return -EINVAL;
3953 	} else if (parm_count + data_count > bcc) {
3954 		cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3955 		return -EINVAL;
3956 	}
3957 	*pdatalen = data_count;
3958 	*pparmlen = parm_count;
3959 	return 0;
3960 }
3961 
3962 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3963 int
CIFSSMBGetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd ** acl_inf,__u32 * pbuflen)3964 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3965 		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3966 {
3967 	int rc = 0;
3968 	int buf_type = 0;
3969 	QUERY_SEC_DESC_REQ *pSMB;
3970 	struct kvec iov[1];
3971 	struct kvec rsp_iov;
3972 
3973 	cifs_dbg(FYI, "GetCifsACL\n");
3974 
3975 	*pbuflen = 0;
3976 	*acl_inf = NULL;
3977 
3978 	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3979 			8 /* parm len */, tcon, (void **) &pSMB);
3980 	if (rc)
3981 		return rc;
3982 
3983 	pSMB->MaxParameterCount = cpu_to_le32(4);
3984 	/* BB TEST with big acls that might need to be e.g. larger than 16K */
3985 	pSMB->MaxSetupCount = 0;
3986 	pSMB->Fid = fid; /* file handle always le */
3987 	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3988 				     CIFS_ACL_DACL);
3989 	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3990 	inc_rfc1001_len(pSMB, 11);
3991 	iov[0].iov_base = (char *)pSMB;
3992 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3993 
3994 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3995 			  0, &rsp_iov);
3996 	cifs_small_buf_release(pSMB);
3997 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3998 	if (rc) {
3999 		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
4000 	} else {                /* decode response */
4001 		__le32 *parm;
4002 		__u32 parm_len;
4003 		__u32 acl_len;
4004 		struct smb_com_ntransact_rsp *pSMBr;
4005 		char *pdata;
4006 
4007 /* validate_nttransact */
4008 		rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
4009 					&pdata, &parm_len, pbuflen);
4010 		if (rc)
4011 			goto qsec_out;
4012 		pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
4013 
4014 		cifs_dbg(FYI, "smb %p parm %p data %p\n",
4015 			 pSMBr, parm, *acl_inf);
4016 
4017 		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
4018 			rc = -EIO;      /* bad smb */
4019 			*pbuflen = 0;
4020 			goto qsec_out;
4021 		}
4022 
4023 /* BB check that data area is minimum length and as big as acl_len */
4024 
4025 		acl_len = le32_to_cpu(*parm);
4026 		if (acl_len != *pbuflen) {
4027 			cifs_dbg(VFS, "acl length %d does not match %d\n",
4028 				 acl_len, *pbuflen);
4029 			if (*pbuflen > acl_len)
4030 				*pbuflen = acl_len;
4031 		}
4032 
4033 		/* check if buffer is big enough for the acl
4034 		   header followed by the smallest SID */
4035 		if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
4036 		    (*pbuflen >= 64 * 1024)) {
4037 			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
4038 			rc = -EINVAL;
4039 			*pbuflen = 0;
4040 		} else {
4041 			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
4042 			if (*acl_inf == NULL) {
4043 				*pbuflen = 0;
4044 				rc = -ENOMEM;
4045 			}
4046 		}
4047 	}
4048 qsec_out:
4049 	free_rsp_buf(buf_type, rsp_iov.iov_base);
4050 	return rc;
4051 }
4052 
4053 int
CIFSSMBSetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd * pntsd,__u32 acllen,int aclflag)4054 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
4055 			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
4056 {
4057 	__u16 byte_count, param_count, data_count, param_offset, data_offset;
4058 	int rc = 0;
4059 	int bytes_returned = 0;
4060 	SET_SEC_DESC_REQ *pSMB = NULL;
4061 	void *pSMBr;
4062 
4063 setCifsAclRetry:
4064 	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
4065 	if (rc)
4066 		return rc;
4067 
4068 	pSMB->MaxSetupCount = 0;
4069 	pSMB->Reserved = 0;
4070 
4071 	param_count = 8;
4072 	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
4073 	data_count = acllen;
4074 	data_offset = param_offset + param_count;
4075 	byte_count = 3 /* pad */  + param_count;
4076 
4077 	pSMB->DataCount = cpu_to_le32(data_count);
4078 	pSMB->TotalDataCount = pSMB->DataCount;
4079 	pSMB->MaxParameterCount = cpu_to_le32(4);
4080 	pSMB->MaxDataCount = cpu_to_le32(16384);
4081 	pSMB->ParameterCount = cpu_to_le32(param_count);
4082 	pSMB->ParameterOffset = cpu_to_le32(param_offset);
4083 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4084 	pSMB->DataOffset = cpu_to_le32(data_offset);
4085 	pSMB->SetupCount = 0;
4086 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
4087 	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
4088 
4089 	pSMB->Fid = fid; /* file handle always le */
4090 	pSMB->Reserved2 = 0;
4091 	pSMB->AclFlags = cpu_to_le32(aclflag);
4092 
4093 	if (pntsd && acllen) {
4094 		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
4095 				data_offset, pntsd, acllen);
4096 		inc_rfc1001_len(pSMB, byte_count + data_count);
4097 	} else
4098 		inc_rfc1001_len(pSMB, byte_count);
4099 
4100 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4101 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4102 
4103 	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
4104 		 bytes_returned, rc);
4105 	if (rc)
4106 		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
4107 	cifs_buf_release(pSMB);
4108 
4109 	if (rc == -EAGAIN)
4110 		goto setCifsAclRetry;
4111 
4112 	return (rc);
4113 }
4114 
4115 
4116 /* Legacy Query Path Information call for lookup to old servers such
4117    as Win9x/WinME */
4118 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)4119 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
4120 		    const char *search_name, FILE_ALL_INFO *data,
4121 		    const struct nls_table *nls_codepage, int remap)
4122 {
4123 	QUERY_INFORMATION_REQ *pSMB;
4124 	QUERY_INFORMATION_RSP *pSMBr;
4125 	int rc = 0;
4126 	int bytes_returned;
4127 	int name_len;
4128 
4129 	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
4130 QInfRetry:
4131 	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4132 		      (void **) &pSMBr);
4133 	if (rc)
4134 		return rc;
4135 
4136 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4137 		name_len =
4138 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4139 					   search_name, PATH_MAX, nls_codepage,
4140 					   remap);
4141 		name_len++;     /* trailing null */
4142 		name_len *= 2;
4143 	} else {
4144 		name_len = copy_path_name(pSMB->FileName, search_name);
4145 	}
4146 	pSMB->BufferFormat = 0x04;
4147 	name_len++; /* account for buffer type byte */
4148 	inc_rfc1001_len(pSMB, (__u16)name_len);
4149 	pSMB->ByteCount = cpu_to_le16(name_len);
4150 
4151 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4152 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4153 	if (rc) {
4154 		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4155 	} else if (data) {
4156 		struct timespec64 ts;
4157 		__u32 time = le32_to_cpu(pSMBr->last_write_time);
4158 
4159 		/* decode response */
4160 		/* BB FIXME - add time zone adjustment BB */
4161 		memset(data, 0, sizeof(FILE_ALL_INFO));
4162 		ts.tv_nsec = 0;
4163 		ts.tv_sec = time;
4164 		/* decode time fields */
4165 		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4166 		data->LastWriteTime = data->ChangeTime;
4167 		data->LastAccessTime = 0;
4168 		data->AllocationSize =
4169 			cpu_to_le64(le32_to_cpu(pSMBr->size));
4170 		data->EndOfFile = data->AllocationSize;
4171 		data->Attributes =
4172 			cpu_to_le32(le16_to_cpu(pSMBr->attr));
4173 	} else
4174 		rc = -EIO; /* bad buffer passed in */
4175 
4176 	cifs_buf_release(pSMB);
4177 
4178 	if (rc == -EAGAIN)
4179 		goto QInfRetry;
4180 
4181 	return rc;
4182 }
4183 
4184 int
CIFSSMBQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)4185 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4186 		 u16 netfid, FILE_ALL_INFO *pFindData)
4187 {
4188 	struct smb_t2_qfi_req *pSMB = NULL;
4189 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4190 	int rc = 0;
4191 	int bytes_returned;
4192 	__u16 params, byte_count;
4193 
4194 QFileInfoRetry:
4195 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4196 		      (void **) &pSMBr);
4197 	if (rc)
4198 		return rc;
4199 
4200 	params = 2 /* level */ + 2 /* fid */;
4201 	pSMB->t2.TotalDataCount = 0;
4202 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4203 	/* BB find exact max data count below from sess structure BB */
4204 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4205 	pSMB->t2.MaxSetupCount = 0;
4206 	pSMB->t2.Reserved = 0;
4207 	pSMB->t2.Flags = 0;
4208 	pSMB->t2.Timeout = 0;
4209 	pSMB->t2.Reserved2 = 0;
4210 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4211 					       Fid) - 4);
4212 	pSMB->t2.DataCount = 0;
4213 	pSMB->t2.DataOffset = 0;
4214 	pSMB->t2.SetupCount = 1;
4215 	pSMB->t2.Reserved3 = 0;
4216 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4217 	byte_count = params + 1 /* pad */ ;
4218 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4219 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4220 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4221 	pSMB->Pad = 0;
4222 	pSMB->Fid = netfid;
4223 	inc_rfc1001_len(pSMB, byte_count);
4224 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4225 
4226 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4227 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4228 	if (rc) {
4229 		cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4230 	} else {		/* decode response */
4231 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4232 
4233 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4234 			rc = -EIO;
4235 		else if (get_bcc(&pSMBr->hdr) < 40)
4236 			rc = -EIO;	/* bad smb */
4237 		else if (pFindData) {
4238 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4239 			memcpy((char *) pFindData,
4240 			       (char *) &pSMBr->hdr.Protocol +
4241 			       data_offset, sizeof(FILE_ALL_INFO));
4242 		} else
4243 		    rc = -ENOMEM;
4244 	}
4245 	cifs_buf_release(pSMB);
4246 	if (rc == -EAGAIN)
4247 		goto QFileInfoRetry;
4248 
4249 	return rc;
4250 }
4251 
4252 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)4253 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4254 		 const char *search_name, FILE_ALL_INFO *data,
4255 		 int legacy /* old style infolevel */,
4256 		 const struct nls_table *nls_codepage, int remap)
4257 {
4258 	/* level 263 SMB_QUERY_FILE_ALL_INFO */
4259 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4260 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4261 	int rc = 0;
4262 	int bytes_returned;
4263 	int name_len;
4264 	__u16 params, byte_count;
4265 
4266 	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4267 QPathInfoRetry:
4268 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4269 		      (void **) &pSMBr);
4270 	if (rc)
4271 		return rc;
4272 
4273 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4274 		name_len =
4275 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4276 				       PATH_MAX, nls_codepage, remap);
4277 		name_len++;	/* trailing null */
4278 		name_len *= 2;
4279 	} else {
4280 		name_len = copy_path_name(pSMB->FileName, search_name);
4281 	}
4282 
4283 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4284 	pSMB->TotalDataCount = 0;
4285 	pSMB->MaxParameterCount = cpu_to_le16(2);
4286 	/* BB find exact max SMB PDU from sess structure BB */
4287 	pSMB->MaxDataCount = cpu_to_le16(4000);
4288 	pSMB->MaxSetupCount = 0;
4289 	pSMB->Reserved = 0;
4290 	pSMB->Flags = 0;
4291 	pSMB->Timeout = 0;
4292 	pSMB->Reserved2 = 0;
4293 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4294 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4295 	pSMB->DataCount = 0;
4296 	pSMB->DataOffset = 0;
4297 	pSMB->SetupCount = 1;
4298 	pSMB->Reserved3 = 0;
4299 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4300 	byte_count = params + 1 /* pad */ ;
4301 	pSMB->TotalParameterCount = cpu_to_le16(params);
4302 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4303 	if (legacy)
4304 		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4305 	else
4306 		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4307 	pSMB->Reserved4 = 0;
4308 	inc_rfc1001_len(pSMB, byte_count);
4309 	pSMB->ByteCount = cpu_to_le16(byte_count);
4310 
4311 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4312 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4313 	if (rc) {
4314 		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4315 	} else {		/* decode response */
4316 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4317 
4318 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
4319 			rc = -EIO;
4320 		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4321 			rc = -EIO;	/* bad smb */
4322 		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4323 			rc = -EIO;  /* 24 or 26 expected but we do not read
4324 					last field */
4325 		else if (data) {
4326 			int size;
4327 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4328 
4329 			/*
4330 			 * On legacy responses we do not read the last field,
4331 			 * EAsize, fortunately since it varies by subdialect and
4332 			 * also note it differs on Set vs Get, ie two bytes or 4
4333 			 * bytes depending but we don't care here.
4334 			 */
4335 			if (legacy)
4336 				size = sizeof(FILE_INFO_STANDARD);
4337 			else
4338 				size = sizeof(FILE_ALL_INFO);
4339 			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4340 			       data_offset, size);
4341 		} else
4342 		    rc = -ENOMEM;
4343 	}
4344 	cifs_buf_release(pSMB);
4345 	if (rc == -EAGAIN)
4346 		goto QPathInfoRetry;
4347 
4348 	return rc;
4349 }
4350 
4351 int
CIFSSMBUnixQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)4352 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4353 		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4354 {
4355 	struct smb_t2_qfi_req *pSMB = NULL;
4356 	struct smb_t2_qfi_rsp *pSMBr = NULL;
4357 	int rc = 0;
4358 	int bytes_returned;
4359 	__u16 params, byte_count;
4360 
4361 UnixQFileInfoRetry:
4362 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4363 		      (void **) &pSMBr);
4364 	if (rc)
4365 		return rc;
4366 
4367 	params = 2 /* level */ + 2 /* fid */;
4368 	pSMB->t2.TotalDataCount = 0;
4369 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4370 	/* BB find exact max data count below from sess structure BB */
4371 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4372 	pSMB->t2.MaxSetupCount = 0;
4373 	pSMB->t2.Reserved = 0;
4374 	pSMB->t2.Flags = 0;
4375 	pSMB->t2.Timeout = 0;
4376 	pSMB->t2.Reserved2 = 0;
4377 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4378 					       Fid) - 4);
4379 	pSMB->t2.DataCount = 0;
4380 	pSMB->t2.DataOffset = 0;
4381 	pSMB->t2.SetupCount = 1;
4382 	pSMB->t2.Reserved3 = 0;
4383 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4384 	byte_count = params + 1 /* pad */ ;
4385 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4386 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4387 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4388 	pSMB->Pad = 0;
4389 	pSMB->Fid = netfid;
4390 	inc_rfc1001_len(pSMB, byte_count);
4391 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4392 
4393 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4394 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4395 	if (rc) {
4396 		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4397 	} else {		/* decode response */
4398 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4399 
4400 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4401 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4402 			rc = -EIO;	/* bad smb */
4403 		} else {
4404 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4405 			memcpy((char *) pFindData,
4406 			       (char *) &pSMBr->hdr.Protocol +
4407 			       data_offset,
4408 			       sizeof(FILE_UNIX_BASIC_INFO));
4409 		}
4410 	}
4411 
4412 	cifs_buf_release(pSMB);
4413 	if (rc == -EAGAIN)
4414 		goto UnixQFileInfoRetry;
4415 
4416 	return rc;
4417 }
4418 
4419 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)4420 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4421 		     const unsigned char *searchName,
4422 		     FILE_UNIX_BASIC_INFO *pFindData,
4423 		     const struct nls_table *nls_codepage, int remap)
4424 {
4425 /* SMB_QUERY_FILE_UNIX_BASIC */
4426 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4427 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4428 	int rc = 0;
4429 	int bytes_returned = 0;
4430 	int name_len;
4431 	__u16 params, byte_count;
4432 
4433 	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4434 UnixQPathInfoRetry:
4435 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4436 		      (void **) &pSMBr);
4437 	if (rc)
4438 		return rc;
4439 
4440 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4441 		name_len =
4442 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4443 				       PATH_MAX, nls_codepage, remap);
4444 		name_len++;	/* trailing null */
4445 		name_len *= 2;
4446 	} else {
4447 		name_len = copy_path_name(pSMB->FileName, searchName);
4448 	}
4449 
4450 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4451 	pSMB->TotalDataCount = 0;
4452 	pSMB->MaxParameterCount = cpu_to_le16(2);
4453 	/* BB find exact max SMB PDU from sess structure BB */
4454 	pSMB->MaxDataCount = cpu_to_le16(4000);
4455 	pSMB->MaxSetupCount = 0;
4456 	pSMB->Reserved = 0;
4457 	pSMB->Flags = 0;
4458 	pSMB->Timeout = 0;
4459 	pSMB->Reserved2 = 0;
4460 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4461 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4462 	pSMB->DataCount = 0;
4463 	pSMB->DataOffset = 0;
4464 	pSMB->SetupCount = 1;
4465 	pSMB->Reserved3 = 0;
4466 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4467 	byte_count = params + 1 /* pad */ ;
4468 	pSMB->TotalParameterCount = cpu_to_le16(params);
4469 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4470 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4471 	pSMB->Reserved4 = 0;
4472 	inc_rfc1001_len(pSMB, byte_count);
4473 	pSMB->ByteCount = cpu_to_le16(byte_count);
4474 
4475 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4476 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4477 	if (rc) {
4478 		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4479 	} else {		/* decode response */
4480 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4481 
4482 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4483 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4484 			rc = -EIO;	/* bad smb */
4485 		} else {
4486 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4487 			memcpy((char *) pFindData,
4488 			       (char *) &pSMBr->hdr.Protocol +
4489 			       data_offset,
4490 			       sizeof(FILE_UNIX_BASIC_INFO));
4491 		}
4492 	}
4493 	cifs_buf_release(pSMB);
4494 	if (rc == -EAGAIN)
4495 		goto UnixQPathInfoRetry;
4496 
4497 	return rc;
4498 }
4499 
4500 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4501 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)4502 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4503 	      const char *searchName, struct cifs_sb_info *cifs_sb,
4504 	      __u16 *pnetfid, __u16 search_flags,
4505 	      struct cifs_search_info *psrch_inf, bool msearch)
4506 {
4507 /* level 257 SMB_ */
4508 	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4509 	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4510 	T2_FFIRST_RSP_PARMS *parms;
4511 	int rc = 0;
4512 	int bytes_returned = 0;
4513 	int name_len, remap;
4514 	__u16 params, byte_count;
4515 	struct nls_table *nls_codepage;
4516 
4517 	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4518 
4519 findFirstRetry:
4520 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4521 		      (void **) &pSMBr);
4522 	if (rc)
4523 		return rc;
4524 
4525 	nls_codepage = cifs_sb->local_nls;
4526 	remap = cifs_remap(cifs_sb);
4527 
4528 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4529 		name_len =
4530 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4531 				       PATH_MAX, nls_codepage, remap);
4532 		/* We can not add the asterik earlier in case
4533 		it got remapped to 0xF03A as if it were part of the
4534 		directory name instead of a wildcard */
4535 		name_len *= 2;
4536 		if (msearch) {
4537 			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4538 			pSMB->FileName[name_len+1] = 0;
4539 			pSMB->FileName[name_len+2] = '*';
4540 			pSMB->FileName[name_len+3] = 0;
4541 			name_len += 4; /* now the trailing null */
4542 			/* null terminate just in case */
4543 			pSMB->FileName[name_len] = 0;
4544 			pSMB->FileName[name_len+1] = 0;
4545 			name_len += 2;
4546 		}
4547 	} else {
4548 		name_len = copy_path_name(pSMB->FileName, searchName);
4549 		if (msearch) {
4550 			if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4551 				name_len = PATH_MAX-2;
4552 			/* overwrite nul byte */
4553 			pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4554 			pSMB->FileName[name_len] = '*';
4555 			pSMB->FileName[name_len+1] = 0;
4556 			name_len += 2;
4557 		}
4558 	}
4559 
4560 	params = 12 + name_len /* includes null */ ;
4561 	pSMB->TotalDataCount = 0;	/* no EAs */
4562 	pSMB->MaxParameterCount = cpu_to_le16(10);
4563 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4564 	pSMB->MaxSetupCount = 0;
4565 	pSMB->Reserved = 0;
4566 	pSMB->Flags = 0;
4567 	pSMB->Timeout = 0;
4568 	pSMB->Reserved2 = 0;
4569 	byte_count = params + 1 /* pad */ ;
4570 	pSMB->TotalParameterCount = cpu_to_le16(params);
4571 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4572 	pSMB->ParameterOffset = cpu_to_le16(
4573 	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4574 		- 4);
4575 	pSMB->DataCount = 0;
4576 	pSMB->DataOffset = 0;
4577 	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
4578 	pSMB->Reserved3 = 0;
4579 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4580 	pSMB->SearchAttributes =
4581 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4582 			ATTR_DIRECTORY);
4583 	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4584 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4585 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4586 
4587 	/* BB what should we set StorageType to? Does it matter? BB */
4588 	pSMB->SearchStorageType = 0;
4589 	inc_rfc1001_len(pSMB, byte_count);
4590 	pSMB->ByteCount = cpu_to_le16(byte_count);
4591 
4592 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4593 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4594 	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4595 
4596 	if (rc) {/* BB add logic to retry regular search if Unix search
4597 			rejected unexpectedly by server */
4598 		/* BB Add code to handle unsupported level rc */
4599 		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4600 
4601 		cifs_buf_release(pSMB);
4602 
4603 		/* BB eventually could optimize out free and realloc of buf */
4604 		/*    for this case */
4605 		if (rc == -EAGAIN)
4606 			goto findFirstRetry;
4607 	} else { /* decode response */
4608 		/* BB remember to free buffer if error BB */
4609 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4610 		if (rc == 0) {
4611 			unsigned int lnoff;
4612 
4613 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4614 				psrch_inf->unicode = true;
4615 			else
4616 				psrch_inf->unicode = false;
4617 
4618 			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4619 			psrch_inf->smallBuf = 0;
4620 			psrch_inf->srch_entries_start =
4621 				(char *) &pSMBr->hdr.Protocol +
4622 					le16_to_cpu(pSMBr->t2.DataOffset);
4623 			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4624 			       le16_to_cpu(pSMBr->t2.ParameterOffset));
4625 
4626 			if (parms->EndofSearch)
4627 				psrch_inf->endOfSearch = true;
4628 			else
4629 				psrch_inf->endOfSearch = false;
4630 
4631 			psrch_inf->entries_in_buffer =
4632 					le16_to_cpu(parms->SearchCount);
4633 			psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4634 				psrch_inf->entries_in_buffer;
4635 			lnoff = le16_to_cpu(parms->LastNameOffset);
4636 			if (CIFSMaxBufSize < lnoff) {
4637 				cifs_dbg(VFS, "ignoring corrupt resume name\n");
4638 				psrch_inf->last_entry = NULL;
4639 				return rc;
4640 			}
4641 
4642 			psrch_inf->last_entry = psrch_inf->srch_entries_start +
4643 							lnoff;
4644 
4645 			if (pnetfid)
4646 				*pnetfid = parms->SearchHandle;
4647 		} else {
4648 			cifs_buf_release(pSMB);
4649 		}
4650 	}
4651 
4652 	return rc;
4653 }
4654 
CIFSFindNext(const unsigned int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4655 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4656 		 __u16 searchHandle, __u16 search_flags,
4657 		 struct cifs_search_info *psrch_inf)
4658 {
4659 	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4660 	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4661 	T2_FNEXT_RSP_PARMS *parms;
4662 	char *response_data;
4663 	int rc = 0;
4664 	int bytes_returned;
4665 	unsigned int name_len;
4666 	__u16 params, byte_count;
4667 
4668 	cifs_dbg(FYI, "In FindNext\n");
4669 
4670 	if (psrch_inf->endOfSearch)
4671 		return -ENOENT;
4672 
4673 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4674 		(void **) &pSMBr);
4675 	if (rc)
4676 		return rc;
4677 
4678 	params = 14; /* includes 2 bytes of null string, converted to LE below*/
4679 	byte_count = 0;
4680 	pSMB->TotalDataCount = 0;       /* no EAs */
4681 	pSMB->MaxParameterCount = cpu_to_le16(8);
4682 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4683 	pSMB->MaxSetupCount = 0;
4684 	pSMB->Reserved = 0;
4685 	pSMB->Flags = 0;
4686 	pSMB->Timeout = 0;
4687 	pSMB->Reserved2 = 0;
4688 	pSMB->ParameterOffset =  cpu_to_le16(
4689 	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4690 	pSMB->DataCount = 0;
4691 	pSMB->DataOffset = 0;
4692 	pSMB->SetupCount = 1;
4693 	pSMB->Reserved3 = 0;
4694 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4695 	pSMB->SearchHandle = searchHandle;      /* always kept as le */
4696 	pSMB->SearchCount =
4697 		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4698 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4699 	pSMB->ResumeKey = psrch_inf->resume_key;
4700 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4701 
4702 	name_len = psrch_inf->resume_name_len;
4703 	params += name_len;
4704 	if (name_len < PATH_MAX) {
4705 		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4706 		byte_count += name_len;
4707 		/* 14 byte parm len above enough for 2 byte null terminator */
4708 		pSMB->ResumeFileName[name_len] = 0;
4709 		pSMB->ResumeFileName[name_len+1] = 0;
4710 	} else {
4711 		rc = -EINVAL;
4712 		goto FNext2_err_exit;
4713 	}
4714 	byte_count = params + 1 /* pad */ ;
4715 	pSMB->TotalParameterCount = cpu_to_le16(params);
4716 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4717 	inc_rfc1001_len(pSMB, byte_count);
4718 	pSMB->ByteCount = cpu_to_le16(byte_count);
4719 
4720 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4721 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4722 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4723 	if (rc) {
4724 		if (rc == -EBADF) {
4725 			psrch_inf->endOfSearch = true;
4726 			cifs_buf_release(pSMB);
4727 			rc = 0; /* search probably was closed at end of search*/
4728 		} else
4729 			cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4730 	} else {                /* decode response */
4731 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4732 
4733 		if (rc == 0) {
4734 			unsigned int lnoff;
4735 
4736 			/* BB fixme add lock for file (srch_info) struct here */
4737 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4738 				psrch_inf->unicode = true;
4739 			else
4740 				psrch_inf->unicode = false;
4741 			response_data = (char *) &pSMBr->hdr.Protocol +
4742 			       le16_to_cpu(pSMBr->t2.ParameterOffset);
4743 			parms = (T2_FNEXT_RSP_PARMS *)response_data;
4744 			response_data = (char *)&pSMBr->hdr.Protocol +
4745 				le16_to_cpu(pSMBr->t2.DataOffset);
4746 			if (psrch_inf->smallBuf)
4747 				cifs_small_buf_release(
4748 					psrch_inf->ntwrk_buf_start);
4749 			else
4750 				cifs_buf_release(psrch_inf->ntwrk_buf_start);
4751 			psrch_inf->srch_entries_start = response_data;
4752 			psrch_inf->ntwrk_buf_start = (char *)pSMB;
4753 			psrch_inf->smallBuf = 0;
4754 			if (parms->EndofSearch)
4755 				psrch_inf->endOfSearch = true;
4756 			else
4757 				psrch_inf->endOfSearch = false;
4758 			psrch_inf->entries_in_buffer =
4759 						le16_to_cpu(parms->SearchCount);
4760 			psrch_inf->index_of_last_entry +=
4761 				psrch_inf->entries_in_buffer;
4762 			lnoff = le16_to_cpu(parms->LastNameOffset);
4763 			if (CIFSMaxBufSize < lnoff) {
4764 				cifs_dbg(VFS, "ignoring corrupt resume name\n");
4765 				psrch_inf->last_entry = NULL;
4766 				return rc;
4767 			} else
4768 				psrch_inf->last_entry =
4769 					psrch_inf->srch_entries_start + lnoff;
4770 
4771 /*  cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4772     psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4773 
4774 			/* BB fixme add unlock here */
4775 		}
4776 
4777 	}
4778 
4779 	/* BB On error, should we leave previous search buf (and count and
4780 	last entry fields) intact or free the previous one? */
4781 
4782 	/* Note: On -EAGAIN error only caller can retry on handle based calls
4783 	since file handle passed in no longer valid */
4784 FNext2_err_exit:
4785 	if (rc != 0)
4786 		cifs_buf_release(pSMB);
4787 	return rc;
4788 }
4789 
4790 int
CIFSFindClose(const unsigned int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4791 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4792 	      const __u16 searchHandle)
4793 {
4794 	int rc = 0;
4795 	FINDCLOSE_REQ *pSMB = NULL;
4796 
4797 	cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4798 	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4799 
4800 	/* no sense returning error if session restarted
4801 		as file handle has been closed */
4802 	if (rc == -EAGAIN)
4803 		return 0;
4804 	if (rc)
4805 		return rc;
4806 
4807 	pSMB->FileID = searchHandle;
4808 	pSMB->ByteCount = 0;
4809 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4810 	cifs_small_buf_release(pSMB);
4811 	if (rc)
4812 		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4813 
4814 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4815 
4816 	/* Since session is dead, search handle closed on server already */
4817 	if (rc == -EAGAIN)
4818 		rc = 0;
4819 
4820 	return rc;
4821 }
4822 
4823 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)4824 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4825 		      const char *search_name, __u64 *inode_number,
4826 		      const struct nls_table *nls_codepage, int remap)
4827 {
4828 	int rc = 0;
4829 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4830 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4831 	int name_len, bytes_returned;
4832 	__u16 params, byte_count;
4833 
4834 	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4835 	if (tcon == NULL)
4836 		return -ENODEV;
4837 
4838 GetInodeNumberRetry:
4839 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4840 		      (void **) &pSMBr);
4841 	if (rc)
4842 		return rc;
4843 
4844 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4845 		name_len =
4846 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4847 					   search_name, PATH_MAX, nls_codepage,
4848 					   remap);
4849 		name_len++;     /* trailing null */
4850 		name_len *= 2;
4851 	} else {
4852 		name_len = copy_path_name(pSMB->FileName, search_name);
4853 	}
4854 
4855 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4856 	pSMB->TotalDataCount = 0;
4857 	pSMB->MaxParameterCount = cpu_to_le16(2);
4858 	/* BB find exact max data count below from sess structure BB */
4859 	pSMB->MaxDataCount = cpu_to_le16(4000);
4860 	pSMB->MaxSetupCount = 0;
4861 	pSMB->Reserved = 0;
4862 	pSMB->Flags = 0;
4863 	pSMB->Timeout = 0;
4864 	pSMB->Reserved2 = 0;
4865 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4866 		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4867 	pSMB->DataCount = 0;
4868 	pSMB->DataOffset = 0;
4869 	pSMB->SetupCount = 1;
4870 	pSMB->Reserved3 = 0;
4871 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4872 	byte_count = params + 1 /* pad */ ;
4873 	pSMB->TotalParameterCount = cpu_to_le16(params);
4874 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4875 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4876 	pSMB->Reserved4 = 0;
4877 	inc_rfc1001_len(pSMB, byte_count);
4878 	pSMB->ByteCount = cpu_to_le16(byte_count);
4879 
4880 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4881 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4882 	if (rc) {
4883 		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4884 	} else {
4885 		/* decode response */
4886 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4887 		/* BB also check enough total bytes returned */
4888 		if (rc || get_bcc(&pSMBr->hdr) < 2)
4889 			/* If rc should we check for EOPNOSUPP and
4890 			disable the srvino flag? or in caller? */
4891 			rc = -EIO;      /* bad smb */
4892 		else {
4893 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4894 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4895 			struct file_internal_info *pfinfo;
4896 			/* BB Do we need a cast or hash here ? */
4897 			if (count < 8) {
4898 				cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4899 				rc = -EIO;
4900 				goto GetInodeNumOut;
4901 			}
4902 			pfinfo = (struct file_internal_info *)
4903 				(data_offset + (char *) &pSMBr->hdr.Protocol);
4904 			*inode_number = le64_to_cpu(pfinfo->UniqueId);
4905 		}
4906 	}
4907 GetInodeNumOut:
4908 	cifs_buf_release(pSMB);
4909 	if (rc == -EAGAIN)
4910 		goto GetInodeNumberRetry;
4911 	return rc;
4912 }
4913 
4914 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)4915 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4916 		const char *search_name, struct dfs_info3_param **target_nodes,
4917 		unsigned int *num_of_nodes,
4918 		const struct nls_table *nls_codepage, int remap)
4919 {
4920 /* TRANS2_GET_DFS_REFERRAL */
4921 	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4922 	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4923 	int rc = 0;
4924 	int bytes_returned;
4925 	int name_len;
4926 	__u16 params, byte_count;
4927 	*num_of_nodes = 0;
4928 	*target_nodes = NULL;
4929 
4930 	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4931 	if (ses == NULL || ses->tcon_ipc == NULL)
4932 		return -ENODEV;
4933 
4934 getDFSRetry:
4935 	rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4936 		      (void **) &pSMBr);
4937 	if (rc)
4938 		return rc;
4939 
4940 	/* server pointer checked in called function,
4941 	but should never be null here anyway */
4942 	pSMB->hdr.Mid = get_next_mid(ses->server);
4943 	pSMB->hdr.Tid = ses->tcon_ipc->tid;
4944 	pSMB->hdr.Uid = ses->Suid;
4945 	if (ses->capabilities & CAP_STATUS32)
4946 		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4947 	if (ses->capabilities & CAP_DFS)
4948 		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4949 
4950 	if (ses->capabilities & CAP_UNICODE) {
4951 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4952 		name_len =
4953 		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4954 				       search_name, PATH_MAX, nls_codepage,
4955 				       remap);
4956 		name_len++;	/* trailing null */
4957 		name_len *= 2;
4958 	} else {	/* BB improve the check for buffer overruns BB */
4959 		name_len = copy_path_name(pSMB->RequestFileName, search_name);
4960 	}
4961 
4962 	if (ses->server->sign)
4963 		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4964 
4965 	pSMB->hdr.Uid = ses->Suid;
4966 
4967 	params = 2 /* level */  + name_len /*includes null */ ;
4968 	pSMB->TotalDataCount = 0;
4969 	pSMB->DataCount = 0;
4970 	pSMB->DataOffset = 0;
4971 	pSMB->MaxParameterCount = 0;
4972 	/* BB find exact max SMB PDU from sess structure BB */
4973 	pSMB->MaxDataCount = cpu_to_le16(4000);
4974 	pSMB->MaxSetupCount = 0;
4975 	pSMB->Reserved = 0;
4976 	pSMB->Flags = 0;
4977 	pSMB->Timeout = 0;
4978 	pSMB->Reserved2 = 0;
4979 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4980 	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4981 	pSMB->SetupCount = 1;
4982 	pSMB->Reserved3 = 0;
4983 	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4984 	byte_count = params + 3 /* pad */ ;
4985 	pSMB->ParameterCount = cpu_to_le16(params);
4986 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4987 	pSMB->MaxReferralLevel = cpu_to_le16(3);
4988 	inc_rfc1001_len(pSMB, byte_count);
4989 	pSMB->ByteCount = cpu_to_le16(byte_count);
4990 
4991 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4992 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4993 	if (rc) {
4994 		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4995 		goto GetDFSRefExit;
4996 	}
4997 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4998 
4999 	/* BB Also check if enough total bytes returned? */
5000 	if (rc || get_bcc(&pSMBr->hdr) < 17) {
5001 		rc = -EIO;      /* bad smb */
5002 		goto GetDFSRefExit;
5003 	}
5004 
5005 	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
5006 		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
5007 
5008 	/* parse returned result into more usable form */
5009 	rc = parse_dfs_referrals(&pSMBr->dfs_data,
5010 				 le16_to_cpu(pSMBr->t2.DataCount),
5011 				 num_of_nodes, target_nodes, nls_codepage,
5012 				 remap, search_name,
5013 				 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
5014 
5015 GetDFSRefExit:
5016 	cifs_buf_release(pSMB);
5017 
5018 	if (rc == -EAGAIN)
5019 		goto getDFSRetry;
5020 
5021 	return rc;
5022 }
5023 
5024 /* Query File System Info such as free space to old servers such as Win 9x */
5025 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5026 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5027 	      struct kstatfs *FSData)
5028 {
5029 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
5030 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5031 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5032 	FILE_SYSTEM_ALLOC_INFO *response_data;
5033 	int rc = 0;
5034 	int bytes_returned = 0;
5035 	__u16 params, byte_count;
5036 
5037 	cifs_dbg(FYI, "OldQFSInfo\n");
5038 oldQFSInfoRetry:
5039 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5040 		(void **) &pSMBr);
5041 	if (rc)
5042 		return rc;
5043 
5044 	params = 2;     /* level */
5045 	pSMB->TotalDataCount = 0;
5046 	pSMB->MaxParameterCount = cpu_to_le16(2);
5047 	pSMB->MaxDataCount = cpu_to_le16(1000);
5048 	pSMB->MaxSetupCount = 0;
5049 	pSMB->Reserved = 0;
5050 	pSMB->Flags = 0;
5051 	pSMB->Timeout = 0;
5052 	pSMB->Reserved2 = 0;
5053 	byte_count = params + 1 /* pad */ ;
5054 	pSMB->TotalParameterCount = cpu_to_le16(params);
5055 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5056 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5057 	struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5058 	pSMB->DataCount = 0;
5059 	pSMB->DataOffset = 0;
5060 	pSMB->SetupCount = 1;
5061 	pSMB->Reserved3 = 0;
5062 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5063 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
5064 	inc_rfc1001_len(pSMB, byte_count);
5065 	pSMB->ByteCount = cpu_to_le16(byte_count);
5066 
5067 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5068 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
5069 	if (rc) {
5070 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5071 	} else {                /* decode response */
5072 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5073 
5074 		if (rc || get_bcc(&pSMBr->hdr) < 18)
5075 			rc = -EIO;      /* bad smb */
5076 		else {
5077 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5078 			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
5079 				 get_bcc(&pSMBr->hdr), data_offset);
5080 
5081 			response_data = (FILE_SYSTEM_ALLOC_INFO *)
5082 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
5083 			FSData->f_bsize =
5084 				le16_to_cpu(response_data->BytesPerSector) *
5085 				le32_to_cpu(response_data->
5086 					SectorsPerAllocationUnit);
5087 			/*
5088 			 * much prefer larger but if server doesn't report
5089 			 * a valid size than 4K is a reasonable minimum
5090 			 */
5091 			if (FSData->f_bsize < 512)
5092 				FSData->f_bsize = 4096;
5093 
5094 			FSData->f_blocks =
5095 			       le32_to_cpu(response_data->TotalAllocationUnits);
5096 			FSData->f_bfree = FSData->f_bavail =
5097 				le32_to_cpu(response_data->FreeAllocationUnits);
5098 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
5099 				 (unsigned long long)FSData->f_blocks,
5100 				 (unsigned long long)FSData->f_bfree,
5101 				 FSData->f_bsize);
5102 		}
5103 	}
5104 	cifs_buf_release(pSMB);
5105 
5106 	if (rc == -EAGAIN)
5107 		goto oldQFSInfoRetry;
5108 
5109 	return rc;
5110 }
5111 
5112 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5113 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5114 	       struct kstatfs *FSData)
5115 {
5116 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5117 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5118 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5119 	FILE_SYSTEM_INFO *response_data;
5120 	int rc = 0;
5121 	int bytes_returned = 0;
5122 	__u16 params, byte_count;
5123 
5124 	cifs_dbg(FYI, "In QFSInfo\n");
5125 QFSInfoRetry:
5126 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5127 		      (void **) &pSMBr);
5128 	if (rc)
5129 		return rc;
5130 
5131 	params = 2;	/* level */
5132 	pSMB->TotalDataCount = 0;
5133 	pSMB->MaxParameterCount = cpu_to_le16(2);
5134 	pSMB->MaxDataCount = cpu_to_le16(1000);
5135 	pSMB->MaxSetupCount = 0;
5136 	pSMB->Reserved = 0;
5137 	pSMB->Flags = 0;
5138 	pSMB->Timeout = 0;
5139 	pSMB->Reserved2 = 0;
5140 	byte_count = params + 1 /* pad */ ;
5141 	pSMB->TotalParameterCount = cpu_to_le16(params);
5142 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5143 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5144 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5145 	pSMB->DataCount = 0;
5146 	pSMB->DataOffset = 0;
5147 	pSMB->SetupCount = 1;
5148 	pSMB->Reserved3 = 0;
5149 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5150 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5151 	inc_rfc1001_len(pSMB, byte_count);
5152 	pSMB->ByteCount = cpu_to_le16(byte_count);
5153 
5154 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5155 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5156 	if (rc) {
5157 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5158 	} else {		/* decode response */
5159 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5160 
5161 		if (rc || get_bcc(&pSMBr->hdr) < 24)
5162 			rc = -EIO;	/* bad smb */
5163 		else {
5164 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5165 
5166 			response_data =
5167 			    (FILE_SYSTEM_INFO
5168 			     *) (((char *) &pSMBr->hdr.Protocol) +
5169 				 data_offset);
5170 			FSData->f_bsize =
5171 			    le32_to_cpu(response_data->BytesPerSector) *
5172 			    le32_to_cpu(response_data->
5173 					SectorsPerAllocationUnit);
5174 			/*
5175 			 * much prefer larger but if server doesn't report
5176 			 * a valid size than 4K is a reasonable minimum
5177 			 */
5178 			if (FSData->f_bsize < 512)
5179 				FSData->f_bsize = 4096;
5180 
5181 			FSData->f_blocks =
5182 			    le64_to_cpu(response_data->TotalAllocationUnits);
5183 			FSData->f_bfree = FSData->f_bavail =
5184 			    le64_to_cpu(response_data->FreeAllocationUnits);
5185 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
5186 				 (unsigned long long)FSData->f_blocks,
5187 				 (unsigned long long)FSData->f_bfree,
5188 				 FSData->f_bsize);
5189 		}
5190 	}
5191 	cifs_buf_release(pSMB);
5192 
5193 	if (rc == -EAGAIN)
5194 		goto QFSInfoRetry;
5195 
5196 	return rc;
5197 }
5198 
5199 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)5200 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5201 {
5202 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5203 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5204 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5205 	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5206 	int rc = 0;
5207 	int bytes_returned = 0;
5208 	__u16 params, byte_count;
5209 
5210 	cifs_dbg(FYI, "In QFSAttributeInfo\n");
5211 QFSAttributeRetry:
5212 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5213 		      (void **) &pSMBr);
5214 	if (rc)
5215 		return rc;
5216 
5217 	params = 2;	/* level */
5218 	pSMB->TotalDataCount = 0;
5219 	pSMB->MaxParameterCount = cpu_to_le16(2);
5220 	/* BB find exact max SMB PDU from sess structure BB */
5221 	pSMB->MaxDataCount = cpu_to_le16(1000);
5222 	pSMB->MaxSetupCount = 0;
5223 	pSMB->Reserved = 0;
5224 	pSMB->Flags = 0;
5225 	pSMB->Timeout = 0;
5226 	pSMB->Reserved2 = 0;
5227 	byte_count = params + 1 /* pad */ ;
5228 	pSMB->TotalParameterCount = cpu_to_le16(params);
5229 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5230 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5231 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5232 	pSMB->DataCount = 0;
5233 	pSMB->DataOffset = 0;
5234 	pSMB->SetupCount = 1;
5235 	pSMB->Reserved3 = 0;
5236 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5237 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5238 	inc_rfc1001_len(pSMB, byte_count);
5239 	pSMB->ByteCount = cpu_to_le16(byte_count);
5240 
5241 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5242 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5243 	if (rc) {
5244 		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5245 	} else {		/* decode response */
5246 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5247 
5248 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5249 			/* BB also check if enough bytes returned */
5250 			rc = -EIO;	/* bad smb */
5251 		} else {
5252 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5253 			response_data =
5254 			    (FILE_SYSTEM_ATTRIBUTE_INFO
5255 			     *) (((char *) &pSMBr->hdr.Protocol) +
5256 				 data_offset);
5257 			memcpy(&tcon->fsAttrInfo, response_data,
5258 			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5259 		}
5260 	}
5261 	cifs_buf_release(pSMB);
5262 
5263 	if (rc == -EAGAIN)
5264 		goto QFSAttributeRetry;
5265 
5266 	return rc;
5267 }
5268 
5269 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)5270 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5271 {
5272 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5273 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5274 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5275 	FILE_SYSTEM_DEVICE_INFO *response_data;
5276 	int rc = 0;
5277 	int bytes_returned = 0;
5278 	__u16 params, byte_count;
5279 
5280 	cifs_dbg(FYI, "In QFSDeviceInfo\n");
5281 QFSDeviceRetry:
5282 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5283 		      (void **) &pSMBr);
5284 	if (rc)
5285 		return rc;
5286 
5287 	params = 2;	/* level */
5288 	pSMB->TotalDataCount = 0;
5289 	pSMB->MaxParameterCount = cpu_to_le16(2);
5290 	/* BB find exact max SMB PDU from sess structure BB */
5291 	pSMB->MaxDataCount = cpu_to_le16(1000);
5292 	pSMB->MaxSetupCount = 0;
5293 	pSMB->Reserved = 0;
5294 	pSMB->Flags = 0;
5295 	pSMB->Timeout = 0;
5296 	pSMB->Reserved2 = 0;
5297 	byte_count = params + 1 /* pad */ ;
5298 	pSMB->TotalParameterCount = cpu_to_le16(params);
5299 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5300 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5301 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5302 
5303 	pSMB->DataCount = 0;
5304 	pSMB->DataOffset = 0;
5305 	pSMB->SetupCount = 1;
5306 	pSMB->Reserved3 = 0;
5307 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5308 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5309 	inc_rfc1001_len(pSMB, byte_count);
5310 	pSMB->ByteCount = cpu_to_le16(byte_count);
5311 
5312 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5313 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5314 	if (rc) {
5315 		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5316 	} else {		/* decode response */
5317 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5318 
5319 		if (rc || get_bcc(&pSMBr->hdr) <
5320 			  sizeof(FILE_SYSTEM_DEVICE_INFO))
5321 			rc = -EIO;	/* bad smb */
5322 		else {
5323 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5324 			response_data =
5325 			    (FILE_SYSTEM_DEVICE_INFO *)
5326 				(((char *) &pSMBr->hdr.Protocol) +
5327 				 data_offset);
5328 			memcpy(&tcon->fsDevInfo, response_data,
5329 			       sizeof(FILE_SYSTEM_DEVICE_INFO));
5330 		}
5331 	}
5332 	cifs_buf_release(pSMB);
5333 
5334 	if (rc == -EAGAIN)
5335 		goto QFSDeviceRetry;
5336 
5337 	return rc;
5338 }
5339 
5340 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)5341 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5342 {
5343 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5344 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5345 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5346 	FILE_SYSTEM_UNIX_INFO *response_data;
5347 	int rc = 0;
5348 	int bytes_returned = 0;
5349 	__u16 params, byte_count;
5350 
5351 	cifs_dbg(FYI, "In QFSUnixInfo\n");
5352 QFSUnixRetry:
5353 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5354 				   (void **) &pSMB, (void **) &pSMBr);
5355 	if (rc)
5356 		return rc;
5357 
5358 	params = 2;	/* level */
5359 	pSMB->TotalDataCount = 0;
5360 	pSMB->DataCount = 0;
5361 	pSMB->DataOffset = 0;
5362 	pSMB->MaxParameterCount = cpu_to_le16(2);
5363 	/* BB find exact max SMB PDU from sess structure BB */
5364 	pSMB->MaxDataCount = cpu_to_le16(100);
5365 	pSMB->MaxSetupCount = 0;
5366 	pSMB->Reserved = 0;
5367 	pSMB->Flags = 0;
5368 	pSMB->Timeout = 0;
5369 	pSMB->Reserved2 = 0;
5370 	byte_count = params + 1 /* pad */ ;
5371 	pSMB->ParameterCount = cpu_to_le16(params);
5372 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5373 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5374 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5375 	pSMB->SetupCount = 1;
5376 	pSMB->Reserved3 = 0;
5377 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5378 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5379 	inc_rfc1001_len(pSMB, byte_count);
5380 	pSMB->ByteCount = cpu_to_le16(byte_count);
5381 
5382 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5383 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5384 	if (rc) {
5385 		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5386 	} else {		/* decode response */
5387 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5388 
5389 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5390 			rc = -EIO;	/* bad smb */
5391 		} else {
5392 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5393 			response_data =
5394 			    (FILE_SYSTEM_UNIX_INFO
5395 			     *) (((char *) &pSMBr->hdr.Protocol) +
5396 				 data_offset);
5397 			memcpy(&tcon->fsUnixInfo, response_data,
5398 			       sizeof(FILE_SYSTEM_UNIX_INFO));
5399 		}
5400 	}
5401 	cifs_buf_release(pSMB);
5402 
5403 	if (rc == -EAGAIN)
5404 		goto QFSUnixRetry;
5405 
5406 
5407 	return rc;
5408 }
5409 
5410 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)5411 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5412 {
5413 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5414 	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5415 	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5416 	int rc = 0;
5417 	int bytes_returned = 0;
5418 	__u16 params, param_offset, offset, byte_count;
5419 
5420 	cifs_dbg(FYI, "In SETFSUnixInfo\n");
5421 SETFSUnixRetry:
5422 	/* BB switch to small buf init to save memory */
5423 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5424 					(void **) &pSMB, (void **) &pSMBr);
5425 	if (rc)
5426 		return rc;
5427 
5428 	params = 4;	/* 2 bytes zero followed by info level. */
5429 	pSMB->MaxSetupCount = 0;
5430 	pSMB->Reserved = 0;
5431 	pSMB->Flags = 0;
5432 	pSMB->Timeout = 0;
5433 	pSMB->Reserved2 = 0;
5434 	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5435 				- 4;
5436 	offset = param_offset + params;
5437 
5438 	pSMB->MaxParameterCount = cpu_to_le16(4);
5439 	/* BB find exact max SMB PDU from sess structure BB */
5440 	pSMB->MaxDataCount = cpu_to_le16(100);
5441 	pSMB->SetupCount = 1;
5442 	pSMB->Reserved3 = 0;
5443 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5444 	byte_count = 1 /* pad */ + params + 12;
5445 
5446 	pSMB->DataCount = cpu_to_le16(12);
5447 	pSMB->ParameterCount = cpu_to_le16(params);
5448 	pSMB->TotalDataCount = pSMB->DataCount;
5449 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5450 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5451 	pSMB->DataOffset = cpu_to_le16(offset);
5452 
5453 	/* Params. */
5454 	pSMB->FileNum = 0;
5455 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5456 
5457 	/* Data. */
5458 	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5459 	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5460 	pSMB->ClientUnixCap = cpu_to_le64(cap);
5461 
5462 	inc_rfc1001_len(pSMB, byte_count);
5463 	pSMB->ByteCount = cpu_to_le16(byte_count);
5464 
5465 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5466 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5467 	if (rc) {
5468 		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5469 	} else {		/* decode response */
5470 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5471 		if (rc)
5472 			rc = -EIO;	/* bad smb */
5473 	}
5474 	cifs_buf_release(pSMB);
5475 
5476 	if (rc == -EAGAIN)
5477 		goto SETFSUnixRetry;
5478 
5479 	return rc;
5480 }
5481 
5482 
5483 
5484 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5485 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5486 		   struct kstatfs *FSData)
5487 {
5488 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5489 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
5490 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5491 	FILE_SYSTEM_POSIX_INFO *response_data;
5492 	int rc = 0;
5493 	int bytes_returned = 0;
5494 	__u16 params, byte_count;
5495 
5496 	cifs_dbg(FYI, "In QFSPosixInfo\n");
5497 QFSPosixRetry:
5498 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5499 		      (void **) &pSMBr);
5500 	if (rc)
5501 		return rc;
5502 
5503 	params = 2;	/* level */
5504 	pSMB->TotalDataCount = 0;
5505 	pSMB->DataCount = 0;
5506 	pSMB->DataOffset = 0;
5507 	pSMB->MaxParameterCount = cpu_to_le16(2);
5508 	/* BB find exact max SMB PDU from sess structure BB */
5509 	pSMB->MaxDataCount = cpu_to_le16(100);
5510 	pSMB->MaxSetupCount = 0;
5511 	pSMB->Reserved = 0;
5512 	pSMB->Flags = 0;
5513 	pSMB->Timeout = 0;
5514 	pSMB->Reserved2 = 0;
5515 	byte_count = params + 1 /* pad */ ;
5516 	pSMB->ParameterCount = cpu_to_le16(params);
5517 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5518 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5519 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5520 	pSMB->SetupCount = 1;
5521 	pSMB->Reserved3 = 0;
5522 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5523 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5524 	inc_rfc1001_len(pSMB, byte_count);
5525 	pSMB->ByteCount = cpu_to_le16(byte_count);
5526 
5527 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5528 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5529 	if (rc) {
5530 		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5531 	} else {		/* decode response */
5532 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5533 
5534 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
5535 			rc = -EIO;	/* bad smb */
5536 		} else {
5537 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5538 			response_data =
5539 			    (FILE_SYSTEM_POSIX_INFO
5540 			     *) (((char *) &pSMBr->hdr.Protocol) +
5541 				 data_offset);
5542 			FSData->f_bsize =
5543 					le32_to_cpu(response_data->BlockSize);
5544 			/*
5545 			 * much prefer larger but if server doesn't report
5546 			 * a valid size than 4K is a reasonable minimum
5547 			 */
5548 			if (FSData->f_bsize < 512)
5549 				FSData->f_bsize = 4096;
5550 
5551 			FSData->f_blocks =
5552 					le64_to_cpu(response_data->TotalBlocks);
5553 			FSData->f_bfree =
5554 			    le64_to_cpu(response_data->BlocksAvail);
5555 			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5556 				FSData->f_bavail = FSData->f_bfree;
5557 			} else {
5558 				FSData->f_bavail =
5559 				    le64_to_cpu(response_data->UserBlocksAvail);
5560 			}
5561 			if (response_data->TotalFileNodes != cpu_to_le64(-1))
5562 				FSData->f_files =
5563 				     le64_to_cpu(response_data->TotalFileNodes);
5564 			if (response_data->FreeFileNodes != cpu_to_le64(-1))
5565 				FSData->f_ffree =
5566 				      le64_to_cpu(response_data->FreeFileNodes);
5567 		}
5568 	}
5569 	cifs_buf_release(pSMB);
5570 
5571 	if (rc == -EAGAIN)
5572 		goto QFSPosixRetry;
5573 
5574 	return rc;
5575 }
5576 
5577 
5578 /*
5579  * We can not use write of zero bytes trick to set file size due to need for
5580  * large file support. Also note that this SetPathInfo is preferred to
5581  * SetFileInfo based method in next routine which is only needed to work around
5582  * a sharing violation bugin Samba which this routine can run into.
5583  */
5584 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)5585 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5586 	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5587 	      bool set_allocation)
5588 {
5589 	struct smb_com_transaction2_spi_req *pSMB = NULL;
5590 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5591 	struct file_end_of_file_info *parm_data;
5592 	int name_len;
5593 	int rc = 0;
5594 	int bytes_returned = 0;
5595 	int remap = cifs_remap(cifs_sb);
5596 
5597 	__u16 params, byte_count, data_count, param_offset, offset;
5598 
5599 	cifs_dbg(FYI, "In SetEOF\n");
5600 SetEOFRetry:
5601 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5602 		      (void **) &pSMBr);
5603 	if (rc)
5604 		return rc;
5605 
5606 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5607 		name_len =
5608 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5609 				       PATH_MAX, cifs_sb->local_nls, remap);
5610 		name_len++;	/* trailing null */
5611 		name_len *= 2;
5612 	} else {
5613 		name_len = copy_path_name(pSMB->FileName, file_name);
5614 	}
5615 	params = 6 + name_len;
5616 	data_count = sizeof(struct file_end_of_file_info);
5617 	pSMB->MaxParameterCount = cpu_to_le16(2);
5618 	pSMB->MaxDataCount = cpu_to_le16(4100);
5619 	pSMB->MaxSetupCount = 0;
5620 	pSMB->Reserved = 0;
5621 	pSMB->Flags = 0;
5622 	pSMB->Timeout = 0;
5623 	pSMB->Reserved2 = 0;
5624 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5625 				InformationLevel) - 4;
5626 	offset = param_offset + params;
5627 	if (set_allocation) {
5628 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5629 			pSMB->InformationLevel =
5630 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5631 		else
5632 			pSMB->InformationLevel =
5633 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5634 	} else /* Set File Size */  {
5635 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5636 		    pSMB->InformationLevel =
5637 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5638 	    else
5639 		    pSMB->InformationLevel =
5640 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5641 	}
5642 
5643 	parm_data =
5644 	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5645 				       offset);
5646 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5647 	pSMB->DataOffset = cpu_to_le16(offset);
5648 	pSMB->SetupCount = 1;
5649 	pSMB->Reserved3 = 0;
5650 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5651 	byte_count = 3 /* pad */  + params + data_count;
5652 	pSMB->DataCount = cpu_to_le16(data_count);
5653 	pSMB->TotalDataCount = pSMB->DataCount;
5654 	pSMB->ParameterCount = cpu_to_le16(params);
5655 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5656 	pSMB->Reserved4 = 0;
5657 	inc_rfc1001_len(pSMB, byte_count);
5658 	parm_data->FileSize = cpu_to_le64(size);
5659 	pSMB->ByteCount = cpu_to_le16(byte_count);
5660 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5661 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5662 	if (rc)
5663 		cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5664 
5665 	cifs_buf_release(pSMB);
5666 
5667 	if (rc == -EAGAIN)
5668 		goto SetEOFRetry;
5669 
5670 	return rc;
5671 }
5672 
5673 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5674 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5675 		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5676 {
5677 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5678 	struct file_end_of_file_info *parm_data;
5679 	int rc = 0;
5680 	__u16 params, param_offset, offset, byte_count, count;
5681 
5682 	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5683 		 (long long)size);
5684 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5685 
5686 	if (rc)
5687 		return rc;
5688 
5689 	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5690 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5691 
5692 	params = 6;
5693 	pSMB->MaxSetupCount = 0;
5694 	pSMB->Reserved = 0;
5695 	pSMB->Flags = 0;
5696 	pSMB->Timeout = 0;
5697 	pSMB->Reserved2 = 0;
5698 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5699 	offset = param_offset + params;
5700 
5701 	count = sizeof(struct file_end_of_file_info);
5702 	pSMB->MaxParameterCount = cpu_to_le16(2);
5703 	/* BB find exact max SMB PDU from sess structure BB */
5704 	pSMB->MaxDataCount = cpu_to_le16(1000);
5705 	pSMB->SetupCount = 1;
5706 	pSMB->Reserved3 = 0;
5707 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5708 	byte_count = 3 /* pad */  + params + count;
5709 	pSMB->DataCount = cpu_to_le16(count);
5710 	pSMB->ParameterCount = cpu_to_le16(params);
5711 	pSMB->TotalDataCount = pSMB->DataCount;
5712 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5713 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5714 	parm_data =
5715 		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5716 				+ offset);
5717 	pSMB->DataOffset = cpu_to_le16(offset);
5718 	parm_data->FileSize = cpu_to_le64(size);
5719 	pSMB->Fid = cfile->fid.netfid;
5720 	if (set_allocation) {
5721 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5722 			pSMB->InformationLevel =
5723 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5724 		else
5725 			pSMB->InformationLevel =
5726 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5727 	} else /* Set File Size */  {
5728 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5729 		    pSMB->InformationLevel =
5730 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5731 	    else
5732 		    pSMB->InformationLevel =
5733 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5734 	}
5735 	pSMB->Reserved4 = 0;
5736 	inc_rfc1001_len(pSMB, byte_count);
5737 	pSMB->ByteCount = cpu_to_le16(byte_count);
5738 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5739 	cifs_small_buf_release(pSMB);
5740 	if (rc) {
5741 		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5742 			 rc);
5743 	}
5744 
5745 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5746 		since file handle passed in no longer valid */
5747 
5748 	return rc;
5749 }
5750 
5751 /* Some legacy servers such as NT4 require that the file times be set on
5752    an open handle, rather than by pathname - this is awkward due to
5753    potential access conflicts on the open, but it is unavoidable for these
5754    old servers since the only other choice is to go from 100 nanosecond DCE
5755    time and resort to the original setpathinfo level which takes the ancient
5756    DOS time format with 2 second granularity */
5757 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5758 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5759 		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5760 {
5761 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5762 	char *data_offset;
5763 	int rc = 0;
5764 	__u16 params, param_offset, offset, byte_count, count;
5765 
5766 	cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5767 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5768 
5769 	if (rc)
5770 		return rc;
5771 
5772 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5773 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5774 
5775 	params = 6;
5776 	pSMB->MaxSetupCount = 0;
5777 	pSMB->Reserved = 0;
5778 	pSMB->Flags = 0;
5779 	pSMB->Timeout = 0;
5780 	pSMB->Reserved2 = 0;
5781 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5782 	offset = param_offset + params;
5783 
5784 	data_offset = (char *)pSMB +
5785 			offsetof(struct smb_hdr, Protocol) + offset;
5786 
5787 	count = sizeof(FILE_BASIC_INFO);
5788 	pSMB->MaxParameterCount = cpu_to_le16(2);
5789 	/* BB find max SMB PDU from sess */
5790 	pSMB->MaxDataCount = cpu_to_le16(1000);
5791 	pSMB->SetupCount = 1;
5792 	pSMB->Reserved3 = 0;
5793 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5794 	byte_count = 3 /* pad */  + params + count;
5795 	pSMB->DataCount = cpu_to_le16(count);
5796 	pSMB->ParameterCount = cpu_to_le16(params);
5797 	pSMB->TotalDataCount = pSMB->DataCount;
5798 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5799 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5800 	pSMB->DataOffset = cpu_to_le16(offset);
5801 	pSMB->Fid = fid;
5802 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5803 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5804 	else
5805 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5806 	pSMB->Reserved4 = 0;
5807 	inc_rfc1001_len(pSMB, byte_count);
5808 	pSMB->ByteCount = cpu_to_le16(byte_count);
5809 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5810 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5811 	cifs_small_buf_release(pSMB);
5812 	if (rc)
5813 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5814 			 rc);
5815 
5816 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5817 		since file handle passed in no longer valid */
5818 
5819 	return rc;
5820 }
5821 
5822 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5823 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5824 			  bool delete_file, __u16 fid, __u32 pid_of_opener)
5825 {
5826 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5827 	char *data_offset;
5828 	int rc = 0;
5829 	__u16 params, param_offset, offset, byte_count, count;
5830 
5831 	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5832 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5833 
5834 	if (rc)
5835 		return rc;
5836 
5837 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5838 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5839 
5840 	params = 6;
5841 	pSMB->MaxSetupCount = 0;
5842 	pSMB->Reserved = 0;
5843 	pSMB->Flags = 0;
5844 	pSMB->Timeout = 0;
5845 	pSMB->Reserved2 = 0;
5846 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5847 	offset = param_offset + params;
5848 
5849 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5850 
5851 	count = 1;
5852 	pSMB->MaxParameterCount = cpu_to_le16(2);
5853 	/* BB find max SMB PDU from sess */
5854 	pSMB->MaxDataCount = cpu_to_le16(1000);
5855 	pSMB->SetupCount = 1;
5856 	pSMB->Reserved3 = 0;
5857 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5858 	byte_count = 3 /* pad */  + params + count;
5859 	pSMB->DataCount = cpu_to_le16(count);
5860 	pSMB->ParameterCount = cpu_to_le16(params);
5861 	pSMB->TotalDataCount = pSMB->DataCount;
5862 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5863 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5864 	pSMB->DataOffset = cpu_to_le16(offset);
5865 	pSMB->Fid = fid;
5866 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5867 	pSMB->Reserved4 = 0;
5868 	inc_rfc1001_len(pSMB, byte_count);
5869 	pSMB->ByteCount = cpu_to_le16(byte_count);
5870 	*data_offset = delete_file ? 1 : 0;
5871 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5872 	cifs_small_buf_release(pSMB);
5873 	if (rc)
5874 		cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5875 
5876 	return rc;
5877 }
5878 
5879 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)5880 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5881 		   const char *fileName, const FILE_BASIC_INFO *data,
5882 		   const struct nls_table *nls_codepage, int remap)
5883 {
5884 	TRANSACTION2_SPI_REQ *pSMB = NULL;
5885 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5886 	int name_len;
5887 	int rc = 0;
5888 	int bytes_returned = 0;
5889 	char *data_offset;
5890 	__u16 params, param_offset, offset, byte_count, count;
5891 
5892 	cifs_dbg(FYI, "In SetTimes\n");
5893 
5894 SetTimesRetry:
5895 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5896 		      (void **) &pSMBr);
5897 	if (rc)
5898 		return rc;
5899 
5900 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5901 		name_len =
5902 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5903 				       PATH_MAX, nls_codepage, remap);
5904 		name_len++;	/* trailing null */
5905 		name_len *= 2;
5906 	} else {
5907 		name_len = copy_path_name(pSMB->FileName, fileName);
5908 	}
5909 
5910 	params = 6 + name_len;
5911 	count = sizeof(FILE_BASIC_INFO);
5912 	pSMB->MaxParameterCount = cpu_to_le16(2);
5913 	/* BB find max SMB PDU from sess structure BB */
5914 	pSMB->MaxDataCount = cpu_to_le16(1000);
5915 	pSMB->MaxSetupCount = 0;
5916 	pSMB->Reserved = 0;
5917 	pSMB->Flags = 0;
5918 	pSMB->Timeout = 0;
5919 	pSMB->Reserved2 = 0;
5920 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5921 				InformationLevel) - 4;
5922 	offset = param_offset + params;
5923 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5924 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5925 	pSMB->DataOffset = cpu_to_le16(offset);
5926 	pSMB->SetupCount = 1;
5927 	pSMB->Reserved3 = 0;
5928 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5929 	byte_count = 3 /* pad */  + params + count;
5930 
5931 	pSMB->DataCount = cpu_to_le16(count);
5932 	pSMB->ParameterCount = cpu_to_le16(params);
5933 	pSMB->TotalDataCount = pSMB->DataCount;
5934 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5935 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5936 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5937 	else
5938 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5939 	pSMB->Reserved4 = 0;
5940 	inc_rfc1001_len(pSMB, byte_count);
5941 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5942 	pSMB->ByteCount = cpu_to_le16(byte_count);
5943 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5944 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5945 	if (rc)
5946 		cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5947 
5948 	cifs_buf_release(pSMB);
5949 
5950 	if (rc == -EAGAIN)
5951 		goto SetTimesRetry;
5952 
5953 	return rc;
5954 }
5955 
5956 /* Can not be used to set time stamps yet (due to old DOS time format) */
5957 /* Can be used to set attributes */
5958 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5959 	  handling it anyway and NT4 was what we thought it would be needed for
5960 	  Do not delete it until we prove whether needed for Win9x though */
5961 int
5962 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5963 		__u16 dos_attrs, const struct nls_table *nls_codepage)
5964 {
5965 	SETATTR_REQ *pSMB = NULL;
5966 	SETATTR_RSP *pSMBr = NULL;
5967 	int rc = 0;
5968 	int bytes_returned;
5969 	int name_len;
5970 
5971 	cifs_dbg(FYI, "In SetAttrLegacy\n");
5972 
5973 SetAttrLgcyRetry:
5974 	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5975 		      (void **) &pSMBr);
5976 	if (rc)
5977 		return rc;
5978 
5979 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5980 		name_len =
5981 			ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5982 				       PATH_MAX, nls_codepage);
5983 		name_len++;     /* trailing null */
5984 		name_len *= 2;
5985 	} else {
5986 		name_len = copy_path_name(pSMB->fileName, fileName);
5987 	}
5988 	pSMB->attr = cpu_to_le16(dos_attrs);
5989 	pSMB->BufferFormat = 0x04;
5990 	inc_rfc1001_len(pSMB, name_len + 1);
5991 	pSMB->ByteCount = cpu_to_le16(name_len + 1);
5992 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5993 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5994 	if (rc)
5995 		cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5996 
5997 	cifs_buf_release(pSMB);
5998 
5999 	if (rc == -EAGAIN)
6000 		goto SetAttrLgcyRetry;
6001 
6002 	return rc;
6003 }
6004 #endif /* temporarily unneeded SetAttr legacy function */
6005 
6006 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)6007 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
6008 			const struct cifs_unix_set_info_args *args)
6009 {
6010 	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
6011 	u64 mode = args->mode;
6012 
6013 	if (uid_valid(args->uid))
6014 		uid = from_kuid(&init_user_ns, args->uid);
6015 	if (gid_valid(args->gid))
6016 		gid = from_kgid(&init_user_ns, args->gid);
6017 
6018 	/*
6019 	 * Samba server ignores set of file size to zero due to bugs in some
6020 	 * older clients, but we should be precise - we use SetFileSize to
6021 	 * set file size and do not want to truncate file size to zero
6022 	 * accidentally as happened on one Samba server beta by putting
6023 	 * zero instead of -1 here
6024 	 */
6025 	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
6026 	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
6027 	data_offset->LastStatusChange = cpu_to_le64(args->ctime);
6028 	data_offset->LastAccessTime = cpu_to_le64(args->atime);
6029 	data_offset->LastModificationTime = cpu_to_le64(args->mtime);
6030 	data_offset->Uid = cpu_to_le64(uid);
6031 	data_offset->Gid = cpu_to_le64(gid);
6032 	/* better to leave device as zero when it is  */
6033 	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
6034 	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
6035 	data_offset->Permissions = cpu_to_le64(mode);
6036 
6037 	if (S_ISREG(mode))
6038 		data_offset->Type = cpu_to_le32(UNIX_FILE);
6039 	else if (S_ISDIR(mode))
6040 		data_offset->Type = cpu_to_le32(UNIX_DIR);
6041 	else if (S_ISLNK(mode))
6042 		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
6043 	else if (S_ISCHR(mode))
6044 		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
6045 	else if (S_ISBLK(mode))
6046 		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
6047 	else if (S_ISFIFO(mode))
6048 		data_offset->Type = cpu_to_le32(UNIX_FIFO);
6049 	else if (S_ISSOCK(mode))
6050 		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
6051 }
6052 
6053 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)6054 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
6055 		       const struct cifs_unix_set_info_args *args,
6056 		       u16 fid, u32 pid_of_opener)
6057 {
6058 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
6059 	char *data_offset;
6060 	int rc = 0;
6061 	u16 params, param_offset, offset, byte_count, count;
6062 
6063 	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
6064 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
6065 
6066 	if (rc)
6067 		return rc;
6068 
6069 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
6070 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
6071 
6072 	params = 6;
6073 	pSMB->MaxSetupCount = 0;
6074 	pSMB->Reserved = 0;
6075 	pSMB->Flags = 0;
6076 	pSMB->Timeout = 0;
6077 	pSMB->Reserved2 = 0;
6078 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6079 	offset = param_offset + params;
6080 
6081 	data_offset = (char *)pSMB +
6082 			offsetof(struct smb_hdr, Protocol) + offset;
6083 
6084 	count = sizeof(FILE_UNIX_BASIC_INFO);
6085 
6086 	pSMB->MaxParameterCount = cpu_to_le16(2);
6087 	/* BB find max SMB PDU from sess */
6088 	pSMB->MaxDataCount = cpu_to_le16(1000);
6089 	pSMB->SetupCount = 1;
6090 	pSMB->Reserved3 = 0;
6091 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6092 	byte_count = 3 /* pad */  + params + count;
6093 	pSMB->DataCount = cpu_to_le16(count);
6094 	pSMB->ParameterCount = cpu_to_le16(params);
6095 	pSMB->TotalDataCount = pSMB->DataCount;
6096 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6097 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6098 	pSMB->DataOffset = cpu_to_le16(offset);
6099 	pSMB->Fid = fid;
6100 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6101 	pSMB->Reserved4 = 0;
6102 	inc_rfc1001_len(pSMB, byte_count);
6103 	pSMB->ByteCount = cpu_to_le16(byte_count);
6104 
6105 	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6106 
6107 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6108 	cifs_small_buf_release(pSMB);
6109 	if (rc)
6110 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6111 			 rc);
6112 
6113 	/* Note: On -EAGAIN error only caller can retry on handle based calls
6114 		since file handle passed in no longer valid */
6115 
6116 	return rc;
6117 }
6118 
6119 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)6120 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6121 		       const char *file_name,
6122 		       const struct cifs_unix_set_info_args *args,
6123 		       const struct nls_table *nls_codepage, int remap)
6124 {
6125 	TRANSACTION2_SPI_REQ *pSMB = NULL;
6126 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
6127 	int name_len;
6128 	int rc = 0;
6129 	int bytes_returned = 0;
6130 	FILE_UNIX_BASIC_INFO *data_offset;
6131 	__u16 params, param_offset, offset, count, byte_count;
6132 
6133 	cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6134 setPermsRetry:
6135 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6136 		      (void **) &pSMBr);
6137 	if (rc)
6138 		return rc;
6139 
6140 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6141 		name_len =
6142 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6143 				       PATH_MAX, nls_codepage, remap);
6144 		name_len++;	/* trailing null */
6145 		name_len *= 2;
6146 	} else {
6147 		name_len = copy_path_name(pSMB->FileName, file_name);
6148 	}
6149 
6150 	params = 6 + name_len;
6151 	count = sizeof(FILE_UNIX_BASIC_INFO);
6152 	pSMB->MaxParameterCount = cpu_to_le16(2);
6153 	/* BB find max SMB PDU from sess structure BB */
6154 	pSMB->MaxDataCount = cpu_to_le16(1000);
6155 	pSMB->MaxSetupCount = 0;
6156 	pSMB->Reserved = 0;
6157 	pSMB->Flags = 0;
6158 	pSMB->Timeout = 0;
6159 	pSMB->Reserved2 = 0;
6160 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6161 				InformationLevel) - 4;
6162 	offset = param_offset + params;
6163 	data_offset =
6164 	    (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6165 				      offset);
6166 	memset(data_offset, 0, count);
6167 	pSMB->DataOffset = cpu_to_le16(offset);
6168 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6169 	pSMB->SetupCount = 1;
6170 	pSMB->Reserved3 = 0;
6171 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6172 	byte_count = 3 /* pad */  + params + count;
6173 	pSMB->ParameterCount = cpu_to_le16(params);
6174 	pSMB->DataCount = cpu_to_le16(count);
6175 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6176 	pSMB->TotalDataCount = pSMB->DataCount;
6177 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6178 	pSMB->Reserved4 = 0;
6179 	inc_rfc1001_len(pSMB, byte_count);
6180 
6181 	cifs_fill_unix_set_info(data_offset, args);
6182 
6183 	pSMB->ByteCount = cpu_to_le16(byte_count);
6184 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6185 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6186 	if (rc)
6187 		cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6188 
6189 	cifs_buf_release(pSMB);
6190 	if (rc == -EAGAIN)
6191 		goto setPermsRetry;
6192 	return rc;
6193 }
6194 
6195 #ifdef CONFIG_CIFS_XATTR
6196 /*
6197  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6198  * function used by listxattr and getxattr type calls. When ea_name is set,
6199  * it looks for that attribute name and stuffs that value into the EAData
6200  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6201  * buffer. In both cases, the return value is either the length of the
6202  * resulting data or a negative error code. If EAData is a NULL pointer then
6203  * the data isn't copied to it, but the length is returned.
6204  */
6205 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)6206 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6207 		const unsigned char *searchName, const unsigned char *ea_name,
6208 		char *EAData, size_t buf_size,
6209 		struct cifs_sb_info *cifs_sb)
6210 {
6211 		/* BB assumes one setup word */
6212 	TRANSACTION2_QPI_REQ *pSMB = NULL;
6213 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
6214 	int remap = cifs_remap(cifs_sb);
6215 	struct nls_table *nls_codepage = cifs_sb->local_nls;
6216 	int rc = 0;
6217 	int bytes_returned;
6218 	int list_len;
6219 	struct fealist *ea_response_data;
6220 	struct fea *temp_fea;
6221 	char *temp_ptr;
6222 	char *end_of_smb;
6223 	__u16 params, byte_count, data_offset;
6224 	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6225 
6226 	cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6227 QAllEAsRetry:
6228 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6229 		      (void **) &pSMBr);
6230 	if (rc)
6231 		return rc;
6232 
6233 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6234 		list_len =
6235 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6236 				       PATH_MAX, nls_codepage, remap);
6237 		list_len++;	/* trailing null */
6238 		list_len *= 2;
6239 	} else {
6240 		list_len = copy_path_name(pSMB->FileName, searchName);
6241 	}
6242 
6243 	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6244 	pSMB->TotalDataCount = 0;
6245 	pSMB->MaxParameterCount = cpu_to_le16(2);
6246 	/* BB find exact max SMB PDU from sess structure BB */
6247 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6248 	pSMB->MaxSetupCount = 0;
6249 	pSMB->Reserved = 0;
6250 	pSMB->Flags = 0;
6251 	pSMB->Timeout = 0;
6252 	pSMB->Reserved2 = 0;
6253 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
6254 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6255 	pSMB->DataCount = 0;
6256 	pSMB->DataOffset = 0;
6257 	pSMB->SetupCount = 1;
6258 	pSMB->Reserved3 = 0;
6259 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6260 	byte_count = params + 1 /* pad */ ;
6261 	pSMB->TotalParameterCount = cpu_to_le16(params);
6262 	pSMB->ParameterCount = pSMB->TotalParameterCount;
6263 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6264 	pSMB->Reserved4 = 0;
6265 	inc_rfc1001_len(pSMB, byte_count);
6266 	pSMB->ByteCount = cpu_to_le16(byte_count);
6267 
6268 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6269 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6270 	if (rc) {
6271 		cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6272 		goto QAllEAsOut;
6273 	}
6274 
6275 
6276 	/* BB also check enough total bytes returned */
6277 	/* BB we need to improve the validity checking
6278 	of these trans2 responses */
6279 
6280 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6281 	if (rc || get_bcc(&pSMBr->hdr) < 4) {
6282 		rc = -EIO;	/* bad smb */
6283 		goto QAllEAsOut;
6284 	}
6285 
6286 	/* check that length of list is not more than bcc */
6287 	/* check that each entry does not go beyond length
6288 	   of list */
6289 	/* check that each element of each entry does not
6290 	   go beyond end of list */
6291 	/* validate_trans2_offsets() */
6292 	/* BB check if start of smb + data_offset > &bcc+ bcc */
6293 
6294 	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6295 	ea_response_data = (struct fealist *)
6296 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
6297 
6298 	list_len = le32_to_cpu(ea_response_data->list_len);
6299 	cifs_dbg(FYI, "ea length %d\n", list_len);
6300 	if (list_len <= 8) {
6301 		cifs_dbg(FYI, "empty EA list returned from server\n");
6302 		/* didn't find the named attribute */
6303 		if (ea_name)
6304 			rc = -ENODATA;
6305 		goto QAllEAsOut;
6306 	}
6307 
6308 	/* make sure list_len doesn't go past end of SMB */
6309 	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6310 	if ((char *)ea_response_data + list_len > end_of_smb) {
6311 		cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6312 		rc = -EIO;
6313 		goto QAllEAsOut;
6314 	}
6315 
6316 	/* account for ea list len */
6317 	list_len -= 4;
6318 	temp_fea = ea_response_data->list;
6319 	temp_ptr = (char *)temp_fea;
6320 	while (list_len > 0) {
6321 		unsigned int name_len;
6322 		__u16 value_len;
6323 
6324 		list_len -= 4;
6325 		temp_ptr += 4;
6326 		/* make sure we can read name_len and value_len */
6327 		if (list_len < 0) {
6328 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6329 			rc = -EIO;
6330 			goto QAllEAsOut;
6331 		}
6332 
6333 		name_len = temp_fea->name_len;
6334 		value_len = le16_to_cpu(temp_fea->value_len);
6335 		list_len -= name_len + 1 + value_len;
6336 		if (list_len < 0) {
6337 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6338 			rc = -EIO;
6339 			goto QAllEAsOut;
6340 		}
6341 
6342 		if (ea_name) {
6343 			if (ea_name_len == name_len &&
6344 			    memcmp(ea_name, temp_ptr, name_len) == 0) {
6345 				temp_ptr += name_len + 1;
6346 				rc = value_len;
6347 				if (buf_size == 0)
6348 					goto QAllEAsOut;
6349 				if ((size_t)value_len > buf_size) {
6350 					rc = -ERANGE;
6351 					goto QAllEAsOut;
6352 				}
6353 				memcpy(EAData, temp_ptr, value_len);
6354 				goto QAllEAsOut;
6355 			}
6356 		} else {
6357 			/* account for prefix user. and trailing null */
6358 			rc += (5 + 1 + name_len);
6359 			if (rc < (int) buf_size) {
6360 				memcpy(EAData, "user.", 5);
6361 				EAData += 5;
6362 				memcpy(EAData, temp_ptr, name_len);
6363 				EAData += name_len;
6364 				/* null terminate name */
6365 				*EAData = 0;
6366 				++EAData;
6367 			} else if (buf_size == 0) {
6368 				/* skip copy - calc size only */
6369 			} else {
6370 				/* stop before overrun buffer */
6371 				rc = -ERANGE;
6372 				break;
6373 			}
6374 		}
6375 		temp_ptr += name_len + 1 + value_len;
6376 		temp_fea = (struct fea *)temp_ptr;
6377 	}
6378 
6379 	/* didn't find the named attribute */
6380 	if (ea_name)
6381 		rc = -ENODATA;
6382 
6383 QAllEAsOut:
6384 	cifs_buf_release(pSMB);
6385 	if (rc == -EAGAIN)
6386 		goto QAllEAsRetry;
6387 
6388 	return (ssize_t)rc;
6389 }
6390 
6391 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)6392 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6393 	     const char *fileName, const char *ea_name, const void *ea_value,
6394 	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
6395 	     struct cifs_sb_info *cifs_sb)
6396 {
6397 	struct smb_com_transaction2_spi_req *pSMB = NULL;
6398 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6399 	struct fealist *parm_data;
6400 	int name_len;
6401 	int rc = 0;
6402 	int bytes_returned = 0;
6403 	__u16 params, param_offset, byte_count, offset, count;
6404 	int remap = cifs_remap(cifs_sb);
6405 
6406 	cifs_dbg(FYI, "In SetEA\n");
6407 SetEARetry:
6408 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6409 		      (void **) &pSMBr);
6410 	if (rc)
6411 		return rc;
6412 
6413 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6414 		name_len =
6415 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6416 				       PATH_MAX, nls_codepage, remap);
6417 		name_len++;	/* trailing null */
6418 		name_len *= 2;
6419 	} else {
6420 		name_len = copy_path_name(pSMB->FileName, fileName);
6421 	}
6422 
6423 	params = 6 + name_len;
6424 
6425 	/* done calculating parms using name_len of file name,
6426 	now use name_len to calculate length of ea name
6427 	we are going to create in the inode xattrs */
6428 	if (ea_name == NULL)
6429 		name_len = 0;
6430 	else
6431 		name_len = strnlen(ea_name, 255);
6432 
6433 	count = sizeof(*parm_data) + ea_value_len + name_len;
6434 	pSMB->MaxParameterCount = cpu_to_le16(2);
6435 	/* BB find max SMB PDU from sess */
6436 	pSMB->MaxDataCount = cpu_to_le16(1000);
6437 	pSMB->MaxSetupCount = 0;
6438 	pSMB->Reserved = 0;
6439 	pSMB->Flags = 0;
6440 	pSMB->Timeout = 0;
6441 	pSMB->Reserved2 = 0;
6442 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
6443 				InformationLevel) - 4;
6444 	offset = param_offset + params;
6445 	pSMB->InformationLevel =
6446 		cpu_to_le16(SMB_SET_FILE_EA);
6447 
6448 	parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6449 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
6450 	pSMB->DataOffset = cpu_to_le16(offset);
6451 	pSMB->SetupCount = 1;
6452 	pSMB->Reserved3 = 0;
6453 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6454 	byte_count = 3 /* pad */  + params + count;
6455 	pSMB->DataCount = cpu_to_le16(count);
6456 	parm_data->list_len = cpu_to_le32(count);
6457 	parm_data->list[0].EA_flags = 0;
6458 	/* we checked above that name len is less than 255 */
6459 	parm_data->list[0].name_len = (__u8)name_len;
6460 	/* EA names are always ASCII */
6461 	if (ea_name)
6462 		strncpy(parm_data->list[0].name, ea_name, name_len);
6463 	parm_data->list[0].name[name_len] = 0;
6464 	parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6465 	/* caller ensures that ea_value_len is less than 64K but
6466 	we need to ensure that it fits within the smb */
6467 
6468 	/*BB add length check to see if it would fit in
6469 	     negotiated SMB buffer size BB */
6470 	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
6471 	if (ea_value_len)
6472 		memcpy(parm_data->list[0].name+name_len+1,
6473 		       ea_value, ea_value_len);
6474 
6475 	pSMB->TotalDataCount = pSMB->DataCount;
6476 	pSMB->ParameterCount = cpu_to_le16(params);
6477 	pSMB->TotalParameterCount = pSMB->ParameterCount;
6478 	pSMB->Reserved4 = 0;
6479 	inc_rfc1001_len(pSMB, byte_count);
6480 	pSMB->ByteCount = cpu_to_le16(byte_count);
6481 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6482 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6483 	if (rc)
6484 		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6485 
6486 	cifs_buf_release(pSMB);
6487 
6488 	if (rc == -EAGAIN)
6489 		goto SetEARetry;
6490 
6491 	return rc;
6492 }
6493 #endif
6494