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