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