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