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