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