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