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