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