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