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