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