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