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