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