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