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