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