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