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