xref: /openbmc/linux/fs/smb/client/cifssmb.c (revision f93d145f)
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(2);
2742 	/* BB find exact data count max from sess structure BB */
2743 	io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
2744 	io_req->MaxSetupCount = 4;
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 	end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
2772 	start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
2773 	if (start >= end) {
2774 		rc = -EIO;
2775 		goto error;
2776 	}
2777 
2778 	data_count = le16_to_cpu(io_rsp->ByteCount);
2779 	buf = (struct reparse_data_buffer *)start;
2780 	len = sizeof(*buf);
2781 	if (data_count < len ||
2782 	    data_count < le16_to_cpu(buf->ReparseDataLength) + len) {
2783 		rc = -EIO;
2784 		goto error;
2785 	}
2786 
2787 	*tag = le32_to_cpu(buf->ReparseTag);
2788 	rsp->iov_base = io_rsp;
2789 	rsp->iov_len = io_rsp_len;
2790 	*rsp_buftype = CIFS_LARGE_BUFFER;
2791 	CIFSSMBClose(xid, tcon, fid.netfid);
2792 	return 0;
2793 
2794 error:
2795 	cifs_buf_release(io_req);
2796 	CIFSSMBClose(xid, tcon, fid.netfid);
2797 	return rc;
2798 }
2799 
2800 int
CIFSSMB_set_compression(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid)2801 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
2802 		    __u16 fid)
2803 {
2804 	int rc = 0;
2805 	int bytes_returned;
2806 	struct smb_com_transaction_compr_ioctl_req *pSMB;
2807 	struct smb_com_transaction_ioctl_rsp *pSMBr;
2808 
2809 	cifs_dbg(FYI, "Set compression for %u\n", fid);
2810 	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2811 		      (void **) &pSMBr);
2812 	if (rc)
2813 		return rc;
2814 
2815 	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
2816 
2817 	pSMB->TotalParameterCount = 0;
2818 	pSMB->TotalDataCount = cpu_to_le32(2);
2819 	pSMB->MaxParameterCount = 0;
2820 	pSMB->MaxDataCount = 0;
2821 	pSMB->MaxSetupCount = 4;
2822 	pSMB->Reserved = 0;
2823 	pSMB->ParameterOffset = 0;
2824 	pSMB->DataCount = cpu_to_le32(2);
2825 	pSMB->DataOffset =
2826 		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
2827 				compression_state) - 4);  /* 84 */
2828 	pSMB->SetupCount = 4;
2829 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2830 	pSMB->ParameterCount = 0;
2831 	pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
2832 	pSMB->IsFsctl = 1; /* FSCTL */
2833 	pSMB->IsRootFlag = 0;
2834 	pSMB->Fid = fid; /* file handle always le */
2835 	/* 3 byte pad, followed by 2 byte compress state */
2836 	pSMB->ByteCount = cpu_to_le16(5);
2837 	inc_rfc1001_len(pSMB, 5);
2838 
2839 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2840 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2841 	if (rc)
2842 		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
2843 
2844 	cifs_buf_release(pSMB);
2845 
2846 	/*
2847 	 * Note: On -EAGAIN error only caller can retry on handle based calls
2848 	 * since file handle passed in no longer valid.
2849 	 */
2850 	return rc;
2851 }
2852 
2853 
2854 #ifdef CONFIG_CIFS_POSIX
2855 
2856 #ifdef CONFIG_FS_POSIX_ACL
2857 /**
2858  * cifs_init_posix_acl - convert ACL from cifs to POSIX ACL format
2859  * @ace: POSIX ACL entry to store converted ACL into
2860  * @cifs_ace: ACL in cifs format
2861  *
2862  * Convert an Access Control Entry from wire format to local POSIX xattr
2863  * format.
2864  *
2865  * Note that the @cifs_uid member is used to store both {g,u}id_t.
2866  */
cifs_init_posix_acl(struct posix_acl_entry * ace,struct cifs_posix_ace * cifs_ace)2867 static void cifs_init_posix_acl(struct posix_acl_entry *ace,
2868 				struct cifs_posix_ace *cifs_ace)
2869 {
2870 	/* u8 cifs fields do not need le conversion */
2871 	ace->e_perm = cifs_ace->cifs_e_perm;
2872 	ace->e_tag = cifs_ace->cifs_e_tag;
2873 
2874 	switch (ace->e_tag) {
2875 	case ACL_USER:
2876 		ace->e_uid = make_kuid(&init_user_ns,
2877 				       le64_to_cpu(cifs_ace->cifs_uid));
2878 		break;
2879 	case ACL_GROUP:
2880 		ace->e_gid = make_kgid(&init_user_ns,
2881 				       le64_to_cpu(cifs_ace->cifs_uid));
2882 		break;
2883 	}
2884 	return;
2885 }
2886 
2887 /**
2888  * cifs_to_posix_acl - copy cifs ACL format to POSIX ACL format
2889  * @acl: ACLs returned in POSIX ACL format
2890  * @src: ACLs in cifs format
2891  * @acl_type: type of POSIX ACL requested
2892  * @size_of_data_area: size of SMB we got
2893  *
2894  * This function converts ACLs from cifs format to POSIX ACL format.
2895  * If @acl is NULL then the size of the buffer required to store POSIX ACLs in
2896  * their uapi format is returned.
2897  */
cifs_to_posix_acl(struct posix_acl ** acl,char * src,const int acl_type,const int size_of_data_area)2898 static int cifs_to_posix_acl(struct posix_acl **acl, char *src,
2899 			     const int acl_type, const int size_of_data_area)
2900 {
2901 	int size =  0;
2902 	__u16 count;
2903 	struct cifs_posix_ace *pACE;
2904 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2905 	struct posix_acl *kacl = NULL;
2906 	struct posix_acl_entry *pa, *pe;
2907 
2908 	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2909 		return -EOPNOTSUPP;
2910 
2911 	if (acl_type == ACL_TYPE_ACCESS) {
2912 		count = le16_to_cpu(cifs_acl->access_entry_count);
2913 		pACE = &cifs_acl->ace_array[0];
2914 		size = sizeof(struct cifs_posix_acl);
2915 		size += sizeof(struct cifs_posix_ace) * count;
2916 		/* check if we would go beyond end of SMB */
2917 		if (size_of_data_area < size) {
2918 			cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
2919 				 size_of_data_area, size);
2920 			return -EINVAL;
2921 		}
2922 	} else if (acl_type == ACL_TYPE_DEFAULT) {
2923 		count = le16_to_cpu(cifs_acl->access_entry_count);
2924 		size = sizeof(struct cifs_posix_acl);
2925 		size += sizeof(struct cifs_posix_ace) * count;
2926 		/* skip past access ACEs to get to default ACEs */
2927 		pACE = &cifs_acl->ace_array[count];
2928 		count = le16_to_cpu(cifs_acl->default_entry_count);
2929 		size += sizeof(struct cifs_posix_ace) * count;
2930 		/* check if we would go beyond end of SMB */
2931 		if (size_of_data_area < size)
2932 			return -EINVAL;
2933 	} else {
2934 		/* illegal type */
2935 		return -EINVAL;
2936 	}
2937 
2938 	/* Allocate number of POSIX ACLs to store in VFS format. */
2939 	kacl = posix_acl_alloc(count, GFP_NOFS);
2940 	if (!kacl)
2941 		return -ENOMEM;
2942 
2943 	FOREACH_ACL_ENTRY(pa, kacl, pe) {
2944 		cifs_init_posix_acl(pa, pACE);
2945 		pACE++;
2946 	}
2947 
2948 	*acl = kacl;
2949 	return 0;
2950 }
2951 
2952 /**
2953  * cifs_init_ace - convert ACL entry from POSIX ACL to cifs format
2954  * @cifs_ace: the cifs ACL entry to store into
2955  * @local_ace: the POSIX ACL entry to convert
2956  */
cifs_init_ace(struct cifs_posix_ace * cifs_ace,const struct posix_acl_entry * local_ace)2957 static void cifs_init_ace(struct cifs_posix_ace *cifs_ace,
2958 			  const struct posix_acl_entry *local_ace)
2959 {
2960 	cifs_ace->cifs_e_perm = local_ace->e_perm;
2961 	cifs_ace->cifs_e_tag =  local_ace->e_tag;
2962 
2963 	switch (local_ace->e_tag) {
2964 	case ACL_USER:
2965 		cifs_ace->cifs_uid =
2966 			cpu_to_le64(from_kuid(&init_user_ns, local_ace->e_uid));
2967 		break;
2968 	case ACL_GROUP:
2969 		cifs_ace->cifs_uid =
2970 			cpu_to_le64(from_kgid(&init_user_ns, local_ace->e_gid));
2971 		break;
2972 	default:
2973 		cifs_ace->cifs_uid = cpu_to_le64(-1);
2974 	}
2975 }
2976 
2977 /**
2978  * posix_acl_to_cifs - convert ACLs from POSIX ACL to cifs format
2979  * @parm_data: ACLs in cifs format to conver to
2980  * @acl: ACLs in POSIX ACL format to convert from
2981  * @acl_type: the type of POSIX ACLs stored in @acl
2982  *
2983  * Return: the number cifs ACL entries after conversion
2984  */
posix_acl_to_cifs(char * parm_data,const struct posix_acl * acl,const int acl_type)2985 static __u16 posix_acl_to_cifs(char *parm_data, const struct posix_acl *acl,
2986 			       const int acl_type)
2987 {
2988 	__u16 rc = 0;
2989 	struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2990 	const struct posix_acl_entry *pa, *pe;
2991 	int count;
2992 	int i = 0;
2993 
2994 	if ((acl == NULL) || (cifs_acl == NULL))
2995 		return 0;
2996 
2997 	count = acl->a_count;
2998 	cifs_dbg(FYI, "setting acl with %d entries\n", count);
2999 
3000 	/*
3001 	 * Note that the uapi POSIX ACL version is verified by the VFS and is
3002 	 * independent of the cifs ACL version. Changing the POSIX ACL version
3003 	 * is a uapi change and if it's changed we will pass down the POSIX ACL
3004 	 * version in struct posix_acl from the VFS. For now there's really
3005 	 * only one that all filesystems know how to deal with.
3006 	 */
3007 	cifs_acl->version = cpu_to_le16(1);
3008 	if (acl_type == ACL_TYPE_ACCESS) {
3009 		cifs_acl->access_entry_count = cpu_to_le16(count);
3010 		cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3011 	} else if (acl_type == ACL_TYPE_DEFAULT) {
3012 		cifs_acl->default_entry_count = cpu_to_le16(count);
3013 		cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3014 	} else {
3015 		cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3016 		return 0;
3017 	}
3018 	FOREACH_ACL_ENTRY(pa, acl, pe) {
3019 		cifs_init_ace(&cifs_acl->ace_array[i++], pa);
3020 	}
3021 	if (rc == 0) {
3022 		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3023 		rc += sizeof(struct cifs_posix_acl);
3024 		/* BB add check to make sure ACL does not overflow SMB */
3025 	}
3026 	return rc;
3027 }
3028 
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)3029 int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3030 		    const unsigned char *searchName, struct posix_acl **acl,
3031 		    const int acl_type, const struct nls_table *nls_codepage,
3032 		    int remap)
3033 {
3034 /* SMB_QUERY_POSIX_ACL */
3035 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3036 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3037 	int rc = 0;
3038 	int bytes_returned;
3039 	int name_len;
3040 	__u16 params, byte_count;
3041 
3042 	cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3043 
3044 queryAclRetry:
3045 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3046 		(void **) &pSMBr);
3047 	if (rc)
3048 		return rc;
3049 
3050 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3051 		name_len =
3052 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3053 					   searchName, PATH_MAX, nls_codepage,
3054 					   remap);
3055 		name_len++;     /* trailing null */
3056 		name_len *= 2;
3057 		pSMB->FileName[name_len] = 0;
3058 		pSMB->FileName[name_len+1] = 0;
3059 	} else {
3060 		name_len = copy_path_name(pSMB->FileName, searchName);
3061 	}
3062 
3063 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3064 	pSMB->TotalDataCount = 0;
3065 	pSMB->MaxParameterCount = cpu_to_le16(2);
3066 	/* BB find exact max data count below from sess structure BB */
3067 	pSMB->MaxDataCount = cpu_to_le16(4000);
3068 	pSMB->MaxSetupCount = 0;
3069 	pSMB->Reserved = 0;
3070 	pSMB->Flags = 0;
3071 	pSMB->Timeout = 0;
3072 	pSMB->Reserved2 = 0;
3073 	pSMB->ParameterOffset = cpu_to_le16(
3074 		offsetof(struct smb_com_transaction2_qpi_req,
3075 			 InformationLevel) - 4);
3076 	pSMB->DataCount = 0;
3077 	pSMB->DataOffset = 0;
3078 	pSMB->SetupCount = 1;
3079 	pSMB->Reserved3 = 0;
3080 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3081 	byte_count = params + 1 /* pad */ ;
3082 	pSMB->TotalParameterCount = cpu_to_le16(params);
3083 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3084 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3085 	pSMB->Reserved4 = 0;
3086 	inc_rfc1001_len(pSMB, byte_count);
3087 	pSMB->ByteCount = cpu_to_le16(byte_count);
3088 
3089 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3090 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3091 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3092 	if (rc) {
3093 		cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3094 	} else {
3095 		/* decode response */
3096 
3097 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3098 		/* BB also check enough total bytes returned */
3099 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3100 			rc = -EIO;      /* bad smb */
3101 		else {
3102 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3103 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3104 			rc = cifs_to_posix_acl(acl,
3105 				(char *)&pSMBr->hdr.Protocol+data_offset,
3106 				acl_type, count);
3107 		}
3108 	}
3109 	cifs_buf_release(pSMB);
3110 	/*
3111 	 * The else branch after SendReceive() doesn't return EAGAIN so if we
3112 	 * allocated @acl in cifs_to_posix_acl() we are guaranteed to return
3113 	 * here and don't leak POSIX ACLs.
3114 	 */
3115 	if (rc == -EAGAIN)
3116 		goto queryAclRetry;
3117 	return rc;
3118 }
3119 
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)3120 int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3121 		    const unsigned char *fileName, const struct posix_acl *acl,
3122 		    const int acl_type, const struct nls_table *nls_codepage,
3123 		    int remap)
3124 {
3125 	struct smb_com_transaction2_spi_req *pSMB = NULL;
3126 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3127 	char *parm_data;
3128 	int name_len;
3129 	int rc = 0;
3130 	int bytes_returned = 0;
3131 	__u16 params, byte_count, data_count, param_offset, offset;
3132 
3133 	cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3134 setAclRetry:
3135 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3136 		      (void **) &pSMBr);
3137 	if (rc)
3138 		return rc;
3139 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3140 		name_len =
3141 			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3142 					   PATH_MAX, nls_codepage, remap);
3143 		name_len++;     /* trailing null */
3144 		name_len *= 2;
3145 	} else {
3146 		name_len = copy_path_name(pSMB->FileName, fileName);
3147 	}
3148 	params = 6 + name_len;
3149 	pSMB->MaxParameterCount = cpu_to_le16(2);
3150 	/* BB find max SMB size from sess */
3151 	pSMB->MaxDataCount = cpu_to_le16(1000);
3152 	pSMB->MaxSetupCount = 0;
3153 	pSMB->Reserved = 0;
3154 	pSMB->Flags = 0;
3155 	pSMB->Timeout = 0;
3156 	pSMB->Reserved2 = 0;
3157 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
3158 				InformationLevel) - 4;
3159 	offset = param_offset + params;
3160 	parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset;
3161 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
3162 
3163 	/* convert to on the wire format for POSIX ACL */
3164 	data_count = posix_acl_to_cifs(parm_data, acl, acl_type);
3165 
3166 	if (data_count == 0) {
3167 		rc = -EOPNOTSUPP;
3168 		goto setACLerrorExit;
3169 	}
3170 	pSMB->DataOffset = cpu_to_le16(offset);
3171 	pSMB->SetupCount = 1;
3172 	pSMB->Reserved3 = 0;
3173 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3174 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3175 	byte_count = 3 /* pad */  + params + data_count;
3176 	pSMB->DataCount = cpu_to_le16(data_count);
3177 	pSMB->TotalDataCount = pSMB->DataCount;
3178 	pSMB->ParameterCount = cpu_to_le16(params);
3179 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3180 	pSMB->Reserved4 = 0;
3181 	inc_rfc1001_len(pSMB, byte_count);
3182 	pSMB->ByteCount = cpu_to_le16(byte_count);
3183 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3184 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3185 	if (rc)
3186 		cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3187 
3188 setACLerrorExit:
3189 	cifs_buf_release(pSMB);
3190 	if (rc == -EAGAIN)
3191 		goto setAclRetry;
3192 	return rc;
3193 }
3194 #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)3195 int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
3196 		    const unsigned char *searchName, struct posix_acl **acl,
3197 		    const int acl_type, const struct nls_table *nls_codepage,
3198 		    int remap)
3199 {
3200 	return -EOPNOTSUPP;
3201 }
3202 
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)3203 int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
3204 		    const unsigned char *fileName, const struct posix_acl *acl,
3205 		    const int acl_type, const struct nls_table *nls_codepage,
3206 		    int remap)
3207 {
3208 	return -EOPNOTSUPP;
3209 }
3210 #endif /* CONFIG_FS_POSIX_ACL */
3211 
3212 int
CIFSGetExtAttr(const unsigned int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3213 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3214 	       const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3215 {
3216 	int rc = 0;
3217 	struct smb_t2_qfi_req *pSMB = NULL;
3218 	struct smb_t2_qfi_rsp *pSMBr = NULL;
3219 	int bytes_returned;
3220 	__u16 params, byte_count;
3221 
3222 	cifs_dbg(FYI, "In GetExtAttr\n");
3223 	if (tcon == NULL)
3224 		return -ENODEV;
3225 
3226 GetExtAttrRetry:
3227 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3228 		      (void **) &pSMBr);
3229 	if (rc)
3230 		return rc;
3231 
3232 	params = 2 /* level */ + 2 /* fid */;
3233 	pSMB->t2.TotalDataCount = 0;
3234 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3235 	/* BB find exact max data count below from sess structure BB */
3236 	pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3237 	pSMB->t2.MaxSetupCount = 0;
3238 	pSMB->t2.Reserved = 0;
3239 	pSMB->t2.Flags = 0;
3240 	pSMB->t2.Timeout = 0;
3241 	pSMB->t2.Reserved2 = 0;
3242 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3243 					       Fid) - 4);
3244 	pSMB->t2.DataCount = 0;
3245 	pSMB->t2.DataOffset = 0;
3246 	pSMB->t2.SetupCount = 1;
3247 	pSMB->t2.Reserved3 = 0;
3248 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3249 	byte_count = params + 1 /* pad */ ;
3250 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3251 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3252 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3253 	pSMB->Pad = 0;
3254 	pSMB->Fid = netfid;
3255 	inc_rfc1001_len(pSMB, byte_count);
3256 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3257 
3258 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3259 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3260 	if (rc) {
3261 		cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3262 	} else {
3263 		/* decode response */
3264 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3265 		/* BB also check enough total bytes returned */
3266 		if (rc || get_bcc(&pSMBr->hdr) < 2)
3267 			/* If rc should we check for EOPNOSUPP and
3268 			   disable the srvino flag? or in caller? */
3269 			rc = -EIO;      /* bad smb */
3270 		else {
3271 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3272 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3273 			struct file_chattr_info *pfinfo;
3274 
3275 			if (count != 16) {
3276 				cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n");
3277 				rc = -EIO;
3278 				goto GetExtAttrOut;
3279 			}
3280 			pfinfo = (struct file_chattr_info *)
3281 				 (data_offset + (char *) &pSMBr->hdr.Protocol);
3282 			*pExtAttrBits = le64_to_cpu(pfinfo->mode);
3283 			*pMask = le64_to_cpu(pfinfo->mask);
3284 		}
3285 	}
3286 GetExtAttrOut:
3287 	cifs_buf_release(pSMB);
3288 	if (rc == -EAGAIN)
3289 		goto GetExtAttrRetry;
3290 	return rc;
3291 }
3292 
3293 #endif /* CONFIG_POSIX */
3294 
3295 /*
3296  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3297  * all NT TRANSACTS that we init here have total parm and data under about 400
3298  * bytes (to fit in small cifs buffer size), which is the case so far, it
3299  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3300  * returned setup area) and MaxParameterCount (returned parms size) must be set
3301  * by caller
3302  */
3303 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3304 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3305 		   const int parm_len, struct cifs_tcon *tcon,
3306 		   void **ret_buf)
3307 {
3308 	int rc;
3309 	__u32 temp_offset;
3310 	struct smb_com_ntransact_req *pSMB;
3311 
3312 	rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3313 				(void **)&pSMB);
3314 	if (rc)
3315 		return rc;
3316 	*ret_buf = (void *)pSMB;
3317 	pSMB->Reserved = 0;
3318 	pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3319 	pSMB->TotalDataCount  = 0;
3320 	pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3321 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3322 	pSMB->DataCount  = pSMB->TotalDataCount;
3323 	temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3324 			(setup_count * 2) - 4 /* for rfc1001 length itself */;
3325 	pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3326 	pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3327 	pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3328 	pSMB->SubCommand = cpu_to_le16(sub_command);
3329 	return 0;
3330 }
3331 
3332 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3333 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3334 		   __u32 *pparmlen, __u32 *pdatalen)
3335 {
3336 	char *end_of_smb;
3337 	__u32 data_count, data_offset, parm_count, parm_offset;
3338 	struct smb_com_ntransact_rsp *pSMBr;
3339 	u16 bcc;
3340 
3341 	*pdatalen = 0;
3342 	*pparmlen = 0;
3343 
3344 	if (buf == NULL)
3345 		return -EINVAL;
3346 
3347 	pSMBr = (struct smb_com_ntransact_rsp *)buf;
3348 
3349 	bcc = get_bcc(&pSMBr->hdr);
3350 	end_of_smb = 2 /* sizeof byte count */ + bcc +
3351 			(char *)&pSMBr->ByteCount;
3352 
3353 	data_offset = le32_to_cpu(pSMBr->DataOffset);
3354 	data_count = le32_to_cpu(pSMBr->DataCount);
3355 	parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3356 	parm_count = le32_to_cpu(pSMBr->ParameterCount);
3357 
3358 	*ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3359 	*ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3360 
3361 	/* should we also check that parm and data areas do not overlap? */
3362 	if (*ppparm > end_of_smb) {
3363 		cifs_dbg(FYI, "parms start after end of smb\n");
3364 		return -EINVAL;
3365 	} else if (parm_count + *ppparm > end_of_smb) {
3366 		cifs_dbg(FYI, "parm end after end of smb\n");
3367 		return -EINVAL;
3368 	} else if (*ppdata > end_of_smb) {
3369 		cifs_dbg(FYI, "data starts after end of smb\n");
3370 		return -EINVAL;
3371 	} else if (data_count + *ppdata > end_of_smb) {
3372 		cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3373 			 *ppdata, data_count, (data_count + *ppdata),
3374 			 end_of_smb, pSMBr);
3375 		return -EINVAL;
3376 	} else if (parm_count + data_count > bcc) {
3377 		cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3378 		return -EINVAL;
3379 	}
3380 	*pdatalen = data_count;
3381 	*pparmlen = parm_count;
3382 	return 0;
3383 }
3384 
3385 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3386 int
CIFSSMBGetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd ** acl_inf,__u32 * pbuflen)3387 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3388 		  struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3389 {
3390 	int rc = 0;
3391 	int buf_type = 0;
3392 	QUERY_SEC_DESC_REQ *pSMB;
3393 	struct kvec iov[1];
3394 	struct kvec rsp_iov;
3395 
3396 	cifs_dbg(FYI, "GetCifsACL\n");
3397 
3398 	*pbuflen = 0;
3399 	*acl_inf = NULL;
3400 
3401 	rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3402 			8 /* parm len */, tcon, (void **) &pSMB);
3403 	if (rc)
3404 		return rc;
3405 
3406 	pSMB->MaxParameterCount = cpu_to_le32(4);
3407 	/* BB TEST with big acls that might need to be e.g. larger than 16K */
3408 	pSMB->MaxSetupCount = 0;
3409 	pSMB->Fid = fid; /* file handle always le */
3410 	pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3411 				     CIFS_ACL_DACL);
3412 	pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3413 	inc_rfc1001_len(pSMB, 11);
3414 	iov[0].iov_base = (char *)pSMB;
3415 	iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3416 
3417 	rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3418 			  0, &rsp_iov);
3419 	cifs_small_buf_release(pSMB);
3420 	cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3421 	if (rc) {
3422 		cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3423 	} else {                /* decode response */
3424 		__le32 *parm;
3425 		__u32 parm_len;
3426 		__u32 acl_len;
3427 		struct smb_com_ntransact_rsp *pSMBr;
3428 		char *pdata;
3429 
3430 /* validate_nttransact */
3431 		rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3432 					&pdata, &parm_len, pbuflen);
3433 		if (rc)
3434 			goto qsec_out;
3435 		pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3436 
3437 		cifs_dbg(FYI, "smb %p parm %p data %p\n",
3438 			 pSMBr, parm, *acl_inf);
3439 
3440 		if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3441 			rc = -EIO;      /* bad smb */
3442 			*pbuflen = 0;
3443 			goto qsec_out;
3444 		}
3445 
3446 /* BB check that data area is minimum length and as big as acl_len */
3447 
3448 		acl_len = le32_to_cpu(*parm);
3449 		if (acl_len != *pbuflen) {
3450 			cifs_dbg(VFS, "acl length %d does not match %d\n",
3451 				 acl_len, *pbuflen);
3452 			if (*pbuflen > acl_len)
3453 				*pbuflen = acl_len;
3454 		}
3455 
3456 		/* check if buffer is big enough for the acl
3457 		   header followed by the smallest SID */
3458 		if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3459 		    (*pbuflen >= 64 * 1024)) {
3460 			cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3461 			rc = -EINVAL;
3462 			*pbuflen = 0;
3463 		} else {
3464 			*acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3465 			if (*acl_inf == NULL) {
3466 				*pbuflen = 0;
3467 				rc = -ENOMEM;
3468 			}
3469 		}
3470 	}
3471 qsec_out:
3472 	free_rsp_buf(buf_type, rsp_iov.iov_base);
3473 	return rc;
3474 }
3475 
3476 int
CIFSSMBSetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd * pntsd,__u32 acllen,int aclflag)3477 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3478 			struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3479 {
3480 	__u16 byte_count, param_count, data_count, param_offset, data_offset;
3481 	int rc = 0;
3482 	int bytes_returned = 0;
3483 	SET_SEC_DESC_REQ *pSMB = NULL;
3484 	void *pSMBr;
3485 
3486 setCifsAclRetry:
3487 	rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3488 	if (rc)
3489 		return rc;
3490 
3491 	pSMB->MaxSetupCount = 0;
3492 	pSMB->Reserved = 0;
3493 
3494 	param_count = 8;
3495 	param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3496 	data_count = acllen;
3497 	data_offset = param_offset + param_count;
3498 	byte_count = 3 /* pad */  + param_count;
3499 
3500 	pSMB->DataCount = cpu_to_le32(data_count);
3501 	pSMB->TotalDataCount = pSMB->DataCount;
3502 	pSMB->MaxParameterCount = cpu_to_le32(4);
3503 	pSMB->MaxDataCount = cpu_to_le32(16384);
3504 	pSMB->ParameterCount = cpu_to_le32(param_count);
3505 	pSMB->ParameterOffset = cpu_to_le32(param_offset);
3506 	pSMB->TotalParameterCount = pSMB->ParameterCount;
3507 	pSMB->DataOffset = cpu_to_le32(data_offset);
3508 	pSMB->SetupCount = 0;
3509 	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3510 	pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3511 
3512 	pSMB->Fid = fid; /* file handle always le */
3513 	pSMB->Reserved2 = 0;
3514 	pSMB->AclFlags = cpu_to_le32(aclflag);
3515 
3516 	if (pntsd && acllen) {
3517 		memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3518 				data_offset, pntsd, acllen);
3519 		inc_rfc1001_len(pSMB, byte_count + data_count);
3520 	} else
3521 		inc_rfc1001_len(pSMB, byte_count);
3522 
3523 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3524 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
3525 
3526 	cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3527 		 bytes_returned, rc);
3528 	if (rc)
3529 		cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3530 	cifs_buf_release(pSMB);
3531 
3532 	if (rc == -EAGAIN)
3533 		goto setCifsAclRetry;
3534 
3535 	return (rc);
3536 }
3537 
3538 
3539 /* Legacy Query Path Information call for lookup to old servers such
3540    as Win9x/WinME */
3541 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)3542 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3543 		    const char *search_name, FILE_ALL_INFO *data,
3544 		    const struct nls_table *nls_codepage, int remap)
3545 {
3546 	QUERY_INFORMATION_REQ *pSMB;
3547 	QUERY_INFORMATION_RSP *pSMBr;
3548 	int rc = 0;
3549 	int bytes_returned;
3550 	int name_len;
3551 
3552 	cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3553 QInfRetry:
3554 	rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3555 		      (void **) &pSMBr);
3556 	if (rc)
3557 		return rc;
3558 
3559 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3560 		name_len =
3561 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
3562 					   search_name, PATH_MAX, nls_codepage,
3563 					   remap);
3564 		name_len++;     /* trailing null */
3565 		name_len *= 2;
3566 	} else {
3567 		name_len = copy_path_name(pSMB->FileName, search_name);
3568 	}
3569 	pSMB->BufferFormat = 0x04;
3570 	name_len++; /* account for buffer type byte */
3571 	inc_rfc1001_len(pSMB, (__u16)name_len);
3572 	pSMB->ByteCount = cpu_to_le16(name_len);
3573 
3574 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3575 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3576 	if (rc) {
3577 		cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
3578 	} else if (data) {
3579 		struct timespec64 ts;
3580 		__u32 time = le32_to_cpu(pSMBr->last_write_time);
3581 
3582 		/* decode response */
3583 		/* BB FIXME - add time zone adjustment BB */
3584 		memset(data, 0, sizeof(FILE_ALL_INFO));
3585 		ts.tv_nsec = 0;
3586 		ts.tv_sec = time;
3587 		/* decode time fields */
3588 		data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3589 		data->LastWriteTime = data->ChangeTime;
3590 		data->LastAccessTime = 0;
3591 		data->AllocationSize =
3592 			cpu_to_le64(le32_to_cpu(pSMBr->size));
3593 		data->EndOfFile = data->AllocationSize;
3594 		data->Attributes =
3595 			cpu_to_le32(le16_to_cpu(pSMBr->attr));
3596 	} else
3597 		rc = -EIO; /* bad buffer passed in */
3598 
3599 	cifs_buf_release(pSMB);
3600 
3601 	if (rc == -EAGAIN)
3602 		goto QInfRetry;
3603 
3604 	return rc;
3605 }
3606 
3607 int
CIFSSMBQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)3608 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3609 		 u16 netfid, FILE_ALL_INFO *pFindData)
3610 {
3611 	struct smb_t2_qfi_req *pSMB = NULL;
3612 	struct smb_t2_qfi_rsp *pSMBr = NULL;
3613 	int rc = 0;
3614 	int bytes_returned;
3615 	__u16 params, byte_count;
3616 
3617 QFileInfoRetry:
3618 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3619 		      (void **) &pSMBr);
3620 	if (rc)
3621 		return rc;
3622 
3623 	params = 2 /* level */ + 2 /* fid */;
3624 	pSMB->t2.TotalDataCount = 0;
3625 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3626 	/* BB find exact max data count below from sess structure BB */
3627 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3628 	pSMB->t2.MaxSetupCount = 0;
3629 	pSMB->t2.Reserved = 0;
3630 	pSMB->t2.Flags = 0;
3631 	pSMB->t2.Timeout = 0;
3632 	pSMB->t2.Reserved2 = 0;
3633 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3634 					       Fid) - 4);
3635 	pSMB->t2.DataCount = 0;
3636 	pSMB->t2.DataOffset = 0;
3637 	pSMB->t2.SetupCount = 1;
3638 	pSMB->t2.Reserved3 = 0;
3639 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3640 	byte_count = params + 1 /* pad */ ;
3641 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3642 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3643 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3644 	pSMB->Pad = 0;
3645 	pSMB->Fid = netfid;
3646 	inc_rfc1001_len(pSMB, byte_count);
3647 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3648 
3649 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3650 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3651 	if (rc) {
3652 		cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc);
3653 	} else {		/* decode response */
3654 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3655 
3656 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
3657 			rc = -EIO;
3658 		else if (get_bcc(&pSMBr->hdr) < 40)
3659 			rc = -EIO;	/* bad smb */
3660 		else if (pFindData) {
3661 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3662 			memcpy((char *) pFindData,
3663 			       (char *) &pSMBr->hdr.Protocol +
3664 			       data_offset, sizeof(FILE_ALL_INFO));
3665 		} else
3666 		    rc = -ENOMEM;
3667 	}
3668 	cifs_buf_release(pSMB);
3669 	if (rc == -EAGAIN)
3670 		goto QFileInfoRetry;
3671 
3672 	return rc;
3673 }
3674 
3675 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)3676 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3677 		 const char *search_name, FILE_ALL_INFO *data,
3678 		 int legacy /* old style infolevel */,
3679 		 const struct nls_table *nls_codepage, int remap)
3680 {
3681 	/* level 263 SMB_QUERY_FILE_ALL_INFO */
3682 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3683 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3684 	int rc = 0;
3685 	int bytes_returned;
3686 	int name_len;
3687 	__u16 params, byte_count;
3688 
3689 	/* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
3690 QPathInfoRetry:
3691 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3692 		      (void **) &pSMBr);
3693 	if (rc)
3694 		return rc;
3695 
3696 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3697 		name_len =
3698 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
3699 				       PATH_MAX, nls_codepage, remap);
3700 		name_len++;	/* trailing null */
3701 		name_len *= 2;
3702 	} else {
3703 		name_len = copy_path_name(pSMB->FileName, search_name);
3704 	}
3705 
3706 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3707 	pSMB->TotalDataCount = 0;
3708 	pSMB->MaxParameterCount = cpu_to_le16(2);
3709 	/* BB find exact max SMB PDU from sess structure BB */
3710 	pSMB->MaxDataCount = cpu_to_le16(4000);
3711 	pSMB->MaxSetupCount = 0;
3712 	pSMB->Reserved = 0;
3713 	pSMB->Flags = 0;
3714 	pSMB->Timeout = 0;
3715 	pSMB->Reserved2 = 0;
3716 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
3717 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3718 	pSMB->DataCount = 0;
3719 	pSMB->DataOffset = 0;
3720 	pSMB->SetupCount = 1;
3721 	pSMB->Reserved3 = 0;
3722 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3723 	byte_count = params + 1 /* pad */ ;
3724 	pSMB->TotalParameterCount = cpu_to_le16(params);
3725 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3726 	if (legacy)
3727 		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3728 	else
3729 		pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3730 	pSMB->Reserved4 = 0;
3731 	inc_rfc1001_len(pSMB, byte_count);
3732 	pSMB->ByteCount = cpu_to_le16(byte_count);
3733 
3734 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3735 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3736 	if (rc) {
3737 		cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
3738 	} else {		/* decode response */
3739 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3740 
3741 		if (rc) /* BB add auto retry on EOPNOTSUPP? */
3742 			rc = -EIO;
3743 		else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
3744 			rc = -EIO;	/* bad smb */
3745 		else if (legacy && get_bcc(&pSMBr->hdr) < 24)
3746 			rc = -EIO;  /* 24 or 26 expected but we do not read
3747 					last field */
3748 		else if (data) {
3749 			int size;
3750 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3751 
3752 			/*
3753 			 * On legacy responses we do not read the last field,
3754 			 * EAsize, fortunately since it varies by subdialect and
3755 			 * also note it differs on Set vs Get, ie two bytes or 4
3756 			 * bytes depending but we don't care here.
3757 			 */
3758 			if (legacy)
3759 				size = sizeof(FILE_INFO_STANDARD);
3760 			else
3761 				size = sizeof(FILE_ALL_INFO);
3762 			memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
3763 			       data_offset, size);
3764 		} else
3765 		    rc = -ENOMEM;
3766 	}
3767 	cifs_buf_release(pSMB);
3768 	if (rc == -EAGAIN)
3769 		goto QPathInfoRetry;
3770 
3771 	return rc;
3772 }
3773 
3774 int
CIFSSMBUnixQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)3775 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
3776 		 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3777 {
3778 	struct smb_t2_qfi_req *pSMB = NULL;
3779 	struct smb_t2_qfi_rsp *pSMBr = NULL;
3780 	int rc = 0;
3781 	int bytes_returned;
3782 	__u16 params, byte_count;
3783 
3784 UnixQFileInfoRetry:
3785 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3786 		      (void **) &pSMBr);
3787 	if (rc)
3788 		return rc;
3789 
3790 	params = 2 /* level */ + 2 /* fid */;
3791 	pSMB->t2.TotalDataCount = 0;
3792 	pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3793 	/* BB find exact max data count below from sess structure BB */
3794 	pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3795 	pSMB->t2.MaxSetupCount = 0;
3796 	pSMB->t2.Reserved = 0;
3797 	pSMB->t2.Flags = 0;
3798 	pSMB->t2.Timeout = 0;
3799 	pSMB->t2.Reserved2 = 0;
3800 	pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3801 					       Fid) - 4);
3802 	pSMB->t2.DataCount = 0;
3803 	pSMB->t2.DataOffset = 0;
3804 	pSMB->t2.SetupCount = 1;
3805 	pSMB->t2.Reserved3 = 0;
3806 	pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3807 	byte_count = params + 1 /* pad */ ;
3808 	pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3809 	pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3810 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3811 	pSMB->Pad = 0;
3812 	pSMB->Fid = netfid;
3813 	inc_rfc1001_len(pSMB, byte_count);
3814 	pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3815 
3816 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3817 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3818 	if (rc) {
3819 		cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc);
3820 	} else {		/* decode response */
3821 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3822 
3823 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3824 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
3825 			rc = -EIO;	/* bad smb */
3826 		} else {
3827 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3828 			memcpy((char *) pFindData,
3829 			       (char *) &pSMBr->hdr.Protocol +
3830 			       data_offset,
3831 			       sizeof(FILE_UNIX_BASIC_INFO));
3832 		}
3833 	}
3834 
3835 	cifs_buf_release(pSMB);
3836 	if (rc == -EAGAIN)
3837 		goto UnixQFileInfoRetry;
3838 
3839 	return rc;
3840 }
3841 
3842 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)3843 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
3844 		     const unsigned char *searchName,
3845 		     FILE_UNIX_BASIC_INFO *pFindData,
3846 		     const struct nls_table *nls_codepage, int remap)
3847 {
3848 /* SMB_QUERY_FILE_UNIX_BASIC */
3849 	TRANSACTION2_QPI_REQ *pSMB = NULL;
3850 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
3851 	int rc = 0;
3852 	int bytes_returned = 0;
3853 	int name_len;
3854 	__u16 params, byte_count;
3855 
3856 	cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
3857 UnixQPathInfoRetry:
3858 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3859 		      (void **) &pSMBr);
3860 	if (rc)
3861 		return rc;
3862 
3863 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3864 		name_len =
3865 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3866 				       PATH_MAX, nls_codepage, remap);
3867 		name_len++;	/* trailing null */
3868 		name_len *= 2;
3869 	} else {
3870 		name_len = copy_path_name(pSMB->FileName, searchName);
3871 	}
3872 
3873 	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3874 	pSMB->TotalDataCount = 0;
3875 	pSMB->MaxParameterCount = cpu_to_le16(2);
3876 	/* BB find exact max SMB PDU from sess structure BB */
3877 	pSMB->MaxDataCount = cpu_to_le16(4000);
3878 	pSMB->MaxSetupCount = 0;
3879 	pSMB->Reserved = 0;
3880 	pSMB->Flags = 0;
3881 	pSMB->Timeout = 0;
3882 	pSMB->Reserved2 = 0;
3883 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
3884 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3885 	pSMB->DataCount = 0;
3886 	pSMB->DataOffset = 0;
3887 	pSMB->SetupCount = 1;
3888 	pSMB->Reserved3 = 0;
3889 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3890 	byte_count = params + 1 /* pad */ ;
3891 	pSMB->TotalParameterCount = cpu_to_le16(params);
3892 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3893 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3894 	pSMB->Reserved4 = 0;
3895 	inc_rfc1001_len(pSMB, byte_count);
3896 	pSMB->ByteCount = cpu_to_le16(byte_count);
3897 
3898 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3899 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3900 	if (rc) {
3901 		cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc);
3902 	} else {		/* decode response */
3903 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3904 
3905 		if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3906 			cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
3907 			rc = -EIO;	/* bad smb */
3908 		} else {
3909 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3910 			memcpy((char *) pFindData,
3911 			       (char *) &pSMBr->hdr.Protocol +
3912 			       data_offset,
3913 			       sizeof(FILE_UNIX_BASIC_INFO));
3914 		}
3915 	}
3916 	cifs_buf_release(pSMB);
3917 	if (rc == -EAGAIN)
3918 		goto UnixQPathInfoRetry;
3919 
3920 	return rc;
3921 }
3922 
3923 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3924 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)3925 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
3926 	      const char *searchName, struct cifs_sb_info *cifs_sb,
3927 	      __u16 *pnetfid, __u16 search_flags,
3928 	      struct cifs_search_info *psrch_inf, bool msearch)
3929 {
3930 /* level 257 SMB_ */
3931 	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3932 	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3933 	T2_FFIRST_RSP_PARMS *parms;
3934 	struct nls_table *nls_codepage;
3935 	unsigned int lnoff;
3936 	__u16 params, byte_count;
3937 	int bytes_returned = 0;
3938 	int name_len, remap;
3939 	int rc = 0;
3940 
3941 	cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
3942 
3943 findFirstRetry:
3944 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3945 		      (void **) &pSMBr);
3946 	if (rc)
3947 		return rc;
3948 
3949 	nls_codepage = cifs_sb->local_nls;
3950 	remap = cifs_remap(cifs_sb);
3951 
3952 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3953 		name_len =
3954 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3955 				       PATH_MAX, nls_codepage, remap);
3956 		/* We can not add the asterik earlier in case
3957 		it got remapped to 0xF03A as if it were part of the
3958 		directory name instead of a wildcard */
3959 		name_len *= 2;
3960 		if (msearch) {
3961 			pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
3962 			pSMB->FileName[name_len+1] = 0;
3963 			pSMB->FileName[name_len+2] = '*';
3964 			pSMB->FileName[name_len+3] = 0;
3965 			name_len += 4; /* now the trailing null */
3966 			/* null terminate just in case */
3967 			pSMB->FileName[name_len] = 0;
3968 			pSMB->FileName[name_len+1] = 0;
3969 			name_len += 2;
3970 		}
3971 	} else {
3972 		name_len = copy_path_name(pSMB->FileName, searchName);
3973 		if (msearch) {
3974 			if (WARN_ON_ONCE(name_len > PATH_MAX-2))
3975 				name_len = PATH_MAX-2;
3976 			/* overwrite nul byte */
3977 			pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
3978 			pSMB->FileName[name_len] = '*';
3979 			pSMB->FileName[name_len+1] = 0;
3980 			name_len += 2;
3981 		}
3982 	}
3983 
3984 	params = 12 + name_len /* includes null */ ;
3985 	pSMB->TotalDataCount = 0;	/* no EAs */
3986 	pSMB->MaxParameterCount = cpu_to_le16(10);
3987 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
3988 	pSMB->MaxSetupCount = 0;
3989 	pSMB->Reserved = 0;
3990 	pSMB->Flags = 0;
3991 	pSMB->Timeout = 0;
3992 	pSMB->Reserved2 = 0;
3993 	byte_count = params + 1 /* pad */ ;
3994 	pSMB->TotalParameterCount = cpu_to_le16(params);
3995 	pSMB->ParameterCount = pSMB->TotalParameterCount;
3996 	pSMB->ParameterOffset = cpu_to_le16(
3997 	      offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3998 		- 4);
3999 	pSMB->DataCount = 0;
4000 	pSMB->DataOffset = 0;
4001 	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
4002 	pSMB->Reserved3 = 0;
4003 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4004 	pSMB->SearchAttributes =
4005 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4006 			ATTR_DIRECTORY);
4007 	pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4008 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4009 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4010 
4011 	/* BB what should we set StorageType to? Does it matter? BB */
4012 	pSMB->SearchStorageType = 0;
4013 	inc_rfc1001_len(pSMB, byte_count);
4014 	pSMB->ByteCount = cpu_to_le16(byte_count);
4015 
4016 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4017 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4018 	cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4019 
4020 	if (rc) {
4021 		/*
4022 		 * BB: add logic to retry regular search if Unix search rejected
4023 		 * unexpectedly by server.
4024 		 */
4025 		/* BB: add code to handle unsupported level rc */
4026 		cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4027 		cifs_buf_release(pSMB);
4028 		/*
4029 		 * BB: eventually could optimize out free and realloc of buf for
4030 		 * this case.
4031 		 */
4032 		if (rc == -EAGAIN)
4033 			goto findFirstRetry;
4034 		return rc;
4035 	}
4036 	/* decode response */
4037 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4038 	if (rc) {
4039 		cifs_buf_release(pSMB);
4040 		return rc;
4041 	}
4042 
4043 	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4044 	psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4045 	psrch_inf->smallBuf = false;
4046 	psrch_inf->srch_entries_start = (char *)&pSMBr->hdr.Protocol +
4047 		le16_to_cpu(pSMBr->t2.DataOffset);
4048 
4049 	parms = (T2_FFIRST_RSP_PARMS *)((char *)&pSMBr->hdr.Protocol +
4050 					le16_to_cpu(pSMBr->t2.ParameterOffset));
4051 	psrch_inf->endOfSearch = !!parms->EndofSearch;
4052 
4053 	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4054 	psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4055 		psrch_inf->entries_in_buffer;
4056 	lnoff = le16_to_cpu(parms->LastNameOffset);
4057 	if (CIFSMaxBufSize < lnoff) {
4058 		cifs_dbg(VFS, "ignoring corrupt resume name\n");
4059 		psrch_inf->last_entry = NULL;
4060 	} else {
4061 		psrch_inf->last_entry = psrch_inf->srch_entries_start + lnoff;
4062 		if (pnetfid)
4063 			*pnetfid = parms->SearchHandle;
4064 	}
4065 	return 0;
4066 }
4067 
CIFSFindNext(const unsigned int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4068 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4069 		 __u16 searchHandle, __u16 search_flags,
4070 		 struct cifs_search_info *psrch_inf)
4071 {
4072 	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4073 	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4074 	T2_FNEXT_RSP_PARMS *parms;
4075 	unsigned int name_len;
4076 	unsigned int lnoff;
4077 	__u16 params, byte_count;
4078 	char *response_data;
4079 	int bytes_returned;
4080 	int rc = 0;
4081 
4082 	cifs_dbg(FYI, "In FindNext\n");
4083 
4084 	if (psrch_inf->endOfSearch)
4085 		return -ENOENT;
4086 
4087 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4088 		(void **) &pSMBr);
4089 	if (rc)
4090 		return rc;
4091 
4092 	params = 14; /* includes 2 bytes of null string, converted to LE below*/
4093 	byte_count = 0;
4094 	pSMB->TotalDataCount = 0;       /* no EAs */
4095 	pSMB->MaxParameterCount = cpu_to_le16(8);
4096 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4097 	pSMB->MaxSetupCount = 0;
4098 	pSMB->Reserved = 0;
4099 	pSMB->Flags = 0;
4100 	pSMB->Timeout = 0;
4101 	pSMB->Reserved2 = 0;
4102 	pSMB->ParameterOffset =  cpu_to_le16(
4103 	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4104 	pSMB->DataCount = 0;
4105 	pSMB->DataOffset = 0;
4106 	pSMB->SetupCount = 1;
4107 	pSMB->Reserved3 = 0;
4108 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4109 	pSMB->SearchHandle = searchHandle;      /* always kept as le */
4110 	pSMB->SearchCount =
4111 		cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4112 	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4113 	pSMB->ResumeKey = psrch_inf->resume_key;
4114 	pSMB->SearchFlags = cpu_to_le16(search_flags);
4115 
4116 	name_len = psrch_inf->resume_name_len;
4117 	params += name_len;
4118 	if (name_len < PATH_MAX) {
4119 		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4120 		byte_count += name_len;
4121 		/* 14 byte parm len above enough for 2 byte null terminator */
4122 		pSMB->ResumeFileName[name_len] = 0;
4123 		pSMB->ResumeFileName[name_len+1] = 0;
4124 	} else {
4125 		cifs_buf_release(pSMB);
4126 		return -EINVAL;
4127 	}
4128 	byte_count = params + 1 /* pad */ ;
4129 	pSMB->TotalParameterCount = cpu_to_le16(params);
4130 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4131 	inc_rfc1001_len(pSMB, byte_count);
4132 	pSMB->ByteCount = cpu_to_le16(byte_count);
4133 
4134 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4135 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4136 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4137 
4138 	if (rc) {
4139 		cifs_buf_release(pSMB);
4140 		if (rc == -EBADF) {
4141 			psrch_inf->endOfSearch = true;
4142 			rc = 0; /* search probably was closed at end of search*/
4143 		} else {
4144 			cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4145 		}
4146 		return rc;
4147 	}
4148 
4149 	/* decode response */
4150 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4151 	if (rc) {
4152 		cifs_buf_release(pSMB);
4153 		return rc;
4154 	}
4155 	/* BB fixme add lock for file (srch_info) struct here */
4156 	psrch_inf->unicode = !!(pSMBr->hdr.Flags2 & SMBFLG2_UNICODE);
4157 	response_data = (char *)&pSMBr->hdr.Protocol +
4158 		le16_to_cpu(pSMBr->t2.ParameterOffset);
4159 	parms = (T2_FNEXT_RSP_PARMS *)response_data;
4160 	response_data = (char *)&pSMBr->hdr.Protocol +
4161 		le16_to_cpu(pSMBr->t2.DataOffset);
4162 
4163 	if (psrch_inf->smallBuf)
4164 		cifs_small_buf_release(psrch_inf->ntwrk_buf_start);
4165 	else
4166 		cifs_buf_release(psrch_inf->ntwrk_buf_start);
4167 
4168 	psrch_inf->srch_entries_start = response_data;
4169 	psrch_inf->ntwrk_buf_start = (char *)pSMB;
4170 	psrch_inf->smallBuf = false;
4171 	psrch_inf->endOfSearch = !!parms->EndofSearch;
4172 	psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
4173 	psrch_inf->index_of_last_entry += psrch_inf->entries_in_buffer;
4174 	lnoff = le16_to_cpu(parms->LastNameOffset);
4175 	if (CIFSMaxBufSize < lnoff) {
4176 		cifs_dbg(VFS, "ignoring corrupt resume name\n");
4177 		psrch_inf->last_entry = NULL;
4178 	} else {
4179 		psrch_inf->last_entry =
4180 			psrch_inf->srch_entries_start + lnoff;
4181 	}
4182 	/* BB fixme add unlock here */
4183 
4184 	/*
4185 	 * BB: On error, should we leave previous search buf
4186 	 * (and count and last entry fields) intact or free the previous one?
4187 	 *
4188 	 * Note: On -EAGAIN error only caller can retry on handle based calls
4189 	 * since file handle passed in no longer valid.
4190 	 */
4191 	return 0;
4192 }
4193 
4194 int
CIFSFindClose(const unsigned int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4195 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4196 	      const __u16 searchHandle)
4197 {
4198 	int rc = 0;
4199 	FINDCLOSE_REQ *pSMB = NULL;
4200 
4201 	cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4202 	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4203 
4204 	/* no sense returning error if session restarted
4205 		as file handle has been closed */
4206 	if (rc == -EAGAIN)
4207 		return 0;
4208 	if (rc)
4209 		return rc;
4210 
4211 	pSMB->FileID = searchHandle;
4212 	pSMB->ByteCount = 0;
4213 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4214 	cifs_small_buf_release(pSMB);
4215 	if (rc)
4216 		cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4217 
4218 	cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4219 
4220 	/* Since session is dead, search handle closed on server already */
4221 	if (rc == -EAGAIN)
4222 		rc = 0;
4223 
4224 	return rc;
4225 }
4226 
4227 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)4228 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4229 		      const char *search_name, __u64 *inode_number,
4230 		      const struct nls_table *nls_codepage, int remap)
4231 {
4232 	int rc = 0;
4233 	TRANSACTION2_QPI_REQ *pSMB = NULL;
4234 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
4235 	int name_len, bytes_returned;
4236 	__u16 params, byte_count;
4237 
4238 	cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4239 	if (tcon == NULL)
4240 		return -ENODEV;
4241 
4242 GetInodeNumberRetry:
4243 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4244 		      (void **) &pSMBr);
4245 	if (rc)
4246 		return rc;
4247 
4248 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4249 		name_len =
4250 			cifsConvertToUTF16((__le16 *) pSMB->FileName,
4251 					   search_name, PATH_MAX, nls_codepage,
4252 					   remap);
4253 		name_len++;     /* trailing null */
4254 		name_len *= 2;
4255 	} else {
4256 		name_len = copy_path_name(pSMB->FileName, search_name);
4257 	}
4258 
4259 	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4260 	pSMB->TotalDataCount = 0;
4261 	pSMB->MaxParameterCount = cpu_to_le16(2);
4262 	/* BB find exact max data count below from sess structure BB */
4263 	pSMB->MaxDataCount = cpu_to_le16(4000);
4264 	pSMB->MaxSetupCount = 0;
4265 	pSMB->Reserved = 0;
4266 	pSMB->Flags = 0;
4267 	pSMB->Timeout = 0;
4268 	pSMB->Reserved2 = 0;
4269 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4270 		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4271 	pSMB->DataCount = 0;
4272 	pSMB->DataOffset = 0;
4273 	pSMB->SetupCount = 1;
4274 	pSMB->Reserved3 = 0;
4275 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4276 	byte_count = params + 1 /* pad */ ;
4277 	pSMB->TotalParameterCount = cpu_to_le16(params);
4278 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4279 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4280 	pSMB->Reserved4 = 0;
4281 	inc_rfc1001_len(pSMB, byte_count);
4282 	pSMB->ByteCount = cpu_to_le16(byte_count);
4283 
4284 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4285 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4286 	if (rc) {
4287 		cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4288 	} else {
4289 		/* decode response */
4290 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4291 		/* BB also check enough total bytes returned */
4292 		if (rc || get_bcc(&pSMBr->hdr) < 2)
4293 			/* If rc should we check for EOPNOSUPP and
4294 			disable the srvino flag? or in caller? */
4295 			rc = -EIO;      /* bad smb */
4296 		else {
4297 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4298 			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4299 			struct file_internal_info *pfinfo;
4300 			/* BB Do we need a cast or hash here ? */
4301 			if (count < 8) {
4302 				cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n");
4303 				rc = -EIO;
4304 				goto GetInodeNumOut;
4305 			}
4306 			pfinfo = (struct file_internal_info *)
4307 				(data_offset + (char *) &pSMBr->hdr.Protocol);
4308 			*inode_number = le64_to_cpu(pfinfo->UniqueId);
4309 		}
4310 	}
4311 GetInodeNumOut:
4312 	cifs_buf_release(pSMB);
4313 	if (rc == -EAGAIN)
4314 		goto GetInodeNumberRetry;
4315 	return rc;
4316 }
4317 
4318 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)4319 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4320 		const char *search_name, struct dfs_info3_param **target_nodes,
4321 		unsigned int *num_of_nodes,
4322 		const struct nls_table *nls_codepage, int remap)
4323 {
4324 /* TRANS2_GET_DFS_REFERRAL */
4325 	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4326 	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4327 	int rc = 0;
4328 	int bytes_returned;
4329 	int name_len;
4330 	__u16 params, byte_count;
4331 	*num_of_nodes = 0;
4332 	*target_nodes = NULL;
4333 
4334 	cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4335 	if (ses == NULL || ses->tcon_ipc == NULL)
4336 		return -ENODEV;
4337 
4338 getDFSRetry:
4339 	/*
4340 	 * Use smb_init_no_reconnect() instead of smb_init() as
4341 	 * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
4342 	 * causing an infinite recursion.
4343 	 */
4344 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
4345 				   (void **)&pSMB, (void **)&pSMBr);
4346 	if (rc)
4347 		return rc;
4348 
4349 	/* server pointer checked in called function,
4350 	but should never be null here anyway */
4351 	pSMB->hdr.Mid = get_next_mid(ses->server);
4352 	pSMB->hdr.Tid = ses->tcon_ipc->tid;
4353 	pSMB->hdr.Uid = ses->Suid;
4354 	if (ses->capabilities & CAP_STATUS32)
4355 		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4356 	if (ses->capabilities & CAP_DFS)
4357 		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4358 
4359 	if (ses->capabilities & CAP_UNICODE) {
4360 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4361 		name_len =
4362 		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4363 				       search_name, PATH_MAX, nls_codepage,
4364 				       remap);
4365 		name_len++;	/* trailing null */
4366 		name_len *= 2;
4367 	} else {	/* BB improve the check for buffer overruns BB */
4368 		name_len = copy_path_name(pSMB->RequestFileName, search_name);
4369 	}
4370 
4371 	if (ses->server->sign)
4372 		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4373 
4374 	pSMB->hdr.Uid = ses->Suid;
4375 
4376 	params = 2 /* level */  + name_len /*includes null */ ;
4377 	pSMB->TotalDataCount = 0;
4378 	pSMB->DataCount = 0;
4379 	pSMB->DataOffset = 0;
4380 	pSMB->MaxParameterCount = 0;
4381 	/* BB find exact max SMB PDU from sess structure BB */
4382 	pSMB->MaxDataCount = cpu_to_le16(4000);
4383 	pSMB->MaxSetupCount = 0;
4384 	pSMB->Reserved = 0;
4385 	pSMB->Flags = 0;
4386 	pSMB->Timeout = 0;
4387 	pSMB->Reserved2 = 0;
4388 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4389 	  struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4390 	pSMB->SetupCount = 1;
4391 	pSMB->Reserved3 = 0;
4392 	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4393 	byte_count = params + 3 /* pad */ ;
4394 	pSMB->ParameterCount = cpu_to_le16(params);
4395 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4396 	pSMB->MaxReferralLevel = cpu_to_le16(3);
4397 	inc_rfc1001_len(pSMB, byte_count);
4398 	pSMB->ByteCount = cpu_to_le16(byte_count);
4399 
4400 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4401 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4402 	if (rc) {
4403 		cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4404 		goto GetDFSRefExit;
4405 	}
4406 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4407 
4408 	/* BB Also check if enough total bytes returned? */
4409 	if (rc || get_bcc(&pSMBr->hdr) < 17) {
4410 		rc = -EIO;      /* bad smb */
4411 		goto GetDFSRefExit;
4412 	}
4413 
4414 	cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d  Offset %d\n",
4415 		 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4416 
4417 	/* parse returned result into more usable form */
4418 	rc = parse_dfs_referrals(&pSMBr->dfs_data,
4419 				 le16_to_cpu(pSMBr->t2.DataCount),
4420 				 num_of_nodes, target_nodes, nls_codepage,
4421 				 remap, search_name,
4422 				 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4423 
4424 GetDFSRefExit:
4425 	cifs_buf_release(pSMB);
4426 
4427 	if (rc == -EAGAIN)
4428 		goto getDFSRetry;
4429 
4430 	return rc;
4431 }
4432 
4433 /* Query File System Info such as free space to old servers such as Win 9x */
4434 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4435 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4436 	      struct kstatfs *FSData)
4437 {
4438 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4439 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4440 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4441 	FILE_SYSTEM_ALLOC_INFO *response_data;
4442 	int rc = 0;
4443 	int bytes_returned = 0;
4444 	__u16 params, byte_count;
4445 
4446 	cifs_dbg(FYI, "OldQFSInfo\n");
4447 oldQFSInfoRetry:
4448 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4449 		(void **) &pSMBr);
4450 	if (rc)
4451 		return rc;
4452 
4453 	params = 2;     /* level */
4454 	pSMB->TotalDataCount = 0;
4455 	pSMB->MaxParameterCount = cpu_to_le16(2);
4456 	pSMB->MaxDataCount = cpu_to_le16(1000);
4457 	pSMB->MaxSetupCount = 0;
4458 	pSMB->Reserved = 0;
4459 	pSMB->Flags = 0;
4460 	pSMB->Timeout = 0;
4461 	pSMB->Reserved2 = 0;
4462 	byte_count = params + 1 /* pad */ ;
4463 	pSMB->TotalParameterCount = cpu_to_le16(params);
4464 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4465 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4466 	struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4467 	pSMB->DataCount = 0;
4468 	pSMB->DataOffset = 0;
4469 	pSMB->SetupCount = 1;
4470 	pSMB->Reserved3 = 0;
4471 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4472 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4473 	inc_rfc1001_len(pSMB, byte_count);
4474 	pSMB->ByteCount = cpu_to_le16(byte_count);
4475 
4476 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4477 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
4478 	if (rc) {
4479 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4480 	} else {                /* decode response */
4481 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4482 
4483 		if (rc || get_bcc(&pSMBr->hdr) < 18)
4484 			rc = -EIO;      /* bad smb */
4485 		else {
4486 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4487 			cifs_dbg(FYI, "qfsinf resp BCC: %d  Offset %d\n",
4488 				 get_bcc(&pSMBr->hdr), data_offset);
4489 
4490 			response_data = (FILE_SYSTEM_ALLOC_INFO *)
4491 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
4492 			FSData->f_bsize =
4493 				le16_to_cpu(response_data->BytesPerSector) *
4494 				le32_to_cpu(response_data->
4495 					SectorsPerAllocationUnit);
4496 			/*
4497 			 * much prefer larger but if server doesn't report
4498 			 * a valid size than 4K is a reasonable minimum
4499 			 */
4500 			if (FSData->f_bsize < 512)
4501 				FSData->f_bsize = 4096;
4502 
4503 			FSData->f_blocks =
4504 			       le32_to_cpu(response_data->TotalAllocationUnits);
4505 			FSData->f_bfree = FSData->f_bavail =
4506 				le32_to_cpu(response_data->FreeAllocationUnits);
4507 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4508 				 (unsigned long long)FSData->f_blocks,
4509 				 (unsigned long long)FSData->f_bfree,
4510 				 FSData->f_bsize);
4511 		}
4512 	}
4513 	cifs_buf_release(pSMB);
4514 
4515 	if (rc == -EAGAIN)
4516 		goto oldQFSInfoRetry;
4517 
4518 	return rc;
4519 }
4520 
4521 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4522 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4523 	       struct kstatfs *FSData)
4524 {
4525 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4526 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4527 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4528 	FILE_SYSTEM_INFO *response_data;
4529 	int rc = 0;
4530 	int bytes_returned = 0;
4531 	__u16 params, byte_count;
4532 
4533 	cifs_dbg(FYI, "In QFSInfo\n");
4534 QFSInfoRetry:
4535 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4536 		      (void **) &pSMBr);
4537 	if (rc)
4538 		return rc;
4539 
4540 	params = 2;	/* level */
4541 	pSMB->TotalDataCount = 0;
4542 	pSMB->MaxParameterCount = cpu_to_le16(2);
4543 	pSMB->MaxDataCount = cpu_to_le16(1000);
4544 	pSMB->MaxSetupCount = 0;
4545 	pSMB->Reserved = 0;
4546 	pSMB->Flags = 0;
4547 	pSMB->Timeout = 0;
4548 	pSMB->Reserved2 = 0;
4549 	byte_count = params + 1 /* pad */ ;
4550 	pSMB->TotalParameterCount = cpu_to_le16(params);
4551 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4552 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4553 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4554 	pSMB->DataCount = 0;
4555 	pSMB->DataOffset = 0;
4556 	pSMB->SetupCount = 1;
4557 	pSMB->Reserved3 = 0;
4558 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4559 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4560 	inc_rfc1001_len(pSMB, byte_count);
4561 	pSMB->ByteCount = cpu_to_le16(byte_count);
4562 
4563 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4564 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4565 	if (rc) {
4566 		cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
4567 	} else {		/* decode response */
4568 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4569 
4570 		if (rc || get_bcc(&pSMBr->hdr) < 24)
4571 			rc = -EIO;	/* bad smb */
4572 		else {
4573 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4574 
4575 			response_data =
4576 			    (FILE_SYSTEM_INFO
4577 			     *) (((char *) &pSMBr->hdr.Protocol) +
4578 				 data_offset);
4579 			FSData->f_bsize =
4580 			    le32_to_cpu(response_data->BytesPerSector) *
4581 			    le32_to_cpu(response_data->
4582 					SectorsPerAllocationUnit);
4583 			/*
4584 			 * much prefer larger but if server doesn't report
4585 			 * a valid size than 4K is a reasonable minimum
4586 			 */
4587 			if (FSData->f_bsize < 512)
4588 				FSData->f_bsize = 4096;
4589 
4590 			FSData->f_blocks =
4591 			    le64_to_cpu(response_data->TotalAllocationUnits);
4592 			FSData->f_bfree = FSData->f_bavail =
4593 			    le64_to_cpu(response_data->FreeAllocationUnits);
4594 			cifs_dbg(FYI, "Blocks: %lld  Free: %lld Block size %ld\n",
4595 				 (unsigned long long)FSData->f_blocks,
4596 				 (unsigned long long)FSData->f_bfree,
4597 				 FSData->f_bsize);
4598 		}
4599 	}
4600 	cifs_buf_release(pSMB);
4601 
4602 	if (rc == -EAGAIN)
4603 		goto QFSInfoRetry;
4604 
4605 	return rc;
4606 }
4607 
4608 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)4609 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
4610 {
4611 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4612 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4613 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4614 	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4615 	int rc = 0;
4616 	int bytes_returned = 0;
4617 	__u16 params, byte_count;
4618 
4619 	cifs_dbg(FYI, "In QFSAttributeInfo\n");
4620 QFSAttributeRetry:
4621 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4622 		      (void **) &pSMBr);
4623 	if (rc)
4624 		return rc;
4625 
4626 	params = 2;	/* level */
4627 	pSMB->TotalDataCount = 0;
4628 	pSMB->MaxParameterCount = cpu_to_le16(2);
4629 	/* BB find exact max SMB PDU from sess structure BB */
4630 	pSMB->MaxDataCount = cpu_to_le16(1000);
4631 	pSMB->MaxSetupCount = 0;
4632 	pSMB->Reserved = 0;
4633 	pSMB->Flags = 0;
4634 	pSMB->Timeout = 0;
4635 	pSMB->Reserved2 = 0;
4636 	byte_count = params + 1 /* pad */ ;
4637 	pSMB->TotalParameterCount = cpu_to_le16(params);
4638 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4639 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4640 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4641 	pSMB->DataCount = 0;
4642 	pSMB->DataOffset = 0;
4643 	pSMB->SetupCount = 1;
4644 	pSMB->Reserved3 = 0;
4645 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4646 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4647 	inc_rfc1001_len(pSMB, byte_count);
4648 	pSMB->ByteCount = cpu_to_le16(byte_count);
4649 
4650 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4651 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4652 	if (rc) {
4653 		cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
4654 	} else {		/* decode response */
4655 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4656 
4657 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
4658 			/* BB also check if enough bytes returned */
4659 			rc = -EIO;	/* bad smb */
4660 		} else {
4661 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4662 			response_data =
4663 			    (FILE_SYSTEM_ATTRIBUTE_INFO
4664 			     *) (((char *) &pSMBr->hdr.Protocol) +
4665 				 data_offset);
4666 			memcpy(&tcon->fsAttrInfo, response_data,
4667 			       sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4668 		}
4669 	}
4670 	cifs_buf_release(pSMB);
4671 
4672 	if (rc == -EAGAIN)
4673 		goto QFSAttributeRetry;
4674 
4675 	return rc;
4676 }
4677 
4678 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)4679 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
4680 {
4681 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4682 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4683 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4684 	FILE_SYSTEM_DEVICE_INFO *response_data;
4685 	int rc = 0;
4686 	int bytes_returned = 0;
4687 	__u16 params, byte_count;
4688 
4689 	cifs_dbg(FYI, "In QFSDeviceInfo\n");
4690 QFSDeviceRetry:
4691 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4692 		      (void **) &pSMBr);
4693 	if (rc)
4694 		return rc;
4695 
4696 	params = 2;	/* level */
4697 	pSMB->TotalDataCount = 0;
4698 	pSMB->MaxParameterCount = cpu_to_le16(2);
4699 	/* BB find exact max SMB PDU from sess structure BB */
4700 	pSMB->MaxDataCount = cpu_to_le16(1000);
4701 	pSMB->MaxSetupCount = 0;
4702 	pSMB->Reserved = 0;
4703 	pSMB->Flags = 0;
4704 	pSMB->Timeout = 0;
4705 	pSMB->Reserved2 = 0;
4706 	byte_count = params + 1 /* pad */ ;
4707 	pSMB->TotalParameterCount = cpu_to_le16(params);
4708 	pSMB->ParameterCount = pSMB->TotalParameterCount;
4709 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
4710 		struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4711 
4712 	pSMB->DataCount = 0;
4713 	pSMB->DataOffset = 0;
4714 	pSMB->SetupCount = 1;
4715 	pSMB->Reserved3 = 0;
4716 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4717 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4718 	inc_rfc1001_len(pSMB, byte_count);
4719 	pSMB->ByteCount = cpu_to_le16(byte_count);
4720 
4721 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4722 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4723 	if (rc) {
4724 		cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
4725 	} else {		/* decode response */
4726 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4727 
4728 		if (rc || get_bcc(&pSMBr->hdr) <
4729 			  sizeof(FILE_SYSTEM_DEVICE_INFO))
4730 			rc = -EIO;	/* bad smb */
4731 		else {
4732 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4733 			response_data =
4734 			    (FILE_SYSTEM_DEVICE_INFO *)
4735 				(((char *) &pSMBr->hdr.Protocol) +
4736 				 data_offset);
4737 			memcpy(&tcon->fsDevInfo, response_data,
4738 			       sizeof(FILE_SYSTEM_DEVICE_INFO));
4739 		}
4740 	}
4741 	cifs_buf_release(pSMB);
4742 
4743 	if (rc == -EAGAIN)
4744 		goto QFSDeviceRetry;
4745 
4746 	return rc;
4747 }
4748 
4749 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)4750 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
4751 {
4752 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4753 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4754 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4755 	FILE_SYSTEM_UNIX_INFO *response_data;
4756 	int rc = 0;
4757 	int bytes_returned = 0;
4758 	__u16 params, byte_count;
4759 
4760 	cifs_dbg(FYI, "In QFSUnixInfo\n");
4761 QFSUnixRetry:
4762 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4763 				   (void **) &pSMB, (void **) &pSMBr);
4764 	if (rc)
4765 		return rc;
4766 
4767 	params = 2;	/* level */
4768 	pSMB->TotalDataCount = 0;
4769 	pSMB->DataCount = 0;
4770 	pSMB->DataOffset = 0;
4771 	pSMB->MaxParameterCount = cpu_to_le16(2);
4772 	/* BB find exact max SMB PDU from sess structure BB */
4773 	pSMB->MaxDataCount = cpu_to_le16(100);
4774 	pSMB->MaxSetupCount = 0;
4775 	pSMB->Reserved = 0;
4776 	pSMB->Flags = 0;
4777 	pSMB->Timeout = 0;
4778 	pSMB->Reserved2 = 0;
4779 	byte_count = params + 1 /* pad */ ;
4780 	pSMB->ParameterCount = cpu_to_le16(params);
4781 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4782 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4783 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4784 	pSMB->SetupCount = 1;
4785 	pSMB->Reserved3 = 0;
4786 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4787 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4788 	inc_rfc1001_len(pSMB, byte_count);
4789 	pSMB->ByteCount = cpu_to_le16(byte_count);
4790 
4791 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4792 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4793 	if (rc) {
4794 		cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
4795 	} else {		/* decode response */
4796 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4797 
4798 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
4799 			rc = -EIO;	/* bad smb */
4800 		} else {
4801 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4802 			response_data =
4803 			    (FILE_SYSTEM_UNIX_INFO
4804 			     *) (((char *) &pSMBr->hdr.Protocol) +
4805 				 data_offset);
4806 			memcpy(&tcon->fsUnixInfo, response_data,
4807 			       sizeof(FILE_SYSTEM_UNIX_INFO));
4808 		}
4809 	}
4810 	cifs_buf_release(pSMB);
4811 
4812 	if (rc == -EAGAIN)
4813 		goto QFSUnixRetry;
4814 
4815 
4816 	return rc;
4817 }
4818 
4819 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)4820 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
4821 {
4822 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4823 	TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4824 	TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4825 	int rc = 0;
4826 	int bytes_returned = 0;
4827 	__u16 params, param_offset, offset, byte_count;
4828 
4829 	cifs_dbg(FYI, "In SETFSUnixInfo\n");
4830 SETFSUnixRetry:
4831 	/* BB switch to small buf init to save memory */
4832 	rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4833 					(void **) &pSMB, (void **) &pSMBr);
4834 	if (rc)
4835 		return rc;
4836 
4837 	params = 4;	/* 2 bytes zero followed by info level. */
4838 	pSMB->MaxSetupCount = 0;
4839 	pSMB->Reserved = 0;
4840 	pSMB->Flags = 0;
4841 	pSMB->Timeout = 0;
4842 	pSMB->Reserved2 = 0;
4843 	param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4844 				- 4;
4845 	offset = param_offset + params;
4846 
4847 	pSMB->MaxParameterCount = cpu_to_le16(4);
4848 	/* BB find exact max SMB PDU from sess structure BB */
4849 	pSMB->MaxDataCount = cpu_to_le16(100);
4850 	pSMB->SetupCount = 1;
4851 	pSMB->Reserved3 = 0;
4852 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4853 	byte_count = 1 /* pad */ + params + 12;
4854 
4855 	pSMB->DataCount = cpu_to_le16(12);
4856 	pSMB->ParameterCount = cpu_to_le16(params);
4857 	pSMB->TotalDataCount = pSMB->DataCount;
4858 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4859 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
4860 	pSMB->DataOffset = cpu_to_le16(offset);
4861 
4862 	/* Params. */
4863 	pSMB->FileNum = 0;
4864 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4865 
4866 	/* Data. */
4867 	pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4868 	pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4869 	pSMB->ClientUnixCap = cpu_to_le64(cap);
4870 
4871 	inc_rfc1001_len(pSMB, byte_count);
4872 	pSMB->ByteCount = cpu_to_le16(byte_count);
4873 
4874 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4875 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4876 	if (rc) {
4877 		cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
4878 	} else {		/* decode response */
4879 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4880 		if (rc)
4881 			rc = -EIO;	/* bad smb */
4882 	}
4883 	cifs_buf_release(pSMB);
4884 
4885 	if (rc == -EAGAIN)
4886 		goto SETFSUnixRetry;
4887 
4888 	return rc;
4889 }
4890 
4891 
4892 
4893 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4894 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
4895 		   struct kstatfs *FSData)
4896 {
4897 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
4898 	TRANSACTION2_QFSI_REQ *pSMB = NULL;
4899 	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4900 	FILE_SYSTEM_POSIX_INFO *response_data;
4901 	int rc = 0;
4902 	int bytes_returned = 0;
4903 	__u16 params, byte_count;
4904 
4905 	cifs_dbg(FYI, "In QFSPosixInfo\n");
4906 QFSPosixRetry:
4907 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4908 		      (void **) &pSMBr);
4909 	if (rc)
4910 		return rc;
4911 
4912 	params = 2;	/* level */
4913 	pSMB->TotalDataCount = 0;
4914 	pSMB->DataCount = 0;
4915 	pSMB->DataOffset = 0;
4916 	pSMB->MaxParameterCount = cpu_to_le16(2);
4917 	/* BB find exact max SMB PDU from sess structure BB */
4918 	pSMB->MaxDataCount = cpu_to_le16(100);
4919 	pSMB->MaxSetupCount = 0;
4920 	pSMB->Reserved = 0;
4921 	pSMB->Flags = 0;
4922 	pSMB->Timeout = 0;
4923 	pSMB->Reserved2 = 0;
4924 	byte_count = params + 1 /* pad */ ;
4925 	pSMB->ParameterCount = cpu_to_le16(params);
4926 	pSMB->TotalParameterCount = pSMB->ParameterCount;
4927 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4928 			smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4929 	pSMB->SetupCount = 1;
4930 	pSMB->Reserved3 = 0;
4931 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4932 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4933 	inc_rfc1001_len(pSMB, byte_count);
4934 	pSMB->ByteCount = cpu_to_le16(byte_count);
4935 
4936 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4937 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4938 	if (rc) {
4939 		cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
4940 	} else {		/* decode response */
4941 		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4942 
4943 		if (rc || get_bcc(&pSMBr->hdr) < 13) {
4944 			rc = -EIO;	/* bad smb */
4945 		} else {
4946 			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4947 			response_data =
4948 			    (FILE_SYSTEM_POSIX_INFO
4949 			     *) (((char *) &pSMBr->hdr.Protocol) +
4950 				 data_offset);
4951 			FSData->f_bsize =
4952 					le32_to_cpu(response_data->BlockSize);
4953 			/*
4954 			 * much prefer larger but if server doesn't report
4955 			 * a valid size than 4K is a reasonable minimum
4956 			 */
4957 			if (FSData->f_bsize < 512)
4958 				FSData->f_bsize = 4096;
4959 
4960 			FSData->f_blocks =
4961 					le64_to_cpu(response_data->TotalBlocks);
4962 			FSData->f_bfree =
4963 			    le64_to_cpu(response_data->BlocksAvail);
4964 			if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4965 				FSData->f_bavail = FSData->f_bfree;
4966 			} else {
4967 				FSData->f_bavail =
4968 				    le64_to_cpu(response_data->UserBlocksAvail);
4969 			}
4970 			if (response_data->TotalFileNodes != cpu_to_le64(-1))
4971 				FSData->f_files =
4972 				     le64_to_cpu(response_data->TotalFileNodes);
4973 			if (response_data->FreeFileNodes != cpu_to_le64(-1))
4974 				FSData->f_ffree =
4975 				      le64_to_cpu(response_data->FreeFileNodes);
4976 		}
4977 	}
4978 	cifs_buf_release(pSMB);
4979 
4980 	if (rc == -EAGAIN)
4981 		goto QFSPosixRetry;
4982 
4983 	return rc;
4984 }
4985 
4986 
4987 /*
4988  * We can not use write of zero bytes trick to set file size due to need for
4989  * large file support. Also note that this SetPathInfo is preferred to
4990  * SetFileInfo based method in next routine which is only needed to work around
4991  * a sharing violation bugin Samba which this routine can run into.
4992  */
4993 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)4994 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
4995 	      const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
4996 	      bool set_allocation, struct dentry *dentry)
4997 {
4998 	struct smb_com_transaction2_spi_req *pSMB = NULL;
4999 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5000 	struct file_end_of_file_info *parm_data;
5001 	int name_len;
5002 	int rc = 0;
5003 	int bytes_returned = 0;
5004 	int remap = cifs_remap(cifs_sb);
5005 
5006 	__u16 params, byte_count, data_count, param_offset, offset;
5007 
5008 	cifs_dbg(FYI, "In SetEOF\n");
5009 SetEOFRetry:
5010 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5011 		      (void **) &pSMBr);
5012 	if (rc)
5013 		return rc;
5014 
5015 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5016 		name_len =
5017 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5018 				       PATH_MAX, cifs_sb->local_nls, remap);
5019 		name_len++;	/* trailing null */
5020 		name_len *= 2;
5021 	} else {
5022 		name_len = copy_path_name(pSMB->FileName, file_name);
5023 	}
5024 	params = 6 + name_len;
5025 	data_count = sizeof(struct file_end_of_file_info);
5026 	pSMB->MaxParameterCount = cpu_to_le16(2);
5027 	pSMB->MaxDataCount = cpu_to_le16(4100);
5028 	pSMB->MaxSetupCount = 0;
5029 	pSMB->Reserved = 0;
5030 	pSMB->Flags = 0;
5031 	pSMB->Timeout = 0;
5032 	pSMB->Reserved2 = 0;
5033 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5034 				InformationLevel) - 4;
5035 	offset = param_offset + params;
5036 	if (set_allocation) {
5037 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5038 			pSMB->InformationLevel =
5039 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5040 		else
5041 			pSMB->InformationLevel =
5042 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5043 	} else /* Set File Size */  {
5044 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5045 		    pSMB->InformationLevel =
5046 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5047 	    else
5048 		    pSMB->InformationLevel =
5049 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5050 	}
5051 
5052 	parm_data =
5053 	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5054 				       offset);
5055 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5056 	pSMB->DataOffset = cpu_to_le16(offset);
5057 	pSMB->SetupCount = 1;
5058 	pSMB->Reserved3 = 0;
5059 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5060 	byte_count = 3 /* pad */  + params + data_count;
5061 	pSMB->DataCount = cpu_to_le16(data_count);
5062 	pSMB->TotalDataCount = pSMB->DataCount;
5063 	pSMB->ParameterCount = cpu_to_le16(params);
5064 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5065 	pSMB->Reserved4 = 0;
5066 	inc_rfc1001_len(pSMB, byte_count);
5067 	parm_data->FileSize = cpu_to_le64(size);
5068 	pSMB->ByteCount = cpu_to_le16(byte_count);
5069 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5070 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5071 	if (rc)
5072 		cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5073 
5074 	cifs_buf_release(pSMB);
5075 
5076 	if (rc == -EAGAIN)
5077 		goto SetEOFRetry;
5078 
5079 	return rc;
5080 }
5081 
5082 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5083 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5084 		   struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5085 {
5086 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5087 	struct file_end_of_file_info *parm_data;
5088 	int rc = 0;
5089 	__u16 params, param_offset, offset, byte_count, count;
5090 
5091 	cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5092 		 (long long)size);
5093 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5094 
5095 	if (rc)
5096 		return rc;
5097 
5098 	pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5099 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5100 
5101 	params = 6;
5102 	pSMB->MaxSetupCount = 0;
5103 	pSMB->Reserved = 0;
5104 	pSMB->Flags = 0;
5105 	pSMB->Timeout = 0;
5106 	pSMB->Reserved2 = 0;
5107 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5108 	offset = param_offset + params;
5109 
5110 	count = sizeof(struct file_end_of_file_info);
5111 	pSMB->MaxParameterCount = cpu_to_le16(2);
5112 	/* BB find exact max SMB PDU from sess structure BB */
5113 	pSMB->MaxDataCount = cpu_to_le16(1000);
5114 	pSMB->SetupCount = 1;
5115 	pSMB->Reserved3 = 0;
5116 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5117 	byte_count = 3 /* pad */  + params + count;
5118 	pSMB->DataCount = cpu_to_le16(count);
5119 	pSMB->ParameterCount = cpu_to_le16(params);
5120 	pSMB->TotalDataCount = pSMB->DataCount;
5121 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5122 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5123 	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5124 	parm_data =
5125 		(struct file_end_of_file_info *)(((char *)pSMB) + offset + 4);
5126 	pSMB->DataOffset = cpu_to_le16(offset);
5127 	parm_data->FileSize = cpu_to_le64(size);
5128 	pSMB->Fid = cfile->fid.netfid;
5129 	if (set_allocation) {
5130 		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5131 			pSMB->InformationLevel =
5132 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5133 		else
5134 			pSMB->InformationLevel =
5135 				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5136 	} else /* Set File Size */  {
5137 	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5138 		    pSMB->InformationLevel =
5139 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5140 	    else
5141 		    pSMB->InformationLevel =
5142 				cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5143 	}
5144 	pSMB->Reserved4 = 0;
5145 	inc_rfc1001_len(pSMB, byte_count);
5146 	pSMB->ByteCount = cpu_to_le16(byte_count);
5147 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5148 	cifs_small_buf_release(pSMB);
5149 	if (rc) {
5150 		cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5151 			 rc);
5152 	}
5153 
5154 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5155 		since file handle passed in no longer valid */
5156 
5157 	return rc;
5158 }
5159 
5160 /* Some legacy servers such as NT4 require that the file times be set on
5161    an open handle, rather than by pathname - this is awkward due to
5162    potential access conflicts on the open, but it is unavoidable for these
5163    old servers since the only other choice is to go from 100 nanosecond DCE
5164    time and resort to the original setpathinfo level which takes the ancient
5165    DOS time format with 2 second granularity */
5166 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5167 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5168 		    const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5169 {
5170 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5171 	char *data_offset;
5172 	int rc = 0;
5173 	__u16 params, param_offset, offset, byte_count, count;
5174 
5175 	cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5176 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5177 
5178 	if (rc)
5179 		return rc;
5180 
5181 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5182 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5183 
5184 	params = 6;
5185 	pSMB->MaxSetupCount = 0;
5186 	pSMB->Reserved = 0;
5187 	pSMB->Flags = 0;
5188 	pSMB->Timeout = 0;
5189 	pSMB->Reserved2 = 0;
5190 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5191 	offset = param_offset + params;
5192 
5193 	data_offset = (char *)pSMB +
5194 			offsetof(struct smb_hdr, Protocol) + offset;
5195 
5196 	count = sizeof(FILE_BASIC_INFO);
5197 	pSMB->MaxParameterCount = cpu_to_le16(2);
5198 	/* BB find max SMB PDU from sess */
5199 	pSMB->MaxDataCount = cpu_to_le16(1000);
5200 	pSMB->SetupCount = 1;
5201 	pSMB->Reserved3 = 0;
5202 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5203 	byte_count = 3 /* pad */  + params + count;
5204 	pSMB->DataCount = cpu_to_le16(count);
5205 	pSMB->ParameterCount = cpu_to_le16(params);
5206 	pSMB->TotalDataCount = pSMB->DataCount;
5207 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5208 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5209 	pSMB->DataOffset = cpu_to_le16(offset);
5210 	pSMB->Fid = fid;
5211 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5212 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5213 	else
5214 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5215 	pSMB->Reserved4 = 0;
5216 	inc_rfc1001_len(pSMB, byte_count);
5217 	pSMB->ByteCount = cpu_to_le16(byte_count);
5218 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5219 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5220 	cifs_small_buf_release(pSMB);
5221 	if (rc)
5222 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5223 			 rc);
5224 
5225 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5226 		since file handle passed in no longer valid */
5227 
5228 	return rc;
5229 }
5230 
5231 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5232 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5233 			  bool delete_file, __u16 fid, __u32 pid_of_opener)
5234 {
5235 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5236 	char *data_offset;
5237 	int rc = 0;
5238 	__u16 params, param_offset, offset, byte_count, count;
5239 
5240 	cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5241 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5242 
5243 	if (rc)
5244 		return rc;
5245 
5246 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5247 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5248 
5249 	params = 6;
5250 	pSMB->MaxSetupCount = 0;
5251 	pSMB->Reserved = 0;
5252 	pSMB->Flags = 0;
5253 	pSMB->Timeout = 0;
5254 	pSMB->Reserved2 = 0;
5255 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5256 	offset = param_offset + params;
5257 
5258 	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5259 	data_offset = (char *)(pSMB) + offset + 4;
5260 
5261 	count = 1;
5262 	pSMB->MaxParameterCount = cpu_to_le16(2);
5263 	/* BB find max SMB PDU from sess */
5264 	pSMB->MaxDataCount = cpu_to_le16(1000);
5265 	pSMB->SetupCount = 1;
5266 	pSMB->Reserved3 = 0;
5267 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5268 	byte_count = 3 /* pad */  + params + count;
5269 	pSMB->DataCount = cpu_to_le16(count);
5270 	pSMB->ParameterCount = cpu_to_le16(params);
5271 	pSMB->TotalDataCount = pSMB->DataCount;
5272 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5273 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5274 	pSMB->DataOffset = cpu_to_le16(offset);
5275 	pSMB->Fid = fid;
5276 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5277 	pSMB->Reserved4 = 0;
5278 	inc_rfc1001_len(pSMB, byte_count);
5279 	pSMB->ByteCount = cpu_to_le16(byte_count);
5280 	*data_offset = delete_file ? 1 : 0;
5281 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5282 	cifs_small_buf_release(pSMB);
5283 	if (rc)
5284 		cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5285 
5286 	return rc;
5287 }
5288 
5289 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)5290 CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5291 		     const char *fileName, const FILE_BASIC_INFO *data,
5292 		     const struct nls_table *nls_codepage,
5293 		     struct cifs_sb_info *cifs_sb)
5294 {
5295 	int oplock = 0;
5296 	struct cifs_open_parms oparms;
5297 	struct cifs_fid fid;
5298 	int rc;
5299 
5300 	oparms = (struct cifs_open_parms) {
5301 		.tcon = tcon,
5302 		.cifs_sb = cifs_sb,
5303 		.desired_access = GENERIC_WRITE,
5304 		.create_options = cifs_create_options(cifs_sb, 0),
5305 		.disposition = FILE_OPEN,
5306 		.path = fileName,
5307 		.fid = &fid,
5308 	};
5309 
5310 	rc = CIFS_open(xid, &oparms, &oplock, NULL);
5311 	if (rc)
5312 		goto out;
5313 
5314 	rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5315 	CIFSSMBClose(xid, tcon, fid.netfid);
5316 out:
5317 
5318 	return rc;
5319 }
5320 
5321 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)5322 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5323 		   const char *fileName, const FILE_BASIC_INFO *data,
5324 		   const struct nls_table *nls_codepage,
5325 		     struct cifs_sb_info *cifs_sb)
5326 {
5327 	TRANSACTION2_SPI_REQ *pSMB = NULL;
5328 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5329 	int name_len;
5330 	int rc = 0;
5331 	int bytes_returned = 0;
5332 	char *data_offset;
5333 	__u16 params, param_offset, offset, byte_count, count;
5334 	int remap = cifs_remap(cifs_sb);
5335 
5336 	cifs_dbg(FYI, "In SetTimes\n");
5337 
5338 SetTimesRetry:
5339 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5340 		      (void **) &pSMBr);
5341 	if (rc)
5342 		return rc;
5343 
5344 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5345 		name_len =
5346 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5347 				       PATH_MAX, nls_codepage, remap);
5348 		name_len++;	/* trailing null */
5349 		name_len *= 2;
5350 	} else {
5351 		name_len = copy_path_name(pSMB->FileName, fileName);
5352 	}
5353 
5354 	params = 6 + name_len;
5355 	count = sizeof(FILE_BASIC_INFO);
5356 	pSMB->MaxParameterCount = cpu_to_le16(2);
5357 	/* BB find max SMB PDU from sess structure BB */
5358 	pSMB->MaxDataCount = cpu_to_le16(1000);
5359 	pSMB->MaxSetupCount = 0;
5360 	pSMB->Reserved = 0;
5361 	pSMB->Flags = 0;
5362 	pSMB->Timeout = 0;
5363 	pSMB->Reserved2 = 0;
5364 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5365 				InformationLevel) - 4;
5366 	offset = param_offset + params;
5367 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5368 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5369 	pSMB->DataOffset = cpu_to_le16(offset);
5370 	pSMB->SetupCount = 1;
5371 	pSMB->Reserved3 = 0;
5372 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5373 	byte_count = 3 /* pad */  + params + count;
5374 
5375 	pSMB->DataCount = cpu_to_le16(count);
5376 	pSMB->ParameterCount = cpu_to_le16(params);
5377 	pSMB->TotalDataCount = pSMB->DataCount;
5378 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5379 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5380 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5381 	else
5382 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5383 	pSMB->Reserved4 = 0;
5384 	inc_rfc1001_len(pSMB, byte_count);
5385 	memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5386 	pSMB->ByteCount = cpu_to_le16(byte_count);
5387 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5388 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5389 	if (rc)
5390 		cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5391 
5392 	cifs_buf_release(pSMB);
5393 
5394 	if (rc == -EAGAIN)
5395 		goto SetTimesRetry;
5396 
5397 	if (rc == -EOPNOTSUPP)
5398 		return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5399 					    nls_codepage, cifs_sb);
5400 
5401 	return rc;
5402 }
5403 
5404 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5405 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5406 			const struct cifs_unix_set_info_args *args)
5407 {
5408 	u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5409 	u64 mode = args->mode;
5410 
5411 	if (uid_valid(args->uid))
5412 		uid = from_kuid(&init_user_ns, args->uid);
5413 	if (gid_valid(args->gid))
5414 		gid = from_kgid(&init_user_ns, args->gid);
5415 
5416 	/*
5417 	 * Samba server ignores set of file size to zero due to bugs in some
5418 	 * older clients, but we should be precise - we use SetFileSize to
5419 	 * set file size and do not want to truncate file size to zero
5420 	 * accidentally as happened on one Samba server beta by putting
5421 	 * zero instead of -1 here
5422 	 */
5423 	data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5424 	data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5425 	data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5426 	data_offset->LastAccessTime = cpu_to_le64(args->atime);
5427 	data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5428 	data_offset->Uid = cpu_to_le64(uid);
5429 	data_offset->Gid = cpu_to_le64(gid);
5430 	/* better to leave device as zero when it is  */
5431 	data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5432 	data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5433 	data_offset->Permissions = cpu_to_le64(mode);
5434 
5435 	if (S_ISREG(mode))
5436 		data_offset->Type = cpu_to_le32(UNIX_FILE);
5437 	else if (S_ISDIR(mode))
5438 		data_offset->Type = cpu_to_le32(UNIX_DIR);
5439 	else if (S_ISLNK(mode))
5440 		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5441 	else if (S_ISCHR(mode))
5442 		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5443 	else if (S_ISBLK(mode))
5444 		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5445 	else if (S_ISFIFO(mode))
5446 		data_offset->Type = cpu_to_le32(UNIX_FIFO);
5447 	else if (S_ISSOCK(mode))
5448 		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5449 }
5450 
5451 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)5452 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5453 		       const struct cifs_unix_set_info_args *args,
5454 		       u16 fid, u32 pid_of_opener)
5455 {
5456 	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5457 	char *data_offset;
5458 	int rc = 0;
5459 	u16 params, param_offset, offset, byte_count, count;
5460 
5461 	cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5462 	rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5463 
5464 	if (rc)
5465 		return rc;
5466 
5467 	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5468 	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5469 
5470 	params = 6;
5471 	pSMB->MaxSetupCount = 0;
5472 	pSMB->Reserved = 0;
5473 	pSMB->Flags = 0;
5474 	pSMB->Timeout = 0;
5475 	pSMB->Reserved2 = 0;
5476 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5477 	offset = param_offset + params;
5478 
5479 	data_offset = (char *)pSMB +
5480 			offsetof(struct smb_hdr, Protocol) + offset;
5481 
5482 	count = sizeof(FILE_UNIX_BASIC_INFO);
5483 
5484 	pSMB->MaxParameterCount = cpu_to_le16(2);
5485 	/* BB find max SMB PDU from sess */
5486 	pSMB->MaxDataCount = cpu_to_le16(1000);
5487 	pSMB->SetupCount = 1;
5488 	pSMB->Reserved3 = 0;
5489 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5490 	byte_count = 3 /* pad */  + params + count;
5491 	pSMB->DataCount = cpu_to_le16(count);
5492 	pSMB->ParameterCount = cpu_to_le16(params);
5493 	pSMB->TotalDataCount = pSMB->DataCount;
5494 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5495 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5496 	pSMB->DataOffset = cpu_to_le16(offset);
5497 	pSMB->Fid = fid;
5498 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5499 	pSMB->Reserved4 = 0;
5500 	inc_rfc1001_len(pSMB, byte_count);
5501 	pSMB->ByteCount = cpu_to_le16(byte_count);
5502 
5503 	cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5504 
5505 	rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5506 	cifs_small_buf_release(pSMB);
5507 	if (rc)
5508 		cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5509 			 rc);
5510 
5511 	/* Note: On -EAGAIN error only caller can retry on handle based calls
5512 		since file handle passed in no longer valid */
5513 
5514 	return rc;
5515 }
5516 
5517 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)5518 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5519 		       const char *file_name,
5520 		       const struct cifs_unix_set_info_args *args,
5521 		       const struct nls_table *nls_codepage, int remap)
5522 {
5523 	TRANSACTION2_SPI_REQ *pSMB = NULL;
5524 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
5525 	int name_len;
5526 	int rc = 0;
5527 	int bytes_returned = 0;
5528 	FILE_UNIX_BASIC_INFO *data_offset;
5529 	__u16 params, param_offset, offset, count, byte_count;
5530 
5531 	cifs_dbg(FYI, "In SetUID/GID/Mode\n");
5532 setPermsRetry:
5533 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5534 		      (void **) &pSMBr);
5535 	if (rc)
5536 		return rc;
5537 
5538 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5539 		name_len =
5540 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5541 				       PATH_MAX, nls_codepage, remap);
5542 		name_len++;	/* trailing null */
5543 		name_len *= 2;
5544 	} else {
5545 		name_len = copy_path_name(pSMB->FileName, file_name);
5546 	}
5547 
5548 	params = 6 + name_len;
5549 	count = sizeof(FILE_UNIX_BASIC_INFO);
5550 	pSMB->MaxParameterCount = cpu_to_le16(2);
5551 	/* BB find max SMB PDU from sess structure BB */
5552 	pSMB->MaxDataCount = cpu_to_le16(1000);
5553 	pSMB->MaxSetupCount = 0;
5554 	pSMB->Reserved = 0;
5555 	pSMB->Flags = 0;
5556 	pSMB->Timeout = 0;
5557 	pSMB->Reserved2 = 0;
5558 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5559 				InformationLevel) - 4;
5560 	offset = param_offset + params;
5561 	/* SMB offsets are from the beginning of SMB which is 4 bytes in, after RFC1001 field */
5562 	data_offset = (FILE_UNIX_BASIC_INFO *)((char *) pSMB + offset + 4);
5563 	memset(data_offset, 0, count);
5564 	pSMB->DataOffset = cpu_to_le16(offset);
5565 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5566 	pSMB->SetupCount = 1;
5567 	pSMB->Reserved3 = 0;
5568 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5569 	byte_count = 3 /* pad */  + params + count;
5570 	pSMB->ParameterCount = cpu_to_le16(params);
5571 	pSMB->DataCount = cpu_to_le16(count);
5572 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5573 	pSMB->TotalDataCount = pSMB->DataCount;
5574 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5575 	pSMB->Reserved4 = 0;
5576 	inc_rfc1001_len(pSMB, byte_count);
5577 
5578 	cifs_fill_unix_set_info(data_offset, args);
5579 
5580 	pSMB->ByteCount = cpu_to_le16(byte_count);
5581 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5582 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5583 	if (rc)
5584 		cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
5585 
5586 	cifs_buf_release(pSMB);
5587 	if (rc == -EAGAIN)
5588 		goto setPermsRetry;
5589 	return rc;
5590 }
5591 
5592 #ifdef CONFIG_CIFS_XATTR
5593 /*
5594  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5595  * function used by listxattr and getxattr type calls. When ea_name is set,
5596  * it looks for that attribute name and stuffs that value into the EAData
5597  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5598  * buffer. In both cases, the return value is either the length of the
5599  * resulting data or a negative error code. If EAData is a NULL pointer then
5600  * the data isn't copied to it, but the length is returned.
5601  */
5602 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)5603 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
5604 		const unsigned char *searchName, const unsigned char *ea_name,
5605 		char *EAData, size_t buf_size,
5606 		struct cifs_sb_info *cifs_sb)
5607 {
5608 		/* BB assumes one setup word */
5609 	TRANSACTION2_QPI_REQ *pSMB = NULL;
5610 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
5611 	int remap = cifs_remap(cifs_sb);
5612 	struct nls_table *nls_codepage = cifs_sb->local_nls;
5613 	int rc = 0;
5614 	int bytes_returned;
5615 	int list_len;
5616 	struct fealist *ea_response_data;
5617 	struct fea *temp_fea;
5618 	char *temp_ptr;
5619 	char *end_of_smb;
5620 	__u16 params, byte_count, data_offset;
5621 	unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
5622 
5623 	cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
5624 QAllEAsRetry:
5625 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5626 		      (void **) &pSMBr);
5627 	if (rc)
5628 		return rc;
5629 
5630 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5631 		list_len =
5632 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
5633 				       PATH_MAX, nls_codepage, remap);
5634 		list_len++;	/* trailing null */
5635 		list_len *= 2;
5636 	} else {
5637 		list_len = copy_path_name(pSMB->FileName, searchName);
5638 	}
5639 
5640 	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5641 	pSMB->TotalDataCount = 0;
5642 	pSMB->MaxParameterCount = cpu_to_le16(2);
5643 	/* BB find exact max SMB PDU from sess structure BB */
5644 	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5645 	pSMB->MaxSetupCount = 0;
5646 	pSMB->Reserved = 0;
5647 	pSMB->Flags = 0;
5648 	pSMB->Timeout = 0;
5649 	pSMB->Reserved2 = 0;
5650 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
5651 	struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5652 	pSMB->DataCount = 0;
5653 	pSMB->DataOffset = 0;
5654 	pSMB->SetupCount = 1;
5655 	pSMB->Reserved3 = 0;
5656 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5657 	byte_count = params + 1 /* pad */ ;
5658 	pSMB->TotalParameterCount = cpu_to_le16(params);
5659 	pSMB->ParameterCount = pSMB->TotalParameterCount;
5660 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5661 	pSMB->Reserved4 = 0;
5662 	inc_rfc1001_len(pSMB, byte_count);
5663 	pSMB->ByteCount = cpu_to_le16(byte_count);
5664 
5665 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5666 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5667 	if (rc) {
5668 		cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
5669 		goto QAllEAsOut;
5670 	}
5671 
5672 
5673 	/* BB also check enough total bytes returned */
5674 	/* BB we need to improve the validity checking
5675 	of these trans2 responses */
5676 
5677 	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5678 	if (rc || get_bcc(&pSMBr->hdr) < 4) {
5679 		rc = -EIO;	/* bad smb */
5680 		goto QAllEAsOut;
5681 	}
5682 
5683 	/* check that length of list is not more than bcc */
5684 	/* check that each entry does not go beyond length
5685 	   of list */
5686 	/* check that each element of each entry does not
5687 	   go beyond end of list */
5688 	/* validate_trans2_offsets() */
5689 	/* BB check if start of smb + data_offset > &bcc+ bcc */
5690 
5691 	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5692 	ea_response_data = (struct fealist *)
5693 				(((char *) &pSMBr->hdr.Protocol) + data_offset);
5694 
5695 	list_len = le32_to_cpu(ea_response_data->list_len);
5696 	cifs_dbg(FYI, "ea length %d\n", list_len);
5697 	if (list_len <= 8) {
5698 		cifs_dbg(FYI, "empty EA list returned from server\n");
5699 		/* didn't find the named attribute */
5700 		if (ea_name)
5701 			rc = -ENODATA;
5702 		goto QAllEAsOut;
5703 	}
5704 
5705 	/* make sure list_len doesn't go past end of SMB */
5706 	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5707 	if ((char *)ea_response_data + list_len > end_of_smb) {
5708 		cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
5709 		rc = -EIO;
5710 		goto QAllEAsOut;
5711 	}
5712 
5713 	/* account for ea list len */
5714 	list_len -= 4;
5715 	temp_fea = &ea_response_data->list;
5716 	temp_ptr = (char *)temp_fea;
5717 	while (list_len > 0) {
5718 		unsigned int name_len;
5719 		__u16 value_len;
5720 
5721 		list_len -= 4;
5722 		temp_ptr += 4;
5723 		/* make sure we can read name_len and value_len */
5724 		if (list_len < 0) {
5725 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
5726 			rc = -EIO;
5727 			goto QAllEAsOut;
5728 		}
5729 
5730 		name_len = temp_fea->name_len;
5731 		value_len = le16_to_cpu(temp_fea->value_len);
5732 		list_len -= name_len + 1 + value_len;
5733 		if (list_len < 0) {
5734 			cifs_dbg(FYI, "EA entry goes beyond length of list\n");
5735 			rc = -EIO;
5736 			goto QAllEAsOut;
5737 		}
5738 
5739 		if (ea_name) {
5740 			if (ea_name_len == name_len &&
5741 			    memcmp(ea_name, temp_ptr, name_len) == 0) {
5742 				temp_ptr += name_len + 1;
5743 				rc = value_len;
5744 				if (buf_size == 0)
5745 					goto QAllEAsOut;
5746 				if ((size_t)value_len > buf_size) {
5747 					rc = -ERANGE;
5748 					goto QAllEAsOut;
5749 				}
5750 				memcpy(EAData, temp_ptr, value_len);
5751 				goto QAllEAsOut;
5752 			}
5753 		} else {
5754 			/* account for prefix user. and trailing null */
5755 			rc += (5 + 1 + name_len);
5756 			if (rc < (int) buf_size) {
5757 				memcpy(EAData, "user.", 5);
5758 				EAData += 5;
5759 				memcpy(EAData, temp_ptr, name_len);
5760 				EAData += name_len;
5761 				/* null terminate name */
5762 				*EAData = 0;
5763 				++EAData;
5764 			} else if (buf_size == 0) {
5765 				/* skip copy - calc size only */
5766 			} else {
5767 				/* stop before overrun buffer */
5768 				rc = -ERANGE;
5769 				break;
5770 			}
5771 		}
5772 		temp_ptr += name_len + 1 + value_len;
5773 		temp_fea = (struct fea *)temp_ptr;
5774 	}
5775 
5776 	/* didn't find the named attribute */
5777 	if (ea_name)
5778 		rc = -ENODATA;
5779 
5780 QAllEAsOut:
5781 	cifs_buf_release(pSMB);
5782 	if (rc == -EAGAIN)
5783 		goto QAllEAsRetry;
5784 
5785 	return (ssize_t)rc;
5786 }
5787 
5788 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)5789 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
5790 	     const char *fileName, const char *ea_name, const void *ea_value,
5791 	     const __u16 ea_value_len, const struct nls_table *nls_codepage,
5792 	     struct cifs_sb_info *cifs_sb)
5793 {
5794 	struct smb_com_transaction2_spi_req *pSMB = NULL;
5795 	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5796 	struct fealist *parm_data;
5797 	int name_len;
5798 	int rc = 0;
5799 	int bytes_returned = 0;
5800 	__u16 params, param_offset, byte_count, offset, count;
5801 	int remap = cifs_remap(cifs_sb);
5802 
5803 	cifs_dbg(FYI, "In SetEA\n");
5804 SetEARetry:
5805 	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5806 		      (void **) &pSMBr);
5807 	if (rc)
5808 		return rc;
5809 
5810 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5811 		name_len =
5812 		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5813 				       PATH_MAX, nls_codepage, remap);
5814 		name_len++;	/* trailing null */
5815 		name_len *= 2;
5816 	} else {
5817 		name_len = copy_path_name(pSMB->FileName, fileName);
5818 	}
5819 
5820 	params = 6 + name_len;
5821 
5822 	/* done calculating parms using name_len of file name,
5823 	now use name_len to calculate length of ea name
5824 	we are going to create in the inode xattrs */
5825 	if (ea_name == NULL)
5826 		name_len = 0;
5827 	else
5828 		name_len = strnlen(ea_name, 255);
5829 
5830 	count = sizeof(*parm_data) + 1 + ea_value_len + name_len;
5831 	pSMB->MaxParameterCount = cpu_to_le16(2);
5832 	/* BB find max SMB PDU from sess */
5833 	pSMB->MaxDataCount = cpu_to_le16(1000);
5834 	pSMB->MaxSetupCount = 0;
5835 	pSMB->Reserved = 0;
5836 	pSMB->Flags = 0;
5837 	pSMB->Timeout = 0;
5838 	pSMB->Reserved2 = 0;
5839 	param_offset = offsetof(struct smb_com_transaction2_spi_req,
5840 				InformationLevel) - 4;
5841 	offset = param_offset + params;
5842 	pSMB->InformationLevel =
5843 		cpu_to_le16(SMB_SET_FILE_EA);
5844 
5845 	parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
5846 	pSMB->ParameterOffset = cpu_to_le16(param_offset);
5847 	pSMB->DataOffset = cpu_to_le16(offset);
5848 	pSMB->SetupCount = 1;
5849 	pSMB->Reserved3 = 0;
5850 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5851 	byte_count = 3 /* pad */  + params + count;
5852 	pSMB->DataCount = cpu_to_le16(count);
5853 	parm_data->list_len = cpu_to_le32(count);
5854 	parm_data->list.EA_flags = 0;
5855 	/* we checked above that name len is less than 255 */
5856 	parm_data->list.name_len = (__u8)name_len;
5857 	/* EA names are always ASCII */
5858 	if (ea_name)
5859 		strncpy(parm_data->list.name, ea_name, name_len);
5860 	parm_data->list.name[name_len] = '\0';
5861 	parm_data->list.value_len = cpu_to_le16(ea_value_len);
5862 	/* caller ensures that ea_value_len is less than 64K but
5863 	we need to ensure that it fits within the smb */
5864 
5865 	/*BB add length check to see if it would fit in
5866 	     negotiated SMB buffer size BB */
5867 	/* if (ea_value_len > buffer_size - 512 (enough for header)) */
5868 	if (ea_value_len)
5869 		memcpy(parm_data->list.name + name_len + 1,
5870 		       ea_value, ea_value_len);
5871 
5872 	pSMB->TotalDataCount = pSMB->DataCount;
5873 	pSMB->ParameterCount = cpu_to_le16(params);
5874 	pSMB->TotalParameterCount = pSMB->ParameterCount;
5875 	pSMB->Reserved4 = 0;
5876 	inc_rfc1001_len(pSMB, byte_count);
5877 	pSMB->ByteCount = cpu_to_le16(byte_count);
5878 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5879 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5880 	if (rc)
5881 		cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
5882 
5883 	cifs_buf_release(pSMB);
5884 
5885 	if (rc == -EAGAIN)
5886 		goto SetEARetry;
5887 
5888 	return rc;
5889 }
5890 #endif
5891