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