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