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 cifs_acl->default_entry_count = __constant_cpu_to_le16(0xFFFF);
3460 } else if (acl_type == ACL_TYPE_DEFAULT) {
3461 cifs_acl->default_entry_count = cpu_to_le16(count);
3462 cifs_acl->access_entry_count = __constant_cpu_to_le16(0xFFFF);
3463 } else {
3464 cFYI(1, "unknown ACL type %d", acl_type);
3465 return 0;
3466 }
3467 for (i = 0; i < count; i++) {
3468 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3469 &local_acl->a_entries[i]);
3470 if (rc != 0) {
3471 /* ACE not converted */
3472 break;
3473 }
3474 }
3475 if (rc == 0) {
3476 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3477 rc += sizeof(struct cifs_posix_acl);
3478 /* BB add check to make sure ACL does not overflow SMB */
3479 }
3480 return rc;
3481 }
3482
3483 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)3484 CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3485 const unsigned char *searchName,
3486 char *acl_inf, const int buflen, const int acl_type,
3487 const struct nls_table *nls_codepage, int remap)
3488 {
3489 /* SMB_QUERY_POSIX_ACL */
3490 TRANSACTION2_QPI_REQ *pSMB = NULL;
3491 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3492 int rc = 0;
3493 int bytes_returned;
3494 int name_len;
3495 __u16 params, byte_count;
3496
3497 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3498
3499 queryAclRetry:
3500 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3501 (void **) &pSMBr);
3502 if (rc)
3503 return rc;
3504
3505 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3506 name_len =
3507 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3508 searchName, PATH_MAX, nls_codepage,
3509 remap);
3510 name_len++; /* trailing null */
3511 name_len *= 2;
3512 pSMB->FileName[name_len] = 0;
3513 pSMB->FileName[name_len+1] = 0;
3514 } else { /* BB improve the check for buffer overruns BB */
3515 name_len = strnlen(searchName, PATH_MAX);
3516 name_len++; /* trailing null */
3517 strncpy(pSMB->FileName, searchName, name_len);
3518 }
3519
3520 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3521 pSMB->TotalDataCount = 0;
3522 pSMB->MaxParameterCount = cpu_to_le16(2);
3523 /* BB find exact max data count below from sess structure BB */
3524 pSMB->MaxDataCount = cpu_to_le16(4000);
3525 pSMB->MaxSetupCount = 0;
3526 pSMB->Reserved = 0;
3527 pSMB->Flags = 0;
3528 pSMB->Timeout = 0;
3529 pSMB->Reserved2 = 0;
3530 pSMB->ParameterOffset = cpu_to_le16(
3531 offsetof(struct smb_com_transaction2_qpi_req,
3532 InformationLevel) - 4);
3533 pSMB->DataCount = 0;
3534 pSMB->DataOffset = 0;
3535 pSMB->SetupCount = 1;
3536 pSMB->Reserved3 = 0;
3537 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3538 byte_count = params + 1 /* pad */ ;
3539 pSMB->TotalParameterCount = cpu_to_le16(params);
3540 pSMB->ParameterCount = pSMB->TotalParameterCount;
3541 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3542 pSMB->Reserved4 = 0;
3543 inc_rfc1001_len(pSMB, byte_count);
3544 pSMB->ByteCount = cpu_to_le16(byte_count);
3545
3546 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3547 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3548 cifs_stats_inc(&tcon->num_acl_get);
3549 if (rc) {
3550 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3551 } else {
3552 /* decode response */
3553
3554 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3555 /* BB also check enough total bytes returned */
3556 if (rc || get_bcc(&pSMBr->hdr) < 2)
3557 rc = -EIO; /* bad smb */
3558 else {
3559 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3560 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3561 rc = cifs_copy_posix_acl(acl_inf,
3562 (char *)&pSMBr->hdr.Protocol+data_offset,
3563 buflen, acl_type, count);
3564 }
3565 }
3566 cifs_buf_release(pSMB);
3567 if (rc == -EAGAIN)
3568 goto queryAclRetry;
3569 return rc;
3570 }
3571
3572 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)3573 CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3574 const unsigned char *fileName,
3575 const char *local_acl, const int buflen,
3576 const int acl_type,
3577 const struct nls_table *nls_codepage, int remap)
3578 {
3579 struct smb_com_transaction2_spi_req *pSMB = NULL;
3580 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3581 char *parm_data;
3582 int name_len;
3583 int rc = 0;
3584 int bytes_returned = 0;
3585 __u16 params, byte_count, data_count, param_offset, offset;
3586
3587 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3588 setAclRetry:
3589 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3590 (void **) &pSMBr);
3591 if (rc)
3592 return rc;
3593 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3594 name_len =
3595 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3596 PATH_MAX, nls_codepage, remap);
3597 name_len++; /* trailing null */
3598 name_len *= 2;
3599 } else { /* BB improve the check for buffer overruns BB */
3600 name_len = strnlen(fileName, PATH_MAX);
3601 name_len++; /* trailing null */
3602 strncpy(pSMB->FileName, fileName, name_len);
3603 }
3604 params = 6 + name_len;
3605 pSMB->MaxParameterCount = cpu_to_le16(2);
3606 /* BB find max SMB size from sess */
3607 pSMB->MaxDataCount = cpu_to_le16(1000);
3608 pSMB->MaxSetupCount = 0;
3609 pSMB->Reserved = 0;
3610 pSMB->Flags = 0;
3611 pSMB->Timeout = 0;
3612 pSMB->Reserved2 = 0;
3613 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3614 InformationLevel) - 4;
3615 offset = param_offset + params;
3616 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3617 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3618
3619 /* convert to on the wire format for POSIX ACL */
3620 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3621
3622 if (data_count == 0) {
3623 rc = -EOPNOTSUPP;
3624 goto setACLerrorExit;
3625 }
3626 pSMB->DataOffset = cpu_to_le16(offset);
3627 pSMB->SetupCount = 1;
3628 pSMB->Reserved3 = 0;
3629 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3630 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3631 byte_count = 3 /* pad */ + params + data_count;
3632 pSMB->DataCount = cpu_to_le16(data_count);
3633 pSMB->TotalDataCount = pSMB->DataCount;
3634 pSMB->ParameterCount = cpu_to_le16(params);
3635 pSMB->TotalParameterCount = pSMB->ParameterCount;
3636 pSMB->Reserved4 = 0;
3637 inc_rfc1001_len(pSMB, byte_count);
3638 pSMB->ByteCount = cpu_to_le16(byte_count);
3639 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3640 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3641 if (rc)
3642 cFYI(1, "Set POSIX ACL returned %d", rc);
3643
3644 setACLerrorExit:
3645 cifs_buf_release(pSMB);
3646 if (rc == -EAGAIN)
3647 goto setAclRetry;
3648 return rc;
3649 }
3650
3651 /* BB fix tabs in this function FIXME BB */
3652 int
CIFSGetExtAttr(const int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3653 CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3654 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3655 {
3656 int rc = 0;
3657 struct smb_t2_qfi_req *pSMB = NULL;
3658 struct smb_t2_qfi_rsp *pSMBr = NULL;
3659 int bytes_returned;
3660 __u16 params, byte_count;
3661
3662 cFYI(1, "In GetExtAttr");
3663 if (tcon == NULL)
3664 return -ENODEV;
3665
3666 GetExtAttrRetry:
3667 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3668 (void **) &pSMBr);
3669 if (rc)
3670 return rc;
3671
3672 params = 2 /* level */ + 2 /* fid */;
3673 pSMB->t2.TotalDataCount = 0;
3674 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3675 /* BB find exact max data count below from sess structure BB */
3676 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3677 pSMB->t2.MaxSetupCount = 0;
3678 pSMB->t2.Reserved = 0;
3679 pSMB->t2.Flags = 0;
3680 pSMB->t2.Timeout = 0;
3681 pSMB->t2.Reserved2 = 0;
3682 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3683 Fid) - 4);
3684 pSMB->t2.DataCount = 0;
3685 pSMB->t2.DataOffset = 0;
3686 pSMB->t2.SetupCount = 1;
3687 pSMB->t2.Reserved3 = 0;
3688 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3689 byte_count = params + 1 /* pad */ ;
3690 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3691 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3692 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3693 pSMB->Pad = 0;
3694 pSMB->Fid = netfid;
3695 inc_rfc1001_len(pSMB, byte_count);
3696 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3697
3698 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3699 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3700 if (rc) {
3701 cFYI(1, "error %d in GetExtAttr", rc);
3702 } else {
3703 /* decode response */
3704 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3705 /* BB also check enough total bytes returned */
3706 if (rc || get_bcc(&pSMBr->hdr) < 2)
3707 /* If rc should we check for EOPNOSUPP and
3708 disable the srvino flag? or in caller? */
3709 rc = -EIO; /* bad smb */
3710 else {
3711 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3712 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3713 struct file_chattr_info *pfinfo;
3714 /* BB Do we need a cast or hash here ? */
3715 if (count != 16) {
3716 cFYI(1, "Illegal size ret in GetExtAttr");
3717 rc = -EIO;
3718 goto GetExtAttrOut;
3719 }
3720 pfinfo = (struct file_chattr_info *)
3721 (data_offset + (char *) &pSMBr->hdr.Protocol);
3722 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3723 *pMask = le64_to_cpu(pfinfo->mask);
3724 }
3725 }
3726 GetExtAttrOut:
3727 cifs_buf_release(pSMB);
3728 if (rc == -EAGAIN)
3729 goto GetExtAttrRetry;
3730 return rc;
3731 }
3732
3733 #endif /* CONFIG_POSIX */
3734
3735 #ifdef CONFIG_CIFS_ACL
3736 /*
3737 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3738 * all NT TRANSACTS that we init here have total parm and data under about 400
3739 * bytes (to fit in small cifs buffer size), which is the case so far, it
3740 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3741 * returned setup area) and MaxParameterCount (returned parms size) must be set
3742 * by caller
3743 */
3744 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3745 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3746 const int parm_len, struct cifs_tcon *tcon,
3747 void **ret_buf)
3748 {
3749 int rc;
3750 __u32 temp_offset;
3751 struct smb_com_ntransact_req *pSMB;
3752
3753 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3754 (void **)&pSMB);
3755 if (rc)
3756 return rc;
3757 *ret_buf = (void *)pSMB;
3758 pSMB->Reserved = 0;
3759 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3760 pSMB->TotalDataCount = 0;
3761 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3762 pSMB->ParameterCount = pSMB->TotalParameterCount;
3763 pSMB->DataCount = pSMB->TotalDataCount;
3764 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3765 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3766 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3767 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3768 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3769 pSMB->SubCommand = cpu_to_le16(sub_command);
3770 return 0;
3771 }
3772
3773 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3774 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3775 __u32 *pparmlen, __u32 *pdatalen)
3776 {
3777 char *end_of_smb;
3778 __u32 data_count, data_offset, parm_count, parm_offset;
3779 struct smb_com_ntransact_rsp *pSMBr;
3780 u16 bcc;
3781
3782 *pdatalen = 0;
3783 *pparmlen = 0;
3784
3785 if (buf == NULL)
3786 return -EINVAL;
3787
3788 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3789
3790 bcc = get_bcc(&pSMBr->hdr);
3791 end_of_smb = 2 /* sizeof byte count */ + bcc +
3792 (char *)&pSMBr->ByteCount;
3793
3794 data_offset = le32_to_cpu(pSMBr->DataOffset);
3795 data_count = le32_to_cpu(pSMBr->DataCount);
3796 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3797 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3798
3799 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3800 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3801
3802 /* should we also check that parm and data areas do not overlap? */
3803 if (*ppparm > end_of_smb) {
3804 cFYI(1, "parms start after end of smb");
3805 return -EINVAL;
3806 } else if (parm_count + *ppparm > end_of_smb) {
3807 cFYI(1, "parm end after end of smb");
3808 return -EINVAL;
3809 } else if (*ppdata > end_of_smb) {
3810 cFYI(1, "data starts after end of smb");
3811 return -EINVAL;
3812 } else if (data_count + *ppdata > end_of_smb) {
3813 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3814 *ppdata, data_count, (data_count + *ppdata),
3815 end_of_smb, pSMBr);
3816 return -EINVAL;
3817 } else if (parm_count + data_count > bcc) {
3818 cFYI(1, "parm count and data count larger than SMB");
3819 return -EINVAL;
3820 }
3821 *pdatalen = data_count;
3822 *pparmlen = parm_count;
3823 return 0;
3824 }
3825
3826 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3827 int
CIFSSMBGetCIFSACL(const int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd ** acl_inf,__u32 * pbuflen)3828 CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3829 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3830 {
3831 int rc = 0;
3832 int buf_type = 0;
3833 QUERY_SEC_DESC_REQ *pSMB;
3834 struct kvec iov[1];
3835
3836 cFYI(1, "GetCifsACL");
3837
3838 *pbuflen = 0;
3839 *acl_inf = NULL;
3840
3841 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3842 8 /* parm len */, tcon, (void **) &pSMB);
3843 if (rc)
3844 return rc;
3845
3846 pSMB->MaxParameterCount = cpu_to_le32(4);
3847 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3848 pSMB->MaxSetupCount = 0;
3849 pSMB->Fid = fid; /* file handle always le */
3850 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3851 CIFS_ACL_DACL);
3852 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3853 inc_rfc1001_len(pSMB, 11);
3854 iov[0].iov_base = (char *)pSMB;
3855 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3856
3857 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3858 0);
3859 cifs_stats_inc(&tcon->num_acl_get);
3860 if (rc) {
3861 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3862 } else { /* decode response */
3863 __le32 *parm;
3864 __u32 parm_len;
3865 __u32 acl_len;
3866 struct smb_com_ntransact_rsp *pSMBr;
3867 char *pdata;
3868
3869 /* validate_nttransact */
3870 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3871 &pdata, &parm_len, pbuflen);
3872 if (rc)
3873 goto qsec_out;
3874 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3875
3876 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3877
3878 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3879 rc = -EIO; /* bad smb */
3880 *pbuflen = 0;
3881 goto qsec_out;
3882 }
3883
3884 /* BB check that data area is minimum length and as big as acl_len */
3885
3886 acl_len = le32_to_cpu(*parm);
3887 if (acl_len != *pbuflen) {
3888 cERROR(1, "acl length %d does not match %d",
3889 acl_len, *pbuflen);
3890 if (*pbuflen > acl_len)
3891 *pbuflen = acl_len;
3892 }
3893
3894 /* check if buffer is big enough for the acl
3895 header followed by the smallest SID */
3896 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3897 (*pbuflen >= 64 * 1024)) {
3898 cERROR(1, "bad acl length %d", *pbuflen);
3899 rc = -EINVAL;
3900 *pbuflen = 0;
3901 } else {
3902 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3903 if (*acl_inf == NULL) {
3904 *pbuflen = 0;
3905 rc = -ENOMEM;
3906 }
3907 memcpy(*acl_inf, pdata, *pbuflen);
3908 }
3909 }
3910 qsec_out:
3911 if (buf_type == CIFS_SMALL_BUFFER)
3912 cifs_small_buf_release(iov[0].iov_base);
3913 else if (buf_type == CIFS_LARGE_BUFFER)
3914 cifs_buf_release(iov[0].iov_base);
3915 /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3916 return rc;
3917 }
3918
3919 int
CIFSSMBSetCIFSACL(const int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd * pntsd,__u32 acllen,int aclflag)3920 CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3921 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3922 {
3923 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3924 int rc = 0;
3925 int bytes_returned = 0;
3926 SET_SEC_DESC_REQ *pSMB = NULL;
3927 void *pSMBr;
3928
3929 setCifsAclRetry:
3930 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3931 if (rc)
3932 return rc;
3933
3934 pSMB->MaxSetupCount = 0;
3935 pSMB->Reserved = 0;
3936
3937 param_count = 8;
3938 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3939 data_count = acllen;
3940 data_offset = param_offset + param_count;
3941 byte_count = 3 /* pad */ + param_count;
3942
3943 pSMB->DataCount = cpu_to_le32(data_count);
3944 pSMB->TotalDataCount = pSMB->DataCount;
3945 pSMB->MaxParameterCount = cpu_to_le32(4);
3946 pSMB->MaxDataCount = cpu_to_le32(16384);
3947 pSMB->ParameterCount = cpu_to_le32(param_count);
3948 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3949 pSMB->TotalParameterCount = pSMB->ParameterCount;
3950 pSMB->DataOffset = cpu_to_le32(data_offset);
3951 pSMB->SetupCount = 0;
3952 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3953 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3954
3955 pSMB->Fid = fid; /* file handle always le */
3956 pSMB->Reserved2 = 0;
3957 pSMB->AclFlags = cpu_to_le32(aclflag);
3958
3959 if (pntsd && acllen) {
3960 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3961 data_offset, pntsd, acllen);
3962 inc_rfc1001_len(pSMB, byte_count + data_count);
3963 } else
3964 inc_rfc1001_len(pSMB, byte_count);
3965
3966 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3967 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3968
3969 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3970 if (rc)
3971 cFYI(1, "Set CIFS ACL returned %d", rc);
3972 cifs_buf_release(pSMB);
3973
3974 if (rc == -EAGAIN)
3975 goto setCifsAclRetry;
3976
3977 return (rc);
3978 }
3979
3980 #endif /* CONFIG_CIFS_ACL */
3981
3982 /* Legacy Query Path Information call for lookup to old servers such
3983 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)3984 int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3985 const unsigned char *searchName,
3986 FILE_ALL_INFO *pFinfo,
3987 const struct nls_table *nls_codepage, int remap)
3988 {
3989 QUERY_INFORMATION_REQ *pSMB;
3990 QUERY_INFORMATION_RSP *pSMBr;
3991 int rc = 0;
3992 int bytes_returned;
3993 int name_len;
3994
3995 cFYI(1, "In SMBQPath path %s", searchName);
3996 QInfRetry:
3997 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3998 (void **) &pSMBr);
3999 if (rc)
4000 return rc;
4001
4002 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4003 name_len =
4004 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4005 searchName, PATH_MAX, nls_codepage,
4006 remap);
4007 name_len++; /* trailing null */
4008 name_len *= 2;
4009 } else {
4010 name_len = strnlen(searchName, PATH_MAX);
4011 name_len++; /* trailing null */
4012 strncpy(pSMB->FileName, searchName, name_len);
4013 }
4014 pSMB->BufferFormat = 0x04;
4015 name_len++; /* account for buffer type byte */
4016 inc_rfc1001_len(pSMB, (__u16)name_len);
4017 pSMB->ByteCount = cpu_to_le16(name_len);
4018
4019 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4020 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4021 if (rc) {
4022 cFYI(1, "Send error in QueryInfo = %d", rc);
4023 } else if (pFinfo) {
4024 struct timespec ts;
4025 __u32 time = le32_to_cpu(pSMBr->last_write_time);
4026
4027 /* decode response */
4028 /* BB FIXME - add time zone adjustment BB */
4029 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
4030 ts.tv_nsec = 0;
4031 ts.tv_sec = time;
4032 /* decode time fields */
4033 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4034 pFinfo->LastWriteTime = pFinfo->ChangeTime;
4035 pFinfo->LastAccessTime = 0;
4036 pFinfo->AllocationSize =
4037 cpu_to_le64(le32_to_cpu(pSMBr->size));
4038 pFinfo->EndOfFile = pFinfo->AllocationSize;
4039 pFinfo->Attributes =
4040 cpu_to_le32(le16_to_cpu(pSMBr->attr));
4041 } else
4042 rc = -EIO; /* bad buffer passed in */
4043
4044 cifs_buf_release(pSMB);
4045
4046 if (rc == -EAGAIN)
4047 goto QInfRetry;
4048
4049 return rc;
4050 }
4051
4052 int
CIFSSMBQFileInfo(const int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)4053 CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
4054 u16 netfid, FILE_ALL_INFO *pFindData)
4055 {
4056 struct smb_t2_qfi_req *pSMB = NULL;
4057 struct smb_t2_qfi_rsp *pSMBr = NULL;
4058 int rc = 0;
4059 int bytes_returned;
4060 __u16 params, byte_count;
4061
4062 QFileInfoRetry:
4063 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4064 (void **) &pSMBr);
4065 if (rc)
4066 return rc;
4067
4068 params = 2 /* level */ + 2 /* fid */;
4069 pSMB->t2.TotalDataCount = 0;
4070 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4071 /* BB find exact max data count below from sess structure BB */
4072 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4073 pSMB->t2.MaxSetupCount = 0;
4074 pSMB->t2.Reserved = 0;
4075 pSMB->t2.Flags = 0;
4076 pSMB->t2.Timeout = 0;
4077 pSMB->t2.Reserved2 = 0;
4078 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4079 Fid) - 4);
4080 pSMB->t2.DataCount = 0;
4081 pSMB->t2.DataOffset = 0;
4082 pSMB->t2.SetupCount = 1;
4083 pSMB->t2.Reserved3 = 0;
4084 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4085 byte_count = params + 1 /* pad */ ;
4086 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4087 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4088 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4089 pSMB->Pad = 0;
4090 pSMB->Fid = netfid;
4091 inc_rfc1001_len(pSMB, byte_count);
4092
4093 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4094 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4095 if (rc) {
4096 cFYI(1, "Send error in QPathInfo = %d", rc);
4097 } else { /* decode response */
4098 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4099
4100 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4101 rc = -EIO;
4102 else if (get_bcc(&pSMBr->hdr) < 40)
4103 rc = -EIO; /* bad smb */
4104 else if (pFindData) {
4105 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4106 memcpy((char *) pFindData,
4107 (char *) &pSMBr->hdr.Protocol +
4108 data_offset, sizeof(FILE_ALL_INFO));
4109 } else
4110 rc = -ENOMEM;
4111 }
4112 cifs_buf_release(pSMB);
4113 if (rc == -EAGAIN)
4114 goto QFileInfoRetry;
4115
4116 return rc;
4117 }
4118
4119 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)4120 CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
4121 const unsigned char *searchName,
4122 FILE_ALL_INFO *pFindData,
4123 int legacy /* old style infolevel */,
4124 const struct nls_table *nls_codepage, int remap)
4125 {
4126 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4127 TRANSACTION2_QPI_REQ *pSMB = NULL;
4128 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4129 int rc = 0;
4130 int bytes_returned;
4131 int name_len;
4132 __u16 params, byte_count;
4133
4134 /* cFYI(1, "In QPathInfo path %s", searchName); */
4135 QPathInfoRetry:
4136 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4137 (void **) &pSMBr);
4138 if (rc)
4139 return rc;
4140
4141 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4142 name_len =
4143 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4144 PATH_MAX, nls_codepage, remap);
4145 name_len++; /* trailing null */
4146 name_len *= 2;
4147 } else { /* BB improve the check for buffer overruns BB */
4148 name_len = strnlen(searchName, PATH_MAX);
4149 name_len++; /* trailing null */
4150 strncpy(pSMB->FileName, searchName, name_len);
4151 }
4152
4153 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4154 pSMB->TotalDataCount = 0;
4155 pSMB->MaxParameterCount = cpu_to_le16(2);
4156 /* BB find exact max SMB PDU from sess structure BB */
4157 pSMB->MaxDataCount = cpu_to_le16(4000);
4158 pSMB->MaxSetupCount = 0;
4159 pSMB->Reserved = 0;
4160 pSMB->Flags = 0;
4161 pSMB->Timeout = 0;
4162 pSMB->Reserved2 = 0;
4163 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4164 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4165 pSMB->DataCount = 0;
4166 pSMB->DataOffset = 0;
4167 pSMB->SetupCount = 1;
4168 pSMB->Reserved3 = 0;
4169 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4170 byte_count = params + 1 /* pad */ ;
4171 pSMB->TotalParameterCount = cpu_to_le16(params);
4172 pSMB->ParameterCount = pSMB->TotalParameterCount;
4173 if (legacy)
4174 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4175 else
4176 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4177 pSMB->Reserved4 = 0;
4178 inc_rfc1001_len(pSMB, byte_count);
4179 pSMB->ByteCount = cpu_to_le16(byte_count);
4180
4181 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4182 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4183 if (rc) {
4184 cFYI(1, "Send error in QPathInfo = %d", rc);
4185 } else { /* decode response */
4186 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4187
4188 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4189 rc = -EIO;
4190 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4191 rc = -EIO; /* bad smb */
4192 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4193 rc = -EIO; /* 24 or 26 expected but we do not read
4194 last field */
4195 else if (pFindData) {
4196 int size;
4197 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4198
4199 /* On legacy responses we do not read the last field,
4200 EAsize, fortunately since it varies by subdialect and
4201 also note it differs on Set vs. Get, ie two bytes or 4
4202 bytes depending but we don't care here */
4203 if (legacy)
4204 size = sizeof(FILE_INFO_STANDARD);
4205 else
4206 size = sizeof(FILE_ALL_INFO);
4207 memcpy((char *) pFindData,
4208 (char *) &pSMBr->hdr.Protocol +
4209 data_offset, size);
4210 } else
4211 rc = -ENOMEM;
4212 }
4213 cifs_buf_release(pSMB);
4214 if (rc == -EAGAIN)
4215 goto QPathInfoRetry;
4216
4217 return rc;
4218 }
4219
4220 int
CIFSSMBUnixQFileInfo(const int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)4221 CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
4222 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4223 {
4224 struct smb_t2_qfi_req *pSMB = NULL;
4225 struct smb_t2_qfi_rsp *pSMBr = NULL;
4226 int rc = 0;
4227 int bytes_returned;
4228 __u16 params, byte_count;
4229
4230 UnixQFileInfoRetry:
4231 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4232 (void **) &pSMBr);
4233 if (rc)
4234 return rc;
4235
4236 params = 2 /* level */ + 2 /* fid */;
4237 pSMB->t2.TotalDataCount = 0;
4238 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4239 /* BB find exact max data count below from sess structure BB */
4240 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4241 pSMB->t2.MaxSetupCount = 0;
4242 pSMB->t2.Reserved = 0;
4243 pSMB->t2.Flags = 0;
4244 pSMB->t2.Timeout = 0;
4245 pSMB->t2.Reserved2 = 0;
4246 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4247 Fid) - 4);
4248 pSMB->t2.DataCount = 0;
4249 pSMB->t2.DataOffset = 0;
4250 pSMB->t2.SetupCount = 1;
4251 pSMB->t2.Reserved3 = 0;
4252 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4253 byte_count = params + 1 /* pad */ ;
4254 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4255 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4256 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4257 pSMB->Pad = 0;
4258 pSMB->Fid = netfid;
4259 inc_rfc1001_len(pSMB, byte_count);
4260
4261 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4262 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4263 if (rc) {
4264 cFYI(1, "Send error in QPathInfo = %d", rc);
4265 } else { /* decode response */
4266 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4267
4268 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4269 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4270 "Unix Extensions can be disabled on mount "
4271 "by specifying the nosfu mount option.");
4272 rc = -EIO; /* bad smb */
4273 } else {
4274 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4275 memcpy((char *) pFindData,
4276 (char *) &pSMBr->hdr.Protocol +
4277 data_offset,
4278 sizeof(FILE_UNIX_BASIC_INFO));
4279 }
4280 }
4281
4282 cifs_buf_release(pSMB);
4283 if (rc == -EAGAIN)
4284 goto UnixQFileInfoRetry;
4285
4286 return rc;
4287 }
4288
4289 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)4290 CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
4291 const unsigned char *searchName,
4292 FILE_UNIX_BASIC_INFO *pFindData,
4293 const struct nls_table *nls_codepage, int remap)
4294 {
4295 /* SMB_QUERY_FILE_UNIX_BASIC */
4296 TRANSACTION2_QPI_REQ *pSMB = NULL;
4297 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4298 int rc = 0;
4299 int bytes_returned = 0;
4300 int name_len;
4301 __u16 params, byte_count;
4302
4303 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4304 UnixQPathInfoRetry:
4305 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4306 (void **) &pSMBr);
4307 if (rc)
4308 return rc;
4309
4310 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4311 name_len =
4312 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4313 PATH_MAX, nls_codepage, remap);
4314 name_len++; /* trailing null */
4315 name_len *= 2;
4316 } else { /* BB improve the check for buffer overruns BB */
4317 name_len = strnlen(searchName, PATH_MAX);
4318 name_len++; /* trailing null */
4319 strncpy(pSMB->FileName, searchName, name_len);
4320 }
4321
4322 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4323 pSMB->TotalDataCount = 0;
4324 pSMB->MaxParameterCount = cpu_to_le16(2);
4325 /* BB find exact max SMB PDU from sess structure BB */
4326 pSMB->MaxDataCount = cpu_to_le16(4000);
4327 pSMB->MaxSetupCount = 0;
4328 pSMB->Reserved = 0;
4329 pSMB->Flags = 0;
4330 pSMB->Timeout = 0;
4331 pSMB->Reserved2 = 0;
4332 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4333 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4334 pSMB->DataCount = 0;
4335 pSMB->DataOffset = 0;
4336 pSMB->SetupCount = 1;
4337 pSMB->Reserved3 = 0;
4338 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4339 byte_count = params + 1 /* pad */ ;
4340 pSMB->TotalParameterCount = cpu_to_le16(params);
4341 pSMB->ParameterCount = pSMB->TotalParameterCount;
4342 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4343 pSMB->Reserved4 = 0;
4344 inc_rfc1001_len(pSMB, byte_count);
4345 pSMB->ByteCount = cpu_to_le16(byte_count);
4346
4347 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4348 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4349 if (rc) {
4350 cFYI(1, "Send error in QPathInfo = %d", rc);
4351 } else { /* decode response */
4352 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4353
4354 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4355 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4356 "Unix Extensions can be disabled on mount "
4357 "by specifying the nosfu mount option.");
4358 rc = -EIO; /* bad smb */
4359 } else {
4360 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4361 memcpy((char *) pFindData,
4362 (char *) &pSMBr->hdr.Protocol +
4363 data_offset,
4364 sizeof(FILE_UNIX_BASIC_INFO));
4365 }
4366 }
4367 cifs_buf_release(pSMB);
4368 if (rc == -EAGAIN)
4369 goto UnixQPathInfoRetry;
4370
4371 return rc;
4372 }
4373
4374 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4375 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)4376 CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4377 const char *searchName,
4378 const struct nls_table *nls_codepage,
4379 __u16 *pnetfid, __u16 search_flags,
4380 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4381 {
4382 /* level 257 SMB_ */
4383 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4384 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4385 T2_FFIRST_RSP_PARMS *parms;
4386 int rc = 0;
4387 int bytes_returned = 0;
4388 int name_len;
4389 __u16 params, byte_count;
4390
4391 cFYI(1, "In FindFirst for %s", searchName);
4392
4393 findFirstRetry:
4394 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4395 (void **) &pSMBr);
4396 if (rc)
4397 return rc;
4398
4399 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4400 name_len =
4401 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4402 PATH_MAX, nls_codepage, remap);
4403 /* We can not add the asterik earlier in case
4404 it got remapped to 0xF03A as if it were part of the
4405 directory name instead of a wildcard */
4406 name_len *= 2;
4407 pSMB->FileName[name_len] = dirsep;
4408 pSMB->FileName[name_len+1] = 0;
4409 pSMB->FileName[name_len+2] = '*';
4410 pSMB->FileName[name_len+3] = 0;
4411 name_len += 4; /* now the trailing null */
4412 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4413 pSMB->FileName[name_len+1] = 0;
4414 name_len += 2;
4415 } else { /* BB add check for overrun of SMB buf BB */
4416 name_len = strnlen(searchName, PATH_MAX);
4417 /* BB fix here and in unicode clause above ie
4418 if (name_len > buffersize-header)
4419 free buffer exit; BB */
4420 strncpy(pSMB->FileName, searchName, name_len);
4421 pSMB->FileName[name_len] = dirsep;
4422 pSMB->FileName[name_len+1] = '*';
4423 pSMB->FileName[name_len+2] = 0;
4424 name_len += 3;
4425 }
4426
4427 params = 12 + name_len /* includes null */ ;
4428 pSMB->TotalDataCount = 0; /* no EAs */
4429 pSMB->MaxParameterCount = cpu_to_le16(10);
4430 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4431 pSMB->MaxSetupCount = 0;
4432 pSMB->Reserved = 0;
4433 pSMB->Flags = 0;
4434 pSMB->Timeout = 0;
4435 pSMB->Reserved2 = 0;
4436 byte_count = params + 1 /* pad */ ;
4437 pSMB->TotalParameterCount = cpu_to_le16(params);
4438 pSMB->ParameterCount = pSMB->TotalParameterCount;
4439 pSMB->ParameterOffset = cpu_to_le16(
4440 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4441 - 4);
4442 pSMB->DataCount = 0;
4443 pSMB->DataOffset = 0;
4444 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4445 pSMB->Reserved3 = 0;
4446 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4447 pSMB->SearchAttributes =
4448 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4449 ATTR_DIRECTORY);
4450 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4451 pSMB->SearchFlags = cpu_to_le16(search_flags);
4452 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4453
4454 /* BB what should we set StorageType to? Does it matter? BB */
4455 pSMB->SearchStorageType = 0;
4456 inc_rfc1001_len(pSMB, byte_count);
4457 pSMB->ByteCount = cpu_to_le16(byte_count);
4458
4459 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4460 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4461 cifs_stats_inc(&tcon->num_ffirst);
4462
4463 if (rc) {/* BB add logic to retry regular search if Unix search
4464 rejected unexpectedly by server */
4465 /* BB Add code to handle unsupported level rc */
4466 cFYI(1, "Error in FindFirst = %d", rc);
4467
4468 cifs_buf_release(pSMB);
4469
4470 /* BB eventually could optimize out free and realloc of buf */
4471 /* for this case */
4472 if (rc == -EAGAIN)
4473 goto findFirstRetry;
4474 } else { /* decode response */
4475 /* BB remember to free buffer if error BB */
4476 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4477 if (rc == 0) {
4478 unsigned int lnoff;
4479
4480 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4481 psrch_inf->unicode = true;
4482 else
4483 psrch_inf->unicode = false;
4484
4485 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4486 psrch_inf->smallBuf = 0;
4487 psrch_inf->srch_entries_start =
4488 (char *) &pSMBr->hdr.Protocol +
4489 le16_to_cpu(pSMBr->t2.DataOffset);
4490 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4491 le16_to_cpu(pSMBr->t2.ParameterOffset));
4492
4493 if (parms->EndofSearch)
4494 psrch_inf->endOfSearch = true;
4495 else
4496 psrch_inf->endOfSearch = false;
4497
4498 psrch_inf->entries_in_buffer =
4499 le16_to_cpu(parms->SearchCount);
4500 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4501 psrch_inf->entries_in_buffer;
4502 lnoff = le16_to_cpu(parms->LastNameOffset);
4503 if (CIFSMaxBufSize < lnoff) {
4504 cERROR(1, "ignoring corrupt resume name");
4505 psrch_inf->last_entry = NULL;
4506 return rc;
4507 }
4508
4509 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4510 lnoff;
4511
4512 *pnetfid = parms->SearchHandle;
4513 } else {
4514 cifs_buf_release(pSMB);
4515 }
4516 }
4517
4518 return rc;
4519 }
4520
CIFSFindNext(const int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4521 int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
4522 __u16 search_flags, struct cifs_search_info *psrch_inf)
4523 {
4524 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4525 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4526 T2_FNEXT_RSP_PARMS *parms;
4527 char *response_data;
4528 int rc = 0;
4529 int bytes_returned;
4530 unsigned int name_len;
4531 __u16 params, byte_count;
4532
4533 cFYI(1, "In FindNext");
4534
4535 if (psrch_inf->endOfSearch)
4536 return -ENOENT;
4537
4538 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4539 (void **) &pSMBr);
4540 if (rc)
4541 return rc;
4542
4543 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4544 byte_count = 0;
4545 pSMB->TotalDataCount = 0; /* no EAs */
4546 pSMB->MaxParameterCount = cpu_to_le16(8);
4547 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4548 pSMB->MaxSetupCount = 0;
4549 pSMB->Reserved = 0;
4550 pSMB->Flags = 0;
4551 pSMB->Timeout = 0;
4552 pSMB->Reserved2 = 0;
4553 pSMB->ParameterOffset = cpu_to_le16(
4554 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4555 pSMB->DataCount = 0;
4556 pSMB->DataOffset = 0;
4557 pSMB->SetupCount = 1;
4558 pSMB->Reserved3 = 0;
4559 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4560 pSMB->SearchHandle = searchHandle; /* always kept as le */
4561 pSMB->SearchCount =
4562 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4563 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4564 pSMB->ResumeKey = psrch_inf->resume_key;
4565 pSMB->SearchFlags = cpu_to_le16(search_flags);
4566
4567 name_len = psrch_inf->resume_name_len;
4568 params += name_len;
4569 if (name_len < PATH_MAX) {
4570 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4571 byte_count += name_len;
4572 /* 14 byte parm len above enough for 2 byte null terminator */
4573 pSMB->ResumeFileName[name_len] = 0;
4574 pSMB->ResumeFileName[name_len+1] = 0;
4575 } else {
4576 rc = -EINVAL;
4577 goto FNext2_err_exit;
4578 }
4579 byte_count = params + 1 /* pad */ ;
4580 pSMB->TotalParameterCount = cpu_to_le16(params);
4581 pSMB->ParameterCount = pSMB->TotalParameterCount;
4582 inc_rfc1001_len(pSMB, byte_count);
4583 pSMB->ByteCount = cpu_to_le16(byte_count);
4584
4585 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4586 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4587 cifs_stats_inc(&tcon->num_fnext);
4588 if (rc) {
4589 if (rc == -EBADF) {
4590 psrch_inf->endOfSearch = true;
4591 cifs_buf_release(pSMB);
4592 rc = 0; /* search probably was closed at end of search*/
4593 } else
4594 cFYI(1, "FindNext returned = %d", rc);
4595 } else { /* decode response */
4596 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4597
4598 if (rc == 0) {
4599 unsigned int lnoff;
4600
4601 /* BB fixme add lock for file (srch_info) struct here */
4602 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4603 psrch_inf->unicode = true;
4604 else
4605 psrch_inf->unicode = false;
4606 response_data = (char *) &pSMBr->hdr.Protocol +
4607 le16_to_cpu(pSMBr->t2.ParameterOffset);
4608 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4609 response_data = (char *)&pSMBr->hdr.Protocol +
4610 le16_to_cpu(pSMBr->t2.DataOffset);
4611 if (psrch_inf->smallBuf)
4612 cifs_small_buf_release(
4613 psrch_inf->ntwrk_buf_start);
4614 else
4615 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4616 psrch_inf->srch_entries_start = response_data;
4617 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4618 psrch_inf->smallBuf = 0;
4619 if (parms->EndofSearch)
4620 psrch_inf->endOfSearch = true;
4621 else
4622 psrch_inf->endOfSearch = false;
4623 psrch_inf->entries_in_buffer =
4624 le16_to_cpu(parms->SearchCount);
4625 psrch_inf->index_of_last_entry +=
4626 psrch_inf->entries_in_buffer;
4627 lnoff = le16_to_cpu(parms->LastNameOffset);
4628 if (CIFSMaxBufSize < lnoff) {
4629 cERROR(1, "ignoring corrupt resume name");
4630 psrch_inf->last_entry = NULL;
4631 return rc;
4632 } else
4633 psrch_inf->last_entry =
4634 psrch_inf->srch_entries_start + lnoff;
4635
4636 /* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4637 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4638
4639 /* BB fixme add unlock here */
4640 }
4641
4642 }
4643
4644 /* BB On error, should we leave previous search buf (and count and
4645 last entry fields) intact or free the previous one? */
4646
4647 /* Note: On -EAGAIN error only caller can retry on handle based calls
4648 since file handle passed in no longer valid */
4649 FNext2_err_exit:
4650 if (rc != 0)
4651 cifs_buf_release(pSMB);
4652 return rc;
4653 }
4654
4655 int
CIFSFindClose(const int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4656 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4657 const __u16 searchHandle)
4658 {
4659 int rc = 0;
4660 FINDCLOSE_REQ *pSMB = NULL;
4661
4662 cFYI(1, "In CIFSSMBFindClose");
4663 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4664
4665 /* no sense returning error if session restarted
4666 as file handle has been closed */
4667 if (rc == -EAGAIN)
4668 return 0;
4669 if (rc)
4670 return rc;
4671
4672 pSMB->FileID = searchHandle;
4673 pSMB->ByteCount = 0;
4674 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4675 if (rc)
4676 cERROR(1, "Send error in FindClose = %d", rc);
4677
4678 cifs_stats_inc(&tcon->num_fclose);
4679
4680 /* Since session is dead, search handle closed on server already */
4681 if (rc == -EAGAIN)
4682 rc = 0;
4683
4684 return rc;
4685 }
4686
4687 int
CIFSGetSrvInodeNumber(const int xid,struct cifs_tcon * tcon,const unsigned char * searchName,__u64 * inode_number,const struct nls_table * nls_codepage,int remap)4688 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4689 const unsigned char *searchName,
4690 __u64 *inode_number,
4691 const struct nls_table *nls_codepage, int remap)
4692 {
4693 int rc = 0;
4694 TRANSACTION2_QPI_REQ *pSMB = NULL;
4695 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4696 int name_len, bytes_returned;
4697 __u16 params, byte_count;
4698
4699 cFYI(1, "In GetSrvInodeNum for %s", searchName);
4700 if (tcon == NULL)
4701 return -ENODEV;
4702
4703 GetInodeNumberRetry:
4704 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4705 (void **) &pSMBr);
4706 if (rc)
4707 return rc;
4708
4709 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4710 name_len =
4711 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4712 searchName, PATH_MAX, nls_codepage,
4713 remap);
4714 name_len++; /* trailing null */
4715 name_len *= 2;
4716 } else { /* BB improve the check for buffer overruns BB */
4717 name_len = strnlen(searchName, PATH_MAX);
4718 name_len++; /* trailing null */
4719 strncpy(pSMB->FileName, searchName, name_len);
4720 }
4721
4722 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4723 pSMB->TotalDataCount = 0;
4724 pSMB->MaxParameterCount = cpu_to_le16(2);
4725 /* BB find exact max data count below from sess structure BB */
4726 pSMB->MaxDataCount = cpu_to_le16(4000);
4727 pSMB->MaxSetupCount = 0;
4728 pSMB->Reserved = 0;
4729 pSMB->Flags = 0;
4730 pSMB->Timeout = 0;
4731 pSMB->Reserved2 = 0;
4732 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4733 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4734 pSMB->DataCount = 0;
4735 pSMB->DataOffset = 0;
4736 pSMB->SetupCount = 1;
4737 pSMB->Reserved3 = 0;
4738 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4739 byte_count = params + 1 /* pad */ ;
4740 pSMB->TotalParameterCount = cpu_to_le16(params);
4741 pSMB->ParameterCount = pSMB->TotalParameterCount;
4742 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4743 pSMB->Reserved4 = 0;
4744 inc_rfc1001_len(pSMB, byte_count);
4745 pSMB->ByteCount = cpu_to_le16(byte_count);
4746
4747 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4748 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4749 if (rc) {
4750 cFYI(1, "error %d in QueryInternalInfo", rc);
4751 } else {
4752 /* decode response */
4753 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4754 /* BB also check enough total bytes returned */
4755 if (rc || get_bcc(&pSMBr->hdr) < 2)
4756 /* If rc should we check for EOPNOSUPP and
4757 disable the srvino flag? or in caller? */
4758 rc = -EIO; /* bad smb */
4759 else {
4760 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4761 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4762 struct file_internal_info *pfinfo;
4763 /* BB Do we need a cast or hash here ? */
4764 if (count < 8) {
4765 cFYI(1, "Illegal size ret in QryIntrnlInf");
4766 rc = -EIO;
4767 goto GetInodeNumOut;
4768 }
4769 pfinfo = (struct file_internal_info *)
4770 (data_offset + (char *) &pSMBr->hdr.Protocol);
4771 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4772 }
4773 }
4774 GetInodeNumOut:
4775 cifs_buf_release(pSMB);
4776 if (rc == -EAGAIN)
4777 goto GetInodeNumberRetry;
4778 return rc;
4779 }
4780
4781 /* parses DFS refferal V3 structure
4782 * caller is responsible for freeing target_nodes
4783 * returns:
4784 * on success - 0
4785 * on failure - errno
4786 */
4787 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)4788 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4789 unsigned int *num_of_nodes,
4790 struct dfs_info3_param **target_nodes,
4791 const struct nls_table *nls_codepage, int remap,
4792 const char *searchName)
4793 {
4794 int i, rc = 0;
4795 char *data_end;
4796 bool is_unicode;
4797 struct dfs_referral_level_3 *ref;
4798
4799 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4800 is_unicode = true;
4801 else
4802 is_unicode = false;
4803 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4804
4805 if (*num_of_nodes < 1) {
4806 cERROR(1, "num_referrals: must be at least > 0,"
4807 "but we get num_referrals = %d\n", *num_of_nodes);
4808 rc = -EINVAL;
4809 goto parse_DFS_referrals_exit;
4810 }
4811
4812 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4813 if (ref->VersionNumber != cpu_to_le16(3)) {
4814 cERROR(1, "Referrals of V%d version are not supported,"
4815 "should be V3", le16_to_cpu(ref->VersionNumber));
4816 rc = -EINVAL;
4817 goto parse_DFS_referrals_exit;
4818 }
4819
4820 /* get the upper boundary of the resp buffer */
4821 data_end = (char *)(&(pSMBr->PathConsumed)) +
4822 le16_to_cpu(pSMBr->t2.DataCount);
4823
4824 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4825 *num_of_nodes,
4826 le32_to_cpu(pSMBr->DFSFlags));
4827
4828 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4829 *num_of_nodes, GFP_KERNEL);
4830 if (*target_nodes == NULL) {
4831 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4832 rc = -ENOMEM;
4833 goto parse_DFS_referrals_exit;
4834 }
4835
4836 /* collect necessary data from referrals */
4837 for (i = 0; i < *num_of_nodes; i++) {
4838 char *temp;
4839 int max_len;
4840 struct dfs_info3_param *node = (*target_nodes)+i;
4841
4842 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4843 if (is_unicode) {
4844 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4845 GFP_KERNEL);
4846 if (tmp == NULL) {
4847 rc = -ENOMEM;
4848 goto parse_DFS_referrals_exit;
4849 }
4850 cifsConvertToUTF16((__le16 *) tmp, searchName,
4851 PATH_MAX, nls_codepage, remap);
4852 node->path_consumed = cifs_utf16_bytes(tmp,
4853 le16_to_cpu(pSMBr->PathConsumed),
4854 nls_codepage);
4855 kfree(tmp);
4856 } else
4857 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4858
4859 node->server_type = le16_to_cpu(ref->ServerType);
4860 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4861
4862 /* copy DfsPath */
4863 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4864 max_len = data_end - temp;
4865 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4866 is_unicode, nls_codepage);
4867 if (!node->path_name) {
4868 rc = -ENOMEM;
4869 goto parse_DFS_referrals_exit;
4870 }
4871
4872 /* copy link target UNC */
4873 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4874 max_len = data_end - temp;
4875 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4876 is_unicode, nls_codepage);
4877 if (!node->node_name) {
4878 rc = -ENOMEM;
4879 goto parse_DFS_referrals_exit;
4880 }
4881
4882 ref++;
4883 }
4884
4885 parse_DFS_referrals_exit:
4886 if (rc) {
4887 free_dfs_info_array(*target_nodes, *num_of_nodes);
4888 *target_nodes = NULL;
4889 *num_of_nodes = 0;
4890 }
4891 return rc;
4892 }
4893
4894 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)4895 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4896 const unsigned char *searchName,
4897 struct dfs_info3_param **target_nodes,
4898 unsigned int *num_of_nodes,
4899 const struct nls_table *nls_codepage, int remap)
4900 {
4901 /* TRANS2_GET_DFS_REFERRAL */
4902 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4903 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4904 int rc = 0;
4905 int bytes_returned;
4906 int name_len;
4907 __u16 params, byte_count;
4908 *num_of_nodes = 0;
4909 *target_nodes = NULL;
4910
4911 cFYI(1, "In GetDFSRefer the path %s", searchName);
4912 if (ses == NULL)
4913 return -ENODEV;
4914 getDFSRetry:
4915 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4916 (void **) &pSMBr);
4917 if (rc)
4918 return rc;
4919
4920 /* server pointer checked in called function,
4921 but should never be null here anyway */
4922 pSMB->hdr.Mid = GetNextMid(ses->server);
4923 pSMB->hdr.Tid = ses->ipc_tid;
4924 pSMB->hdr.Uid = ses->Suid;
4925 if (ses->capabilities & CAP_STATUS32)
4926 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4927 if (ses->capabilities & CAP_DFS)
4928 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4929
4930 if (ses->capabilities & CAP_UNICODE) {
4931 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4932 name_len =
4933 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4934 searchName, PATH_MAX, nls_codepage,
4935 remap);
4936 name_len++; /* trailing null */
4937 name_len *= 2;
4938 } else { /* BB improve the check for buffer overruns BB */
4939 name_len = strnlen(searchName, PATH_MAX);
4940 name_len++; /* trailing null */
4941 strncpy(pSMB->RequestFileName, searchName, name_len);
4942 }
4943
4944 if (ses->server) {
4945 if (ses->server->sec_mode &
4946 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4947 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4948 }
4949
4950 pSMB->hdr.Uid = ses->Suid;
4951
4952 params = 2 /* level */ + name_len /*includes null */ ;
4953 pSMB->TotalDataCount = 0;
4954 pSMB->DataCount = 0;
4955 pSMB->DataOffset = 0;
4956 pSMB->MaxParameterCount = 0;
4957 /* BB find exact max SMB PDU from sess structure BB */
4958 pSMB->MaxDataCount = cpu_to_le16(4000);
4959 pSMB->MaxSetupCount = 0;
4960 pSMB->Reserved = 0;
4961 pSMB->Flags = 0;
4962 pSMB->Timeout = 0;
4963 pSMB->Reserved2 = 0;
4964 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4965 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4966 pSMB->SetupCount = 1;
4967 pSMB->Reserved3 = 0;
4968 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4969 byte_count = params + 3 /* pad */ ;
4970 pSMB->ParameterCount = cpu_to_le16(params);
4971 pSMB->TotalParameterCount = pSMB->ParameterCount;
4972 pSMB->MaxReferralLevel = cpu_to_le16(3);
4973 inc_rfc1001_len(pSMB, byte_count);
4974 pSMB->ByteCount = cpu_to_le16(byte_count);
4975
4976 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4978 if (rc) {
4979 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4980 goto GetDFSRefExit;
4981 }
4982 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4983
4984 /* BB Also check if enough total bytes returned? */
4985 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4986 rc = -EIO; /* bad smb */
4987 goto GetDFSRefExit;
4988 }
4989
4990 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4991 get_bcc(&pSMBr->hdr),
4992 le16_to_cpu(pSMBr->t2.DataOffset));
4993
4994 /* parse returned result into more usable form */
4995 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4996 target_nodes, nls_codepage, remap,
4997 searchName);
4998
4999 GetDFSRefExit:
5000 cifs_buf_release(pSMB);
5001
5002 if (rc == -EAGAIN)
5003 goto getDFSRetry;
5004
5005 return rc;
5006 }
5007
5008 /* Query File System Info such as free space to old servers such as Win 9x */
5009 int
SMBOldQFSInfo(const int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5010 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
5011 {
5012 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
5013 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5014 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5015 FILE_SYSTEM_ALLOC_INFO *response_data;
5016 int rc = 0;
5017 int bytes_returned = 0;
5018 __u16 params, byte_count;
5019
5020 cFYI(1, "OldQFSInfo");
5021 oldQFSInfoRetry:
5022 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5023 (void **) &pSMBr);
5024 if (rc)
5025 return rc;
5026
5027 params = 2; /* level */
5028 pSMB->TotalDataCount = 0;
5029 pSMB->MaxParameterCount = cpu_to_le16(2);
5030 pSMB->MaxDataCount = cpu_to_le16(1000);
5031 pSMB->MaxSetupCount = 0;
5032 pSMB->Reserved = 0;
5033 pSMB->Flags = 0;
5034 pSMB->Timeout = 0;
5035 pSMB->Reserved2 = 0;
5036 byte_count = params + 1 /* pad */ ;
5037 pSMB->TotalParameterCount = cpu_to_le16(params);
5038 pSMB->ParameterCount = pSMB->TotalParameterCount;
5039 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5040 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5041 pSMB->DataCount = 0;
5042 pSMB->DataOffset = 0;
5043 pSMB->SetupCount = 1;
5044 pSMB->Reserved3 = 0;
5045 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5046 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
5047 inc_rfc1001_len(pSMB, byte_count);
5048 pSMB->ByteCount = cpu_to_le16(byte_count);
5049
5050 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5051 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5052 if (rc) {
5053 cFYI(1, "Send error in QFSInfo = %d", rc);
5054 } else { /* decode response */
5055 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5056
5057 if (rc || get_bcc(&pSMBr->hdr) < 18)
5058 rc = -EIO; /* bad smb */
5059 else {
5060 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5061 cFYI(1, "qfsinf resp BCC: %d Offset %d",
5062 get_bcc(&pSMBr->hdr), data_offset);
5063
5064 response_data = (FILE_SYSTEM_ALLOC_INFO *)
5065 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5066 FSData->f_bsize =
5067 le16_to_cpu(response_data->BytesPerSector) *
5068 le32_to_cpu(response_data->
5069 SectorsPerAllocationUnit);
5070 FSData->f_blocks =
5071 le32_to_cpu(response_data->TotalAllocationUnits);
5072 FSData->f_bfree = FSData->f_bavail =
5073 le32_to_cpu(response_data->FreeAllocationUnits);
5074 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5075 (unsigned long long)FSData->f_blocks,
5076 (unsigned long long)FSData->f_bfree,
5077 FSData->f_bsize);
5078 }
5079 }
5080 cifs_buf_release(pSMB);
5081
5082 if (rc == -EAGAIN)
5083 goto oldQFSInfoRetry;
5084
5085 return rc;
5086 }
5087
5088 int
CIFSSMBQFSInfo(const int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5089 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
5090 {
5091 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5092 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5093 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5094 FILE_SYSTEM_INFO *response_data;
5095 int rc = 0;
5096 int bytes_returned = 0;
5097 __u16 params, byte_count;
5098
5099 cFYI(1, "In QFSInfo");
5100 QFSInfoRetry:
5101 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5102 (void **) &pSMBr);
5103 if (rc)
5104 return rc;
5105
5106 params = 2; /* level */
5107 pSMB->TotalDataCount = 0;
5108 pSMB->MaxParameterCount = cpu_to_le16(2);
5109 pSMB->MaxDataCount = cpu_to_le16(1000);
5110 pSMB->MaxSetupCount = 0;
5111 pSMB->Reserved = 0;
5112 pSMB->Flags = 0;
5113 pSMB->Timeout = 0;
5114 pSMB->Reserved2 = 0;
5115 byte_count = params + 1 /* pad */ ;
5116 pSMB->TotalParameterCount = cpu_to_le16(params);
5117 pSMB->ParameterCount = pSMB->TotalParameterCount;
5118 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5119 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5120 pSMB->DataCount = 0;
5121 pSMB->DataOffset = 0;
5122 pSMB->SetupCount = 1;
5123 pSMB->Reserved3 = 0;
5124 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5125 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5126 inc_rfc1001_len(pSMB, byte_count);
5127 pSMB->ByteCount = cpu_to_le16(byte_count);
5128
5129 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5130 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5131 if (rc) {
5132 cFYI(1, "Send error in QFSInfo = %d", rc);
5133 } else { /* decode response */
5134 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5135
5136 if (rc || get_bcc(&pSMBr->hdr) < 24)
5137 rc = -EIO; /* bad smb */
5138 else {
5139 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5140
5141 response_data =
5142 (FILE_SYSTEM_INFO
5143 *) (((char *) &pSMBr->hdr.Protocol) +
5144 data_offset);
5145 FSData->f_bsize =
5146 le32_to_cpu(response_data->BytesPerSector) *
5147 le32_to_cpu(response_data->
5148 SectorsPerAllocationUnit);
5149 FSData->f_blocks =
5150 le64_to_cpu(response_data->TotalAllocationUnits);
5151 FSData->f_bfree = FSData->f_bavail =
5152 le64_to_cpu(response_data->FreeAllocationUnits);
5153 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
5154 (unsigned long long)FSData->f_blocks,
5155 (unsigned long long)FSData->f_bfree,
5156 FSData->f_bsize);
5157 }
5158 }
5159 cifs_buf_release(pSMB);
5160
5161 if (rc == -EAGAIN)
5162 goto QFSInfoRetry;
5163
5164 return rc;
5165 }
5166
5167 int
CIFSSMBQFSAttributeInfo(const int xid,struct cifs_tcon * tcon)5168 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
5169 {
5170 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5171 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5172 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5173 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5174 int rc = 0;
5175 int bytes_returned = 0;
5176 __u16 params, byte_count;
5177
5178 cFYI(1, "In QFSAttributeInfo");
5179 QFSAttributeRetry:
5180 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5181 (void **) &pSMBr);
5182 if (rc)
5183 return rc;
5184
5185 params = 2; /* level */
5186 pSMB->TotalDataCount = 0;
5187 pSMB->MaxParameterCount = cpu_to_le16(2);
5188 /* BB find exact max SMB PDU from sess structure BB */
5189 pSMB->MaxDataCount = cpu_to_le16(1000);
5190 pSMB->MaxSetupCount = 0;
5191 pSMB->Reserved = 0;
5192 pSMB->Flags = 0;
5193 pSMB->Timeout = 0;
5194 pSMB->Reserved2 = 0;
5195 byte_count = params + 1 /* pad */ ;
5196 pSMB->TotalParameterCount = cpu_to_le16(params);
5197 pSMB->ParameterCount = pSMB->TotalParameterCount;
5198 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5199 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5200 pSMB->DataCount = 0;
5201 pSMB->DataOffset = 0;
5202 pSMB->SetupCount = 1;
5203 pSMB->Reserved3 = 0;
5204 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5205 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5206 inc_rfc1001_len(pSMB, byte_count);
5207 pSMB->ByteCount = cpu_to_le16(byte_count);
5208
5209 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5210 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5211 if (rc) {
5212 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5213 } else { /* decode response */
5214 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5215
5216 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5217 /* BB also check if enough bytes returned */
5218 rc = -EIO; /* bad smb */
5219 } else {
5220 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5221 response_data =
5222 (FILE_SYSTEM_ATTRIBUTE_INFO
5223 *) (((char *) &pSMBr->hdr.Protocol) +
5224 data_offset);
5225 memcpy(&tcon->fsAttrInfo, response_data,
5226 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5227 }
5228 }
5229 cifs_buf_release(pSMB);
5230
5231 if (rc == -EAGAIN)
5232 goto QFSAttributeRetry;
5233
5234 return rc;
5235 }
5236
5237 int
CIFSSMBQFSDeviceInfo(const int xid,struct cifs_tcon * tcon)5238 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
5239 {
5240 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5241 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5242 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5243 FILE_SYSTEM_DEVICE_INFO *response_data;
5244 int rc = 0;
5245 int bytes_returned = 0;
5246 __u16 params, byte_count;
5247
5248 cFYI(1, "In QFSDeviceInfo");
5249 QFSDeviceRetry:
5250 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5251 (void **) &pSMBr);
5252 if (rc)
5253 return rc;
5254
5255 params = 2; /* level */
5256 pSMB->TotalDataCount = 0;
5257 pSMB->MaxParameterCount = cpu_to_le16(2);
5258 /* BB find exact max SMB PDU from sess structure BB */
5259 pSMB->MaxDataCount = cpu_to_le16(1000);
5260 pSMB->MaxSetupCount = 0;
5261 pSMB->Reserved = 0;
5262 pSMB->Flags = 0;
5263 pSMB->Timeout = 0;
5264 pSMB->Reserved2 = 0;
5265 byte_count = params + 1 /* pad */ ;
5266 pSMB->TotalParameterCount = cpu_to_le16(params);
5267 pSMB->ParameterCount = pSMB->TotalParameterCount;
5268 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5269 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5270
5271 pSMB->DataCount = 0;
5272 pSMB->DataOffset = 0;
5273 pSMB->SetupCount = 1;
5274 pSMB->Reserved3 = 0;
5275 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5276 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5277 inc_rfc1001_len(pSMB, byte_count);
5278 pSMB->ByteCount = cpu_to_le16(byte_count);
5279
5280 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5281 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5282 if (rc) {
5283 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5284 } else { /* decode response */
5285 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5286
5287 if (rc || get_bcc(&pSMBr->hdr) <
5288 sizeof(FILE_SYSTEM_DEVICE_INFO))
5289 rc = -EIO; /* bad smb */
5290 else {
5291 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5292 response_data =
5293 (FILE_SYSTEM_DEVICE_INFO *)
5294 (((char *) &pSMBr->hdr.Protocol) +
5295 data_offset);
5296 memcpy(&tcon->fsDevInfo, response_data,
5297 sizeof(FILE_SYSTEM_DEVICE_INFO));
5298 }
5299 }
5300 cifs_buf_release(pSMB);
5301
5302 if (rc == -EAGAIN)
5303 goto QFSDeviceRetry;
5304
5305 return rc;
5306 }
5307
5308 int
CIFSSMBQFSUnixInfo(const int xid,struct cifs_tcon * tcon)5309 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
5310 {
5311 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5312 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5313 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5314 FILE_SYSTEM_UNIX_INFO *response_data;
5315 int rc = 0;
5316 int bytes_returned = 0;
5317 __u16 params, byte_count;
5318
5319 cFYI(1, "In QFSUnixInfo");
5320 QFSUnixRetry:
5321 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5322 (void **) &pSMB, (void **) &pSMBr);
5323 if (rc)
5324 return rc;
5325
5326 params = 2; /* level */
5327 pSMB->TotalDataCount = 0;
5328 pSMB->DataCount = 0;
5329 pSMB->DataOffset = 0;
5330 pSMB->MaxParameterCount = cpu_to_le16(2);
5331 /* BB find exact max SMB PDU from sess structure BB */
5332 pSMB->MaxDataCount = cpu_to_le16(100);
5333 pSMB->MaxSetupCount = 0;
5334 pSMB->Reserved = 0;
5335 pSMB->Flags = 0;
5336 pSMB->Timeout = 0;
5337 pSMB->Reserved2 = 0;
5338 byte_count = params + 1 /* pad */ ;
5339 pSMB->ParameterCount = cpu_to_le16(params);
5340 pSMB->TotalParameterCount = pSMB->ParameterCount;
5341 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5342 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5343 pSMB->SetupCount = 1;
5344 pSMB->Reserved3 = 0;
5345 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5346 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5347 inc_rfc1001_len(pSMB, byte_count);
5348 pSMB->ByteCount = cpu_to_le16(byte_count);
5349
5350 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5351 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5352 if (rc) {
5353 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5354 } else { /* decode response */
5355 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5356
5357 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5358 rc = -EIO; /* bad smb */
5359 } else {
5360 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5361 response_data =
5362 (FILE_SYSTEM_UNIX_INFO
5363 *) (((char *) &pSMBr->hdr.Protocol) +
5364 data_offset);
5365 memcpy(&tcon->fsUnixInfo, response_data,
5366 sizeof(FILE_SYSTEM_UNIX_INFO));
5367 }
5368 }
5369 cifs_buf_release(pSMB);
5370
5371 if (rc == -EAGAIN)
5372 goto QFSUnixRetry;
5373
5374
5375 return rc;
5376 }
5377
5378 int
CIFSSMBSetFSUnixInfo(const int xid,struct cifs_tcon * tcon,__u64 cap)5379 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
5380 {
5381 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5382 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5383 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5384 int rc = 0;
5385 int bytes_returned = 0;
5386 __u16 params, param_offset, offset, byte_count;
5387
5388 cFYI(1, "In SETFSUnixInfo");
5389 SETFSUnixRetry:
5390 /* BB switch to small buf init to save memory */
5391 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5392 (void **) &pSMB, (void **) &pSMBr);
5393 if (rc)
5394 return rc;
5395
5396 params = 4; /* 2 bytes zero followed by info level. */
5397 pSMB->MaxSetupCount = 0;
5398 pSMB->Reserved = 0;
5399 pSMB->Flags = 0;
5400 pSMB->Timeout = 0;
5401 pSMB->Reserved2 = 0;
5402 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5403 - 4;
5404 offset = param_offset + params;
5405
5406 pSMB->MaxParameterCount = cpu_to_le16(4);
5407 /* BB find exact max SMB PDU from sess structure BB */
5408 pSMB->MaxDataCount = cpu_to_le16(100);
5409 pSMB->SetupCount = 1;
5410 pSMB->Reserved3 = 0;
5411 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5412 byte_count = 1 /* pad */ + params + 12;
5413
5414 pSMB->DataCount = cpu_to_le16(12);
5415 pSMB->ParameterCount = cpu_to_le16(params);
5416 pSMB->TotalDataCount = pSMB->DataCount;
5417 pSMB->TotalParameterCount = pSMB->ParameterCount;
5418 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5419 pSMB->DataOffset = cpu_to_le16(offset);
5420
5421 /* Params. */
5422 pSMB->FileNum = 0;
5423 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5424
5425 /* Data. */
5426 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5427 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5428 pSMB->ClientUnixCap = cpu_to_le64(cap);
5429
5430 inc_rfc1001_len(pSMB, byte_count);
5431 pSMB->ByteCount = cpu_to_le16(byte_count);
5432
5433 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5434 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5435 if (rc) {
5436 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5437 } else { /* decode response */
5438 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5439 if (rc)
5440 rc = -EIO; /* bad smb */
5441 }
5442 cifs_buf_release(pSMB);
5443
5444 if (rc == -EAGAIN)
5445 goto SETFSUnixRetry;
5446
5447 return rc;
5448 }
5449
5450
5451
5452 int
CIFSSMBQFSPosixInfo(const int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5453 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5454 struct kstatfs *FSData)
5455 {
5456 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5457 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5458 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5459 FILE_SYSTEM_POSIX_INFO *response_data;
5460 int rc = 0;
5461 int bytes_returned = 0;
5462 __u16 params, byte_count;
5463
5464 cFYI(1, "In QFSPosixInfo");
5465 QFSPosixRetry:
5466 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5467 (void **) &pSMBr);
5468 if (rc)
5469 return rc;
5470
5471 params = 2; /* level */
5472 pSMB->TotalDataCount = 0;
5473 pSMB->DataCount = 0;
5474 pSMB->DataOffset = 0;
5475 pSMB->MaxParameterCount = cpu_to_le16(2);
5476 /* BB find exact max SMB PDU from sess structure BB */
5477 pSMB->MaxDataCount = cpu_to_le16(100);
5478 pSMB->MaxSetupCount = 0;
5479 pSMB->Reserved = 0;
5480 pSMB->Flags = 0;
5481 pSMB->Timeout = 0;
5482 pSMB->Reserved2 = 0;
5483 byte_count = params + 1 /* pad */ ;
5484 pSMB->ParameterCount = cpu_to_le16(params);
5485 pSMB->TotalParameterCount = pSMB->ParameterCount;
5486 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5487 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5488 pSMB->SetupCount = 1;
5489 pSMB->Reserved3 = 0;
5490 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5491 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5492 inc_rfc1001_len(pSMB, byte_count);
5493 pSMB->ByteCount = cpu_to_le16(byte_count);
5494
5495 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5496 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5497 if (rc) {
5498 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5499 } else { /* decode response */
5500 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5501
5502 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5503 rc = -EIO; /* bad smb */
5504 } else {
5505 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5506 response_data =
5507 (FILE_SYSTEM_POSIX_INFO
5508 *) (((char *) &pSMBr->hdr.Protocol) +
5509 data_offset);
5510 FSData->f_bsize =
5511 le32_to_cpu(response_data->BlockSize);
5512 FSData->f_blocks =
5513 le64_to_cpu(response_data->TotalBlocks);
5514 FSData->f_bfree =
5515 le64_to_cpu(response_data->BlocksAvail);
5516 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5517 FSData->f_bavail = FSData->f_bfree;
5518 } else {
5519 FSData->f_bavail =
5520 le64_to_cpu(response_data->UserBlocksAvail);
5521 }
5522 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5523 FSData->f_files =
5524 le64_to_cpu(response_data->TotalFileNodes);
5525 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5526 FSData->f_ffree =
5527 le64_to_cpu(response_data->FreeFileNodes);
5528 }
5529 }
5530 cifs_buf_release(pSMB);
5531
5532 if (rc == -EAGAIN)
5533 goto QFSPosixRetry;
5534
5535 return rc;
5536 }
5537
5538
5539 /* We can not use write of zero bytes trick to
5540 set file size due to need for large file support. Also note that
5541 this SetPathInfo is preferred to SetFileInfo based method in next
5542 routine which is only needed to work around a sharing violation bug
5543 in Samba which this routine can run into */
5544
5545 int
CIFSSMBSetEOF(const int xid,struct cifs_tcon * tcon,const char * fileName,__u64 size,bool SetAllocation,const struct nls_table * nls_codepage,int remap)5546 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5547 __u64 size, bool SetAllocation,
5548 const struct nls_table *nls_codepage, int remap)
5549 {
5550 struct smb_com_transaction2_spi_req *pSMB = NULL;
5551 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5552 struct file_end_of_file_info *parm_data;
5553 int name_len;
5554 int rc = 0;
5555 int bytes_returned = 0;
5556 __u16 params, byte_count, data_count, param_offset, offset;
5557
5558 cFYI(1, "In SetEOF");
5559 SetEOFRetry:
5560 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5561 (void **) &pSMBr);
5562 if (rc)
5563 return rc;
5564
5565 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5566 name_len =
5567 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5568 PATH_MAX, nls_codepage, remap);
5569 name_len++; /* trailing null */
5570 name_len *= 2;
5571 } else { /* BB improve the check for buffer overruns BB */
5572 name_len = strnlen(fileName, PATH_MAX);
5573 name_len++; /* trailing null */
5574 strncpy(pSMB->FileName, fileName, name_len);
5575 }
5576 params = 6 + name_len;
5577 data_count = sizeof(struct file_end_of_file_info);
5578 pSMB->MaxParameterCount = cpu_to_le16(2);
5579 pSMB->MaxDataCount = cpu_to_le16(4100);
5580 pSMB->MaxSetupCount = 0;
5581 pSMB->Reserved = 0;
5582 pSMB->Flags = 0;
5583 pSMB->Timeout = 0;
5584 pSMB->Reserved2 = 0;
5585 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5586 InformationLevel) - 4;
5587 offset = param_offset + params;
5588 if (SetAllocation) {
5589 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5590 pSMB->InformationLevel =
5591 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5592 else
5593 pSMB->InformationLevel =
5594 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5595 } else /* Set File Size */ {
5596 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5597 pSMB->InformationLevel =
5598 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5599 else
5600 pSMB->InformationLevel =
5601 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5602 }
5603
5604 parm_data =
5605 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5606 offset);
5607 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5608 pSMB->DataOffset = cpu_to_le16(offset);
5609 pSMB->SetupCount = 1;
5610 pSMB->Reserved3 = 0;
5611 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5612 byte_count = 3 /* pad */ + params + data_count;
5613 pSMB->DataCount = cpu_to_le16(data_count);
5614 pSMB->TotalDataCount = pSMB->DataCount;
5615 pSMB->ParameterCount = cpu_to_le16(params);
5616 pSMB->TotalParameterCount = pSMB->ParameterCount;
5617 pSMB->Reserved4 = 0;
5618 inc_rfc1001_len(pSMB, byte_count);
5619 parm_data->FileSize = cpu_to_le64(size);
5620 pSMB->ByteCount = cpu_to_le16(byte_count);
5621 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5622 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5623 if (rc)
5624 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5625
5626 cifs_buf_release(pSMB);
5627
5628 if (rc == -EAGAIN)
5629 goto SetEOFRetry;
5630
5631 return rc;
5632 }
5633
5634 int
CIFSSMBSetFileSize(const int xid,struct cifs_tcon * tcon,__u64 size,__u16 fid,__u32 pid_of_opener,bool SetAllocation)5635 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5636 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5637 {
5638 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5639 struct file_end_of_file_info *parm_data;
5640 int rc = 0;
5641 __u16 params, param_offset, offset, byte_count, count;
5642
5643 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5644 (long long)size);
5645 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5646
5647 if (rc)
5648 return rc;
5649
5650 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5651 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5652
5653 params = 6;
5654 pSMB->MaxSetupCount = 0;
5655 pSMB->Reserved = 0;
5656 pSMB->Flags = 0;
5657 pSMB->Timeout = 0;
5658 pSMB->Reserved2 = 0;
5659 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5660 offset = param_offset + params;
5661
5662 count = sizeof(struct file_end_of_file_info);
5663 pSMB->MaxParameterCount = cpu_to_le16(2);
5664 /* BB find exact max SMB PDU from sess structure BB */
5665 pSMB->MaxDataCount = cpu_to_le16(1000);
5666 pSMB->SetupCount = 1;
5667 pSMB->Reserved3 = 0;
5668 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5669 byte_count = 3 /* pad */ + params + count;
5670 pSMB->DataCount = cpu_to_le16(count);
5671 pSMB->ParameterCount = cpu_to_le16(params);
5672 pSMB->TotalDataCount = pSMB->DataCount;
5673 pSMB->TotalParameterCount = pSMB->ParameterCount;
5674 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5675 parm_data =
5676 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5677 + offset);
5678 pSMB->DataOffset = cpu_to_le16(offset);
5679 parm_data->FileSize = cpu_to_le64(size);
5680 pSMB->Fid = fid;
5681 if (SetAllocation) {
5682 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5683 pSMB->InformationLevel =
5684 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5685 else
5686 pSMB->InformationLevel =
5687 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5688 } else /* Set File Size */ {
5689 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5690 pSMB->InformationLevel =
5691 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5692 else
5693 pSMB->InformationLevel =
5694 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5695 }
5696 pSMB->Reserved4 = 0;
5697 inc_rfc1001_len(pSMB, byte_count);
5698 pSMB->ByteCount = cpu_to_le16(byte_count);
5699 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5700 if (rc) {
5701 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5702 }
5703
5704 /* Note: On -EAGAIN error only caller can retry on handle based calls
5705 since file handle passed in no longer valid */
5706
5707 return rc;
5708 }
5709
5710 /* Some legacy servers such as NT4 require that the file times be set on
5711 an open handle, rather than by pathname - this is awkward due to
5712 potential access conflicts on the open, but it is unavoidable for these
5713 old servers since the only other choice is to go from 100 nanosecond DCE
5714 time and resort to the original setpathinfo level which takes the ancient
5715 DOS time format with 2 second granularity */
5716 int
CIFSSMBSetFileInfo(const int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5717 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5718 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5719 {
5720 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5721 char *data_offset;
5722 int rc = 0;
5723 __u16 params, param_offset, offset, byte_count, count;
5724
5725 cFYI(1, "Set Times (via SetFileInfo)");
5726 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5727
5728 if (rc)
5729 return rc;
5730
5731 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5732 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5733
5734 params = 6;
5735 pSMB->MaxSetupCount = 0;
5736 pSMB->Reserved = 0;
5737 pSMB->Flags = 0;
5738 pSMB->Timeout = 0;
5739 pSMB->Reserved2 = 0;
5740 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5741 offset = param_offset + params;
5742
5743 data_offset = (char *)pSMB +
5744 offsetof(struct smb_hdr, Protocol) + offset;
5745
5746 count = sizeof(FILE_BASIC_INFO);
5747 pSMB->MaxParameterCount = cpu_to_le16(2);
5748 /* BB find max SMB PDU from sess */
5749 pSMB->MaxDataCount = cpu_to_le16(1000);
5750 pSMB->SetupCount = 1;
5751 pSMB->Reserved3 = 0;
5752 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5753 byte_count = 3 /* pad */ + params + count;
5754 pSMB->DataCount = cpu_to_le16(count);
5755 pSMB->ParameterCount = cpu_to_le16(params);
5756 pSMB->TotalDataCount = pSMB->DataCount;
5757 pSMB->TotalParameterCount = pSMB->ParameterCount;
5758 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5759 pSMB->DataOffset = cpu_to_le16(offset);
5760 pSMB->Fid = fid;
5761 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5762 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5763 else
5764 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5765 pSMB->Reserved4 = 0;
5766 inc_rfc1001_len(pSMB, byte_count);
5767 pSMB->ByteCount = cpu_to_le16(byte_count);
5768 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5769 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5770 if (rc)
5771 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5772
5773 /* Note: On -EAGAIN error only caller can retry on handle based calls
5774 since file handle passed in no longer valid */
5775
5776 return rc;
5777 }
5778
5779 int
CIFSSMBSetFileDisposition(const int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5780 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5781 bool delete_file, __u16 fid, __u32 pid_of_opener)
5782 {
5783 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5784 char *data_offset;
5785 int rc = 0;
5786 __u16 params, param_offset, offset, byte_count, count;
5787
5788 cFYI(1, "Set File Disposition (via SetFileInfo)");
5789 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5790
5791 if (rc)
5792 return rc;
5793
5794 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5795 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5796
5797 params = 6;
5798 pSMB->MaxSetupCount = 0;
5799 pSMB->Reserved = 0;
5800 pSMB->Flags = 0;
5801 pSMB->Timeout = 0;
5802 pSMB->Reserved2 = 0;
5803 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5804 offset = param_offset + params;
5805
5806 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5807
5808 count = 1;
5809 pSMB->MaxParameterCount = cpu_to_le16(2);
5810 /* BB find max SMB PDU from sess */
5811 pSMB->MaxDataCount = cpu_to_le16(1000);
5812 pSMB->SetupCount = 1;
5813 pSMB->Reserved3 = 0;
5814 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5815 byte_count = 3 /* pad */ + params + count;
5816 pSMB->DataCount = cpu_to_le16(count);
5817 pSMB->ParameterCount = cpu_to_le16(params);
5818 pSMB->TotalDataCount = pSMB->DataCount;
5819 pSMB->TotalParameterCount = pSMB->ParameterCount;
5820 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5821 pSMB->DataOffset = cpu_to_le16(offset);
5822 pSMB->Fid = fid;
5823 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5824 pSMB->Reserved4 = 0;
5825 inc_rfc1001_len(pSMB, byte_count);
5826 pSMB->ByteCount = cpu_to_le16(byte_count);
5827 *data_offset = delete_file ? 1 : 0;
5828 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5829 if (rc)
5830 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5831
5832 return rc;
5833 }
5834
5835 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)5836 CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
5837 const char *fileName, const FILE_BASIC_INFO *data,
5838 const struct nls_table *nls_codepage, int remap)
5839 {
5840 TRANSACTION2_SPI_REQ *pSMB = NULL;
5841 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5842 int name_len;
5843 int rc = 0;
5844 int bytes_returned = 0;
5845 char *data_offset;
5846 __u16 params, param_offset, offset, byte_count, count;
5847
5848 cFYI(1, "In SetTimes");
5849
5850 SetTimesRetry:
5851 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5852 (void **) &pSMBr);
5853 if (rc)
5854 return rc;
5855
5856 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5857 name_len =
5858 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5859 PATH_MAX, nls_codepage, remap);
5860 name_len++; /* trailing null */
5861 name_len *= 2;
5862 } else { /* BB improve the check for buffer overruns BB */
5863 name_len = strnlen(fileName, PATH_MAX);
5864 name_len++; /* trailing null */
5865 strncpy(pSMB->FileName, fileName, name_len);
5866 }
5867
5868 params = 6 + name_len;
5869 count = sizeof(FILE_BASIC_INFO);
5870 pSMB->MaxParameterCount = cpu_to_le16(2);
5871 /* BB find max SMB PDU from sess structure BB */
5872 pSMB->MaxDataCount = cpu_to_le16(1000);
5873 pSMB->MaxSetupCount = 0;
5874 pSMB->Reserved = 0;
5875 pSMB->Flags = 0;
5876 pSMB->Timeout = 0;
5877 pSMB->Reserved2 = 0;
5878 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5879 InformationLevel) - 4;
5880 offset = param_offset + params;
5881 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5882 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5883 pSMB->DataOffset = cpu_to_le16(offset);
5884 pSMB->SetupCount = 1;
5885 pSMB->Reserved3 = 0;
5886 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5887 byte_count = 3 /* pad */ + params + count;
5888
5889 pSMB->DataCount = cpu_to_le16(count);
5890 pSMB->ParameterCount = cpu_to_le16(params);
5891 pSMB->TotalDataCount = pSMB->DataCount;
5892 pSMB->TotalParameterCount = pSMB->ParameterCount;
5893 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5894 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5895 else
5896 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5897 pSMB->Reserved4 = 0;
5898 inc_rfc1001_len(pSMB, byte_count);
5899 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5900 pSMB->ByteCount = cpu_to_le16(byte_count);
5901 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5902 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5903 if (rc)
5904 cFYI(1, "SetPathInfo (times) returned %d", rc);
5905
5906 cifs_buf_release(pSMB);
5907
5908 if (rc == -EAGAIN)
5909 goto SetTimesRetry;
5910
5911 return rc;
5912 }
5913
5914 /* Can not be used to set time stamps yet (due to old DOS time format) */
5915 /* Can be used to set attributes */
5916 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5917 handling it anyway and NT4 was what we thought it would be needed for
5918 Do not delete it until we prove whether needed for Win9x though */
5919 int
5920 CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
5921 __u16 dos_attrs, const struct nls_table *nls_codepage)
5922 {
5923 SETATTR_REQ *pSMB = NULL;
5924 SETATTR_RSP *pSMBr = NULL;
5925 int rc = 0;
5926 int bytes_returned;
5927 int name_len;
5928
5929 cFYI(1, "In SetAttrLegacy");
5930
5931 SetAttrLgcyRetry:
5932 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5933 (void **) &pSMBr);
5934 if (rc)
5935 return rc;
5936
5937 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5938 name_len =
5939 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5940 PATH_MAX, nls_codepage);
5941 name_len++; /* trailing null */
5942 name_len *= 2;
5943 } else { /* BB improve the check for buffer overruns BB */
5944 name_len = strnlen(fileName, PATH_MAX);
5945 name_len++; /* trailing null */
5946 strncpy(pSMB->fileName, fileName, name_len);
5947 }
5948 pSMB->attr = cpu_to_le16(dos_attrs);
5949 pSMB->BufferFormat = 0x04;
5950 inc_rfc1001_len(pSMB, name_len + 1);
5951 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5952 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5953 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5954 if (rc)
5955 cFYI(1, "Error in LegacySetAttr = %d", rc);
5956
5957 cifs_buf_release(pSMB);
5958
5959 if (rc == -EAGAIN)
5960 goto SetAttrLgcyRetry;
5961
5962 return rc;
5963 }
5964 #endif /* temporarily unneeded SetAttr legacy function */
5965
5966 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5967 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5968 const struct cifs_unix_set_info_args *args)
5969 {
5970 u64 mode = args->mode;
5971
5972 /*
5973 * Samba server ignores set of file size to zero due to bugs in some
5974 * older clients, but we should be precise - we use SetFileSize to
5975 * set file size and do not want to truncate file size to zero
5976 * accidentally as happened on one Samba server beta by putting
5977 * zero instead of -1 here
5978 */
5979 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5980 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5981 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5982 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5983 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5984 data_offset->Uid = cpu_to_le64(args->uid);
5985 data_offset->Gid = cpu_to_le64(args->gid);
5986 /* better to leave device as zero when it is */
5987 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5988 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5989 data_offset->Permissions = cpu_to_le64(mode);
5990
5991 if (S_ISREG(mode))
5992 data_offset->Type = cpu_to_le32(UNIX_FILE);
5993 else if (S_ISDIR(mode))
5994 data_offset->Type = cpu_to_le32(UNIX_DIR);
5995 else if (S_ISLNK(mode))
5996 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5997 else if (S_ISCHR(mode))
5998 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5999 else if (S_ISBLK(mode))
6000 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
6001 else if (S_ISFIFO(mode))
6002 data_offset->Type = cpu_to_le32(UNIX_FIFO);
6003 else if (S_ISSOCK(mode))
6004 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
6005 }
6006
6007 int
CIFSSMBUnixSetFileInfo(const int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)6008 CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
6009 const struct cifs_unix_set_info_args *args,
6010 u16 fid, u32 pid_of_opener)
6011 {
6012 struct smb_com_transaction2_sfi_req *pSMB = NULL;
6013 char *data_offset;
6014 int rc = 0;
6015 u16 params, param_offset, offset, byte_count, count;
6016
6017 cFYI(1, "Set Unix Info (via SetFileInfo)");
6018 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
6019
6020 if (rc)
6021 return rc;
6022
6023 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
6024 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
6025
6026 params = 6;
6027 pSMB->MaxSetupCount = 0;
6028 pSMB->Reserved = 0;
6029 pSMB->Flags = 0;
6030 pSMB->Timeout = 0;
6031 pSMB->Reserved2 = 0;
6032 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6033 offset = param_offset + params;
6034
6035 data_offset = (char *)pSMB +
6036 offsetof(struct smb_hdr, Protocol) + offset;
6037
6038 count = sizeof(FILE_UNIX_BASIC_INFO);
6039
6040 pSMB->MaxParameterCount = cpu_to_le16(2);
6041 /* BB find max SMB PDU from sess */
6042 pSMB->MaxDataCount = cpu_to_le16(1000);
6043 pSMB->SetupCount = 1;
6044 pSMB->Reserved3 = 0;
6045 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6046 byte_count = 3 /* pad */ + params + count;
6047 pSMB->DataCount = cpu_to_le16(count);
6048 pSMB->ParameterCount = cpu_to_le16(params);
6049 pSMB->TotalDataCount = pSMB->DataCount;
6050 pSMB->TotalParameterCount = pSMB->ParameterCount;
6051 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6052 pSMB->DataOffset = cpu_to_le16(offset);
6053 pSMB->Fid = fid;
6054 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6055 pSMB->Reserved4 = 0;
6056 inc_rfc1001_len(pSMB, byte_count);
6057 pSMB->ByteCount = cpu_to_le16(byte_count);
6058
6059 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6060
6061 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6062 if (rc)
6063 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
6064
6065 /* Note: On -EAGAIN error only caller can retry on handle based calls
6066 since file handle passed in no longer valid */
6067
6068 return rc;
6069 }
6070
6071 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)6072 CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
6073 const struct cifs_unix_set_info_args *args,
6074 const struct nls_table *nls_codepage, int remap)
6075 {
6076 TRANSACTION2_SPI_REQ *pSMB = NULL;
6077 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6078 int name_len;
6079 int rc = 0;
6080 int bytes_returned = 0;
6081 FILE_UNIX_BASIC_INFO *data_offset;
6082 __u16 params, param_offset, offset, count, byte_count;
6083
6084 cFYI(1, "In SetUID/GID/Mode");
6085 setPermsRetry:
6086 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6087 (void **) &pSMBr);
6088 if (rc)
6089 return rc;
6090
6091 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6092 name_len =
6093 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6094 PATH_MAX, nls_codepage, remap);
6095 name_len++; /* trailing null */
6096 name_len *= 2;
6097 } else { /* BB improve the check for buffer overruns BB */
6098 name_len = strnlen(fileName, PATH_MAX);
6099 name_len++; /* trailing null */
6100 strncpy(pSMB->FileName, fileName, name_len);
6101 }
6102
6103 params = 6 + name_len;
6104 count = sizeof(FILE_UNIX_BASIC_INFO);
6105 pSMB->MaxParameterCount = cpu_to_le16(2);
6106 /* BB find max SMB PDU from sess structure BB */
6107 pSMB->MaxDataCount = cpu_to_le16(1000);
6108 pSMB->MaxSetupCount = 0;
6109 pSMB->Reserved = 0;
6110 pSMB->Flags = 0;
6111 pSMB->Timeout = 0;
6112 pSMB->Reserved2 = 0;
6113 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6114 InformationLevel) - 4;
6115 offset = param_offset + params;
6116 data_offset =
6117 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6118 offset);
6119 memset(data_offset, 0, count);
6120 pSMB->DataOffset = cpu_to_le16(offset);
6121 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6122 pSMB->SetupCount = 1;
6123 pSMB->Reserved3 = 0;
6124 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6125 byte_count = 3 /* pad */ + params + count;
6126 pSMB->ParameterCount = cpu_to_le16(params);
6127 pSMB->DataCount = cpu_to_le16(count);
6128 pSMB->TotalParameterCount = pSMB->ParameterCount;
6129 pSMB->TotalDataCount = pSMB->DataCount;
6130 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6131 pSMB->Reserved4 = 0;
6132 inc_rfc1001_len(pSMB, byte_count);
6133
6134 cifs_fill_unix_set_info(data_offset, args);
6135
6136 pSMB->ByteCount = cpu_to_le16(byte_count);
6137 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6138 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6139 if (rc)
6140 cFYI(1, "SetPathInfo (perms) returned %d", rc);
6141
6142 cifs_buf_release(pSMB);
6143 if (rc == -EAGAIN)
6144 goto setPermsRetry;
6145 return rc;
6146 }
6147
6148 #ifdef CONFIG_CIFS_XATTR
6149 /*
6150 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6151 * function used by listxattr and getxattr type calls. When ea_name is set,
6152 * it looks for that attribute name and stuffs that value into the EAData
6153 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6154 * buffer. In both cases, the return value is either the length of the
6155 * resulting data or a negative error code. If EAData is a NULL pointer then
6156 * the data isn't copied to it, but the length is returned.
6157 */
6158 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)6159 CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
6160 const unsigned char *searchName, const unsigned char *ea_name,
6161 char *EAData, size_t buf_size,
6162 const struct nls_table *nls_codepage, int remap)
6163 {
6164 /* BB assumes one setup word */
6165 TRANSACTION2_QPI_REQ *pSMB = NULL;
6166 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6167 int rc = 0;
6168 int bytes_returned;
6169 int list_len;
6170 struct fealist *ea_response_data;
6171 struct fea *temp_fea;
6172 char *temp_ptr;
6173 char *end_of_smb;
6174 __u16 params, byte_count, data_offset;
6175 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6176
6177 cFYI(1, "In Query All EAs path %s", searchName);
6178 QAllEAsRetry:
6179 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6180 (void **) &pSMBr);
6181 if (rc)
6182 return rc;
6183
6184 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6185 list_len =
6186 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6187 PATH_MAX, nls_codepage, remap);
6188 list_len++; /* trailing null */
6189 list_len *= 2;
6190 } else { /* BB improve the check for buffer overruns BB */
6191 list_len = strnlen(searchName, PATH_MAX);
6192 list_len++; /* trailing null */
6193 strncpy(pSMB->FileName, searchName, list_len);
6194 }
6195
6196 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6197 pSMB->TotalDataCount = 0;
6198 pSMB->MaxParameterCount = cpu_to_le16(2);
6199 /* BB find exact max SMB PDU from sess structure BB */
6200 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6201 pSMB->MaxSetupCount = 0;
6202 pSMB->Reserved = 0;
6203 pSMB->Flags = 0;
6204 pSMB->Timeout = 0;
6205 pSMB->Reserved2 = 0;
6206 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6207 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6208 pSMB->DataCount = 0;
6209 pSMB->DataOffset = 0;
6210 pSMB->SetupCount = 1;
6211 pSMB->Reserved3 = 0;
6212 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6213 byte_count = params + 1 /* pad */ ;
6214 pSMB->TotalParameterCount = cpu_to_le16(params);
6215 pSMB->ParameterCount = pSMB->TotalParameterCount;
6216 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6217 pSMB->Reserved4 = 0;
6218 inc_rfc1001_len(pSMB, byte_count);
6219 pSMB->ByteCount = cpu_to_le16(byte_count);
6220
6221 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6222 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6223 if (rc) {
6224 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6225 goto QAllEAsOut;
6226 }
6227
6228
6229 /* BB also check enough total bytes returned */
6230 /* BB we need to improve the validity checking
6231 of these trans2 responses */
6232
6233 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6234 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6235 rc = -EIO; /* bad smb */
6236 goto QAllEAsOut;
6237 }
6238
6239 /* check that length of list is not more than bcc */
6240 /* check that each entry does not go beyond length
6241 of list */
6242 /* check that each element of each entry does not
6243 go beyond end of list */
6244 /* validate_trans2_offsets() */
6245 /* BB check if start of smb + data_offset > &bcc+ bcc */
6246
6247 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6248 ea_response_data = (struct fealist *)
6249 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6250
6251 list_len = le32_to_cpu(ea_response_data->list_len);
6252 cFYI(1, "ea length %d", list_len);
6253 if (list_len <= 8) {
6254 cFYI(1, "empty EA list returned from server");
6255 goto QAllEAsOut;
6256 }
6257
6258 /* make sure list_len doesn't go past end of SMB */
6259 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6260 if ((char *)ea_response_data + list_len > end_of_smb) {
6261 cFYI(1, "EA list appears to go beyond SMB");
6262 rc = -EIO;
6263 goto QAllEAsOut;
6264 }
6265
6266 /* account for ea list len */
6267 list_len -= 4;
6268 temp_fea = ea_response_data->list;
6269 temp_ptr = (char *)temp_fea;
6270 while (list_len > 0) {
6271 unsigned int name_len;
6272 __u16 value_len;
6273
6274 list_len -= 4;
6275 temp_ptr += 4;
6276 /* make sure we can read name_len and value_len */
6277 if (list_len < 0) {
6278 cFYI(1, "EA entry goes beyond length of list");
6279 rc = -EIO;
6280 goto QAllEAsOut;
6281 }
6282
6283 name_len = temp_fea->name_len;
6284 value_len = le16_to_cpu(temp_fea->value_len);
6285 list_len -= name_len + 1 + value_len;
6286 if (list_len < 0) {
6287 cFYI(1, "EA entry goes beyond length of list");
6288 rc = -EIO;
6289 goto QAllEAsOut;
6290 }
6291
6292 if (ea_name) {
6293 if (ea_name_len == name_len &&
6294 memcmp(ea_name, temp_ptr, name_len) == 0) {
6295 temp_ptr += name_len + 1;
6296 rc = value_len;
6297 if (buf_size == 0)
6298 goto QAllEAsOut;
6299 if ((size_t)value_len > buf_size) {
6300 rc = -ERANGE;
6301 goto QAllEAsOut;
6302 }
6303 memcpy(EAData, temp_ptr, value_len);
6304 goto QAllEAsOut;
6305 }
6306 } else {
6307 /* account for prefix user. and trailing null */
6308 rc += (5 + 1 + name_len);
6309 if (rc < (int) buf_size) {
6310 memcpy(EAData, "user.", 5);
6311 EAData += 5;
6312 memcpy(EAData, temp_ptr, name_len);
6313 EAData += name_len;
6314 /* null terminate name */
6315 *EAData = 0;
6316 ++EAData;
6317 } else if (buf_size == 0) {
6318 /* skip copy - calc size only */
6319 } else {
6320 /* stop before overrun buffer */
6321 rc = -ERANGE;
6322 break;
6323 }
6324 }
6325 temp_ptr += name_len + 1 + value_len;
6326 temp_fea = (struct fea *)temp_ptr;
6327 }
6328
6329 /* didn't find the named attribute */
6330 if (ea_name)
6331 rc = -ENODATA;
6332
6333 QAllEAsOut:
6334 cifs_buf_release(pSMB);
6335 if (rc == -EAGAIN)
6336 goto QAllEAsRetry;
6337
6338 return (ssize_t)rc;
6339 }
6340
6341 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)6342 CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
6343 const char *ea_name, const void *ea_value,
6344 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6345 int remap)
6346 {
6347 struct smb_com_transaction2_spi_req *pSMB = NULL;
6348 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6349 struct fealist *parm_data;
6350 int name_len;
6351 int rc = 0;
6352 int bytes_returned = 0;
6353 __u16 params, param_offset, byte_count, offset, count;
6354
6355 cFYI(1, "In SetEA");
6356 SetEARetry:
6357 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6358 (void **) &pSMBr);
6359 if (rc)
6360 return rc;
6361
6362 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6363 name_len =
6364 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6365 PATH_MAX, nls_codepage, remap);
6366 name_len++; /* trailing null */
6367 name_len *= 2;
6368 } else { /* BB improve the check for buffer overruns BB */
6369 name_len = strnlen(fileName, PATH_MAX);
6370 name_len++; /* trailing null */
6371 strncpy(pSMB->FileName, fileName, name_len);
6372 }
6373
6374 params = 6 + name_len;
6375
6376 /* done calculating parms using name_len of file name,
6377 now use name_len to calculate length of ea name
6378 we are going to create in the inode xattrs */
6379 if (ea_name == NULL)
6380 name_len = 0;
6381 else
6382 name_len = strnlen(ea_name, 255);
6383
6384 count = sizeof(*parm_data) + ea_value_len + name_len;
6385 pSMB->MaxParameterCount = cpu_to_le16(2);
6386 /* BB find max SMB PDU from sess */
6387 pSMB->MaxDataCount = cpu_to_le16(1000);
6388 pSMB->MaxSetupCount = 0;
6389 pSMB->Reserved = 0;
6390 pSMB->Flags = 0;
6391 pSMB->Timeout = 0;
6392 pSMB->Reserved2 = 0;
6393 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6394 InformationLevel) - 4;
6395 offset = param_offset + params;
6396 pSMB->InformationLevel =
6397 cpu_to_le16(SMB_SET_FILE_EA);
6398
6399 parm_data =
6400 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6401 offset);
6402 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6403 pSMB->DataOffset = cpu_to_le16(offset);
6404 pSMB->SetupCount = 1;
6405 pSMB->Reserved3 = 0;
6406 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6407 byte_count = 3 /* pad */ + params + count;
6408 pSMB->DataCount = cpu_to_le16(count);
6409 parm_data->list_len = cpu_to_le32(count);
6410 parm_data->list[0].EA_flags = 0;
6411 /* we checked above that name len is less than 255 */
6412 parm_data->list[0].name_len = (__u8)name_len;
6413 /* EA names are always ASCII */
6414 if (ea_name)
6415 strncpy(parm_data->list[0].name, ea_name, name_len);
6416 parm_data->list[0].name[name_len] = 0;
6417 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6418 /* caller ensures that ea_value_len is less than 64K but
6419 we need to ensure that it fits within the smb */
6420
6421 /*BB add length check to see if it would fit in
6422 negotiated SMB buffer size BB */
6423 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6424 if (ea_value_len)
6425 memcpy(parm_data->list[0].name+name_len+1,
6426 ea_value, ea_value_len);
6427
6428 pSMB->TotalDataCount = pSMB->DataCount;
6429 pSMB->ParameterCount = cpu_to_le16(params);
6430 pSMB->TotalParameterCount = pSMB->ParameterCount;
6431 pSMB->Reserved4 = 0;
6432 inc_rfc1001_len(pSMB, byte_count);
6433 pSMB->ByteCount = cpu_to_le16(byte_count);
6434 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6435 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6436 if (rc)
6437 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6438
6439 cifs_buf_release(pSMB);
6440
6441 if (rc == -EAGAIN)
6442 goto SetEARetry;
6443
6444 return rc;
6445 }
6446 #endif
6447
6448 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6449 /*
6450 * Years ago the kernel added a "dnotify" function for Samba server,
6451 * to allow network clients (such as Windows) to display updated
6452 * lists of files in directory listings automatically when
6453 * files are added by one user when another user has the
6454 * same directory open on their desktop. The Linux cifs kernel
6455 * client hooked into the kernel side of this interface for
6456 * the same reason, but ironically when the VFS moved from
6457 * "dnotify" to "inotify" it became harder to plug in Linux
6458 * network file system clients (the most obvious use case
6459 * for notify interfaces is when multiple users can update
6460 * the contents of the same directory - exactly what network
6461 * file systems can do) although the server (Samba) could
6462 * still use it. For the short term we leave the worker
6463 * function ifdeffed out (below) until inotify is fixed
6464 * in the VFS to make it easier to plug in network file
6465 * system clients. If inotify turns out to be permanently
6466 * incompatible for network fs clients, we could instead simply
6467 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6468 */
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)6469 int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
6470 const int notify_subdirs, const __u16 netfid,
6471 __u32 filter, struct file *pfile, int multishot,
6472 const struct nls_table *nls_codepage)
6473 {
6474 int rc = 0;
6475 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6476 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6477 struct dir_notify_req *dnotify_req;
6478 int bytes_returned;
6479
6480 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6481 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6482 (void **) &pSMBr);
6483 if (rc)
6484 return rc;
6485
6486 pSMB->TotalParameterCount = 0 ;
6487 pSMB->TotalDataCount = 0;
6488 pSMB->MaxParameterCount = cpu_to_le32(2);
6489 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6490 pSMB->MaxSetupCount = 4;
6491 pSMB->Reserved = 0;
6492 pSMB->ParameterOffset = 0;
6493 pSMB->DataCount = 0;
6494 pSMB->DataOffset = 0;
6495 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6496 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6497 pSMB->ParameterCount = pSMB->TotalParameterCount;
6498 if (notify_subdirs)
6499 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6500 pSMB->Reserved2 = 0;
6501 pSMB->CompletionFilter = cpu_to_le32(filter);
6502 pSMB->Fid = netfid; /* file handle always le */
6503 pSMB->ByteCount = 0;
6504
6505 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6506 (struct smb_hdr *)pSMBr, &bytes_returned,
6507 CIFS_ASYNC_OP);
6508 if (rc) {
6509 cFYI(1, "Error in Notify = %d", rc);
6510 } else {
6511 /* Add file to outstanding requests */
6512 /* BB change to kmem cache alloc */
6513 dnotify_req = kmalloc(
6514 sizeof(struct dir_notify_req),
6515 GFP_KERNEL);
6516 if (dnotify_req) {
6517 dnotify_req->Pid = pSMB->hdr.Pid;
6518 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6519 dnotify_req->Mid = pSMB->hdr.Mid;
6520 dnotify_req->Tid = pSMB->hdr.Tid;
6521 dnotify_req->Uid = pSMB->hdr.Uid;
6522 dnotify_req->netfid = netfid;
6523 dnotify_req->pfile = pfile;
6524 dnotify_req->filter = filter;
6525 dnotify_req->multishot = multishot;
6526 spin_lock(&GlobalMid_Lock);
6527 list_add_tail(&dnotify_req->lhead,
6528 &GlobalDnotifyReqList);
6529 spin_unlock(&GlobalMid_Lock);
6530 } else
6531 rc = -ENOMEM;
6532 }
6533 cifs_buf_release(pSMB);
6534 return rc;
6535 }
6536 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
6537