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