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 /*
4863 * Use smb_init_no_reconnect() instead of smb_init() as
4864 * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
4865 * causing an infinite recursion.
4866 */
4867 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
4868 (void **)&pSMB, (void **)&pSMBr);
4869 if (rc)
4870 return rc;
4871
4872 /* server pointer checked in called function,
4873 but should never be null here anyway */
4874 pSMB->hdr.Mid = get_next_mid(ses->server);
4875 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4876 pSMB->hdr.Uid = ses->Suid;
4877 if (ses->capabilities & CAP_STATUS32)
4878 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4879 if (ses->capabilities & CAP_DFS)
4880 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4881
4882 if (ses->capabilities & CAP_UNICODE) {
4883 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4884 name_len =
4885 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4886 search_name, PATH_MAX, nls_codepage,
4887 remap);
4888 name_len++; /* trailing null */
4889 name_len *= 2;
4890 } else { /* BB improve the check for buffer overruns BB */
4891 name_len = copy_path_name(pSMB->RequestFileName, search_name);
4892 }
4893
4894 if (ses->server->sign)
4895 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4896
4897 pSMB->hdr.Uid = ses->Suid;
4898
4899 params = 2 /* level */ + name_len /*includes null */ ;
4900 pSMB->TotalDataCount = 0;
4901 pSMB->DataCount = 0;
4902 pSMB->DataOffset = 0;
4903 pSMB->MaxParameterCount = 0;
4904 /* BB find exact max SMB PDU from sess structure BB */
4905 pSMB->MaxDataCount = cpu_to_le16(4000);
4906 pSMB->MaxSetupCount = 0;
4907 pSMB->Reserved = 0;
4908 pSMB->Flags = 0;
4909 pSMB->Timeout = 0;
4910 pSMB->Reserved2 = 0;
4911 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4912 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4913 pSMB->SetupCount = 1;
4914 pSMB->Reserved3 = 0;
4915 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4916 byte_count = params + 3 /* pad */ ;
4917 pSMB->ParameterCount = cpu_to_le16(params);
4918 pSMB->TotalParameterCount = pSMB->ParameterCount;
4919 pSMB->MaxReferralLevel = cpu_to_le16(3);
4920 inc_rfc1001_len(pSMB, byte_count);
4921 pSMB->ByteCount = cpu_to_le16(byte_count);
4922
4923 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4924 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4925 if (rc) {
4926 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4927 goto GetDFSRefExit;
4928 }
4929 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4930
4931 /* BB Also check if enough total bytes returned? */
4932 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4933 rc = -EIO; /* bad smb */
4934 goto GetDFSRefExit;
4935 }
4936
4937 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4938 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4939
4940 /* parse returned result into more usable form */
4941 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4942 le16_to_cpu(pSMBr->t2.DataCount),
4943 num_of_nodes, target_nodes, nls_codepage,
4944 remap, search_name,
4945 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4946
4947 GetDFSRefExit:
4948 cifs_buf_release(pSMB);
4949
4950 if (rc == -EAGAIN)
4951 goto getDFSRetry;
4952
4953 return rc;
4954 }
4955
4956 /* Query File System Info such as free space to old servers such as Win 9x */
4957 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4958 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4959 struct kstatfs *FSData)
4960 {
4961 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4962 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4963 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4964 FILE_SYSTEM_ALLOC_INFO *response_data;
4965 int rc = 0;
4966 int bytes_returned = 0;
4967 __u16 params, byte_count;
4968
4969 cifs_dbg(FYI, "OldQFSInfo\n");
4970 oldQFSInfoRetry:
4971 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4972 (void **) &pSMBr);
4973 if (rc)
4974 return rc;
4975
4976 params = 2; /* level */
4977 pSMB->TotalDataCount = 0;
4978 pSMB->MaxParameterCount = cpu_to_le16(2);
4979 pSMB->MaxDataCount = cpu_to_le16(1000);
4980 pSMB->MaxSetupCount = 0;
4981 pSMB->Reserved = 0;
4982 pSMB->Flags = 0;
4983 pSMB->Timeout = 0;
4984 pSMB->Reserved2 = 0;
4985 byte_count = params + 1 /* pad */ ;
4986 pSMB->TotalParameterCount = cpu_to_le16(params);
4987 pSMB->ParameterCount = pSMB->TotalParameterCount;
4988 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4989 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4990 pSMB->DataCount = 0;
4991 pSMB->DataOffset = 0;
4992 pSMB->SetupCount = 1;
4993 pSMB->Reserved3 = 0;
4994 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4995 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4996 inc_rfc1001_len(pSMB, byte_count);
4997 pSMB->ByteCount = cpu_to_le16(byte_count);
4998
4999 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5000 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5001 if (rc) {
5002 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5003 } else { /* decode response */
5004 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5005
5006 if (rc || get_bcc(&pSMBr->hdr) < 18)
5007 rc = -EIO; /* bad smb */
5008 else {
5009 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5010 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
5011 get_bcc(&pSMBr->hdr), data_offset);
5012
5013 response_data = (FILE_SYSTEM_ALLOC_INFO *)
5014 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5015 FSData->f_bsize =
5016 le16_to_cpu(response_data->BytesPerSector) *
5017 le32_to_cpu(response_data->
5018 SectorsPerAllocationUnit);
5019 /*
5020 * much prefer larger but if server doesn't report
5021 * a valid size than 4K is a reasonable minimum
5022 */
5023 if (FSData->f_bsize < 512)
5024 FSData->f_bsize = 4096;
5025
5026 FSData->f_blocks =
5027 le32_to_cpu(response_data->TotalAllocationUnits);
5028 FSData->f_bfree = FSData->f_bavail =
5029 le32_to_cpu(response_data->FreeAllocationUnits);
5030 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5031 (unsigned long long)FSData->f_blocks,
5032 (unsigned long long)FSData->f_bfree,
5033 FSData->f_bsize);
5034 }
5035 }
5036 cifs_buf_release(pSMB);
5037
5038 if (rc == -EAGAIN)
5039 goto oldQFSInfoRetry;
5040
5041 return rc;
5042 }
5043
5044 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5045 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5046 struct kstatfs *FSData)
5047 {
5048 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5049 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5050 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5051 FILE_SYSTEM_INFO *response_data;
5052 int rc = 0;
5053 int bytes_returned = 0;
5054 __u16 params, byte_count;
5055
5056 cifs_dbg(FYI, "In QFSInfo\n");
5057 QFSInfoRetry:
5058 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5059 (void **) &pSMBr);
5060 if (rc)
5061 return rc;
5062
5063 params = 2; /* level */
5064 pSMB->TotalDataCount = 0;
5065 pSMB->MaxParameterCount = cpu_to_le16(2);
5066 pSMB->MaxDataCount = cpu_to_le16(1000);
5067 pSMB->MaxSetupCount = 0;
5068 pSMB->Reserved = 0;
5069 pSMB->Flags = 0;
5070 pSMB->Timeout = 0;
5071 pSMB->Reserved2 = 0;
5072 byte_count = params + 1 /* pad */ ;
5073 pSMB->TotalParameterCount = cpu_to_le16(params);
5074 pSMB->ParameterCount = pSMB->TotalParameterCount;
5075 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5076 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5077 pSMB->DataCount = 0;
5078 pSMB->DataOffset = 0;
5079 pSMB->SetupCount = 1;
5080 pSMB->Reserved3 = 0;
5081 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5082 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5083 inc_rfc1001_len(pSMB, byte_count);
5084 pSMB->ByteCount = cpu_to_le16(byte_count);
5085
5086 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5087 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5088 if (rc) {
5089 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5090 } else { /* decode response */
5091 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5092
5093 if (rc || get_bcc(&pSMBr->hdr) < 24)
5094 rc = -EIO; /* bad smb */
5095 else {
5096 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5097
5098 response_data =
5099 (FILE_SYSTEM_INFO
5100 *) (((char *) &pSMBr->hdr.Protocol) +
5101 data_offset);
5102 FSData->f_bsize =
5103 le32_to_cpu(response_data->BytesPerSector) *
5104 le32_to_cpu(response_data->
5105 SectorsPerAllocationUnit);
5106 /*
5107 * much prefer larger but if server doesn't report
5108 * a valid size than 4K is a reasonable minimum
5109 */
5110 if (FSData->f_bsize < 512)
5111 FSData->f_bsize = 4096;
5112
5113 FSData->f_blocks =
5114 le64_to_cpu(response_data->TotalAllocationUnits);
5115 FSData->f_bfree = FSData->f_bavail =
5116 le64_to_cpu(response_data->FreeAllocationUnits);
5117 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5118 (unsigned long long)FSData->f_blocks,
5119 (unsigned long long)FSData->f_bfree,
5120 FSData->f_bsize);
5121 }
5122 }
5123 cifs_buf_release(pSMB);
5124
5125 if (rc == -EAGAIN)
5126 goto QFSInfoRetry;
5127
5128 return rc;
5129 }
5130
5131 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)5132 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5133 {
5134 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5135 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5136 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5137 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5138 int rc = 0;
5139 int bytes_returned = 0;
5140 __u16 params, byte_count;
5141
5142 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5143 QFSAttributeRetry:
5144 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5145 (void **) &pSMBr);
5146 if (rc)
5147 return rc;
5148
5149 params = 2; /* level */
5150 pSMB->TotalDataCount = 0;
5151 pSMB->MaxParameterCount = cpu_to_le16(2);
5152 /* BB find exact max SMB PDU from sess structure BB */
5153 pSMB->MaxDataCount = cpu_to_le16(1000);
5154 pSMB->MaxSetupCount = 0;
5155 pSMB->Reserved = 0;
5156 pSMB->Flags = 0;
5157 pSMB->Timeout = 0;
5158 pSMB->Reserved2 = 0;
5159 byte_count = params + 1 /* pad */ ;
5160 pSMB->TotalParameterCount = cpu_to_le16(params);
5161 pSMB->ParameterCount = pSMB->TotalParameterCount;
5162 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5163 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5164 pSMB->DataCount = 0;
5165 pSMB->DataOffset = 0;
5166 pSMB->SetupCount = 1;
5167 pSMB->Reserved3 = 0;
5168 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5169 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5170 inc_rfc1001_len(pSMB, byte_count);
5171 pSMB->ByteCount = cpu_to_le16(byte_count);
5172
5173 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5174 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5175 if (rc) {
5176 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5177 } else { /* decode response */
5178 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5179
5180 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5181 /* BB also check if enough bytes returned */
5182 rc = -EIO; /* bad smb */
5183 } else {
5184 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5185 response_data =
5186 (FILE_SYSTEM_ATTRIBUTE_INFO
5187 *) (((char *) &pSMBr->hdr.Protocol) +
5188 data_offset);
5189 memcpy(&tcon->fsAttrInfo, response_data,
5190 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5191 }
5192 }
5193 cifs_buf_release(pSMB);
5194
5195 if (rc == -EAGAIN)
5196 goto QFSAttributeRetry;
5197
5198 return rc;
5199 }
5200
5201 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)5202 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5203 {
5204 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5205 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5206 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5207 FILE_SYSTEM_DEVICE_INFO *response_data;
5208 int rc = 0;
5209 int bytes_returned = 0;
5210 __u16 params, byte_count;
5211
5212 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5213 QFSDeviceRetry:
5214 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5215 (void **) &pSMBr);
5216 if (rc)
5217 return rc;
5218
5219 params = 2; /* level */
5220 pSMB->TotalDataCount = 0;
5221 pSMB->MaxParameterCount = cpu_to_le16(2);
5222 /* BB find exact max SMB PDU from sess structure BB */
5223 pSMB->MaxDataCount = cpu_to_le16(1000);
5224 pSMB->MaxSetupCount = 0;
5225 pSMB->Reserved = 0;
5226 pSMB->Flags = 0;
5227 pSMB->Timeout = 0;
5228 pSMB->Reserved2 = 0;
5229 byte_count = params + 1 /* pad */ ;
5230 pSMB->TotalParameterCount = cpu_to_le16(params);
5231 pSMB->ParameterCount = pSMB->TotalParameterCount;
5232 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5233 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5234
5235 pSMB->DataCount = 0;
5236 pSMB->DataOffset = 0;
5237 pSMB->SetupCount = 1;
5238 pSMB->Reserved3 = 0;
5239 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5240 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5241 inc_rfc1001_len(pSMB, byte_count);
5242 pSMB->ByteCount = cpu_to_le16(byte_count);
5243
5244 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5245 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5246 if (rc) {
5247 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5248 } else { /* decode response */
5249 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5250
5251 if (rc || get_bcc(&pSMBr->hdr) <
5252 sizeof(FILE_SYSTEM_DEVICE_INFO))
5253 rc = -EIO; /* bad smb */
5254 else {
5255 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5256 response_data =
5257 (FILE_SYSTEM_DEVICE_INFO *)
5258 (((char *) &pSMBr->hdr.Protocol) +
5259 data_offset);
5260 memcpy(&tcon->fsDevInfo, response_data,
5261 sizeof(FILE_SYSTEM_DEVICE_INFO));
5262 }
5263 }
5264 cifs_buf_release(pSMB);
5265
5266 if (rc == -EAGAIN)
5267 goto QFSDeviceRetry;
5268
5269 return rc;
5270 }
5271
5272 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)5273 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5274 {
5275 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5276 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5277 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5278 FILE_SYSTEM_UNIX_INFO *response_data;
5279 int rc = 0;
5280 int bytes_returned = 0;
5281 __u16 params, byte_count;
5282
5283 cifs_dbg(FYI, "In QFSUnixInfo\n");
5284 QFSUnixRetry:
5285 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5286 (void **) &pSMB, (void **) &pSMBr);
5287 if (rc)
5288 return rc;
5289
5290 params = 2; /* level */
5291 pSMB->TotalDataCount = 0;
5292 pSMB->DataCount = 0;
5293 pSMB->DataOffset = 0;
5294 pSMB->MaxParameterCount = cpu_to_le16(2);
5295 /* BB find exact max SMB PDU from sess structure BB */
5296 pSMB->MaxDataCount = cpu_to_le16(100);
5297 pSMB->MaxSetupCount = 0;
5298 pSMB->Reserved = 0;
5299 pSMB->Flags = 0;
5300 pSMB->Timeout = 0;
5301 pSMB->Reserved2 = 0;
5302 byte_count = params + 1 /* pad */ ;
5303 pSMB->ParameterCount = cpu_to_le16(params);
5304 pSMB->TotalParameterCount = pSMB->ParameterCount;
5305 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5306 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5307 pSMB->SetupCount = 1;
5308 pSMB->Reserved3 = 0;
5309 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5310 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5311 inc_rfc1001_len(pSMB, byte_count);
5312 pSMB->ByteCount = cpu_to_le16(byte_count);
5313
5314 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5315 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5316 if (rc) {
5317 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5318 } else { /* decode response */
5319 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5320
5321 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5322 rc = -EIO; /* bad smb */
5323 } else {
5324 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5325 response_data =
5326 (FILE_SYSTEM_UNIX_INFO
5327 *) (((char *) &pSMBr->hdr.Protocol) +
5328 data_offset);
5329 memcpy(&tcon->fsUnixInfo, response_data,
5330 sizeof(FILE_SYSTEM_UNIX_INFO));
5331 }
5332 }
5333 cifs_buf_release(pSMB);
5334
5335 if (rc == -EAGAIN)
5336 goto QFSUnixRetry;
5337
5338
5339 return rc;
5340 }
5341
5342 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)5343 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5344 {
5345 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5346 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5347 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5348 int rc = 0;
5349 int bytes_returned = 0;
5350 __u16 params, param_offset, offset, byte_count;
5351
5352 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5353 SETFSUnixRetry:
5354 /* BB switch to small buf init to save memory */
5355 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5356 (void **) &pSMB, (void **) &pSMBr);
5357 if (rc)
5358 return rc;
5359
5360 params = 4; /* 2 bytes zero followed by info level. */
5361 pSMB->MaxSetupCount = 0;
5362 pSMB->Reserved = 0;
5363 pSMB->Flags = 0;
5364 pSMB->Timeout = 0;
5365 pSMB->Reserved2 = 0;
5366 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5367 - 4;
5368 offset = param_offset + params;
5369
5370 pSMB->MaxParameterCount = cpu_to_le16(4);
5371 /* BB find exact max SMB PDU from sess structure BB */
5372 pSMB->MaxDataCount = cpu_to_le16(100);
5373 pSMB->SetupCount = 1;
5374 pSMB->Reserved3 = 0;
5375 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5376 byte_count = 1 /* pad */ + params + 12;
5377
5378 pSMB->DataCount = cpu_to_le16(12);
5379 pSMB->ParameterCount = cpu_to_le16(params);
5380 pSMB->TotalDataCount = pSMB->DataCount;
5381 pSMB->TotalParameterCount = pSMB->ParameterCount;
5382 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5383 pSMB->DataOffset = cpu_to_le16(offset);
5384
5385 /* Params. */
5386 pSMB->FileNum = 0;
5387 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5388
5389 /* Data. */
5390 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5391 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5392 pSMB->ClientUnixCap = cpu_to_le64(cap);
5393
5394 inc_rfc1001_len(pSMB, byte_count);
5395 pSMB->ByteCount = cpu_to_le16(byte_count);
5396
5397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5399 if (rc) {
5400 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5401 } else { /* decode response */
5402 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5403 if (rc)
5404 rc = -EIO; /* bad smb */
5405 }
5406 cifs_buf_release(pSMB);
5407
5408 if (rc == -EAGAIN)
5409 goto SETFSUnixRetry;
5410
5411 return rc;
5412 }
5413
5414
5415
5416 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5417 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5418 struct kstatfs *FSData)
5419 {
5420 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5421 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5422 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5423 FILE_SYSTEM_POSIX_INFO *response_data;
5424 int rc = 0;
5425 int bytes_returned = 0;
5426 __u16 params, byte_count;
5427
5428 cifs_dbg(FYI, "In QFSPosixInfo\n");
5429 QFSPosixRetry:
5430 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5431 (void **) &pSMBr);
5432 if (rc)
5433 return rc;
5434
5435 params = 2; /* level */
5436 pSMB->TotalDataCount = 0;
5437 pSMB->DataCount = 0;
5438 pSMB->DataOffset = 0;
5439 pSMB->MaxParameterCount = cpu_to_le16(2);
5440 /* BB find exact max SMB PDU from sess structure BB */
5441 pSMB->MaxDataCount = cpu_to_le16(100);
5442 pSMB->MaxSetupCount = 0;
5443 pSMB->Reserved = 0;
5444 pSMB->Flags = 0;
5445 pSMB->Timeout = 0;
5446 pSMB->Reserved2 = 0;
5447 byte_count = params + 1 /* pad */ ;
5448 pSMB->ParameterCount = cpu_to_le16(params);
5449 pSMB->TotalParameterCount = pSMB->ParameterCount;
5450 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5451 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5452 pSMB->SetupCount = 1;
5453 pSMB->Reserved3 = 0;
5454 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5455 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5456 inc_rfc1001_len(pSMB, byte_count);
5457 pSMB->ByteCount = cpu_to_le16(byte_count);
5458
5459 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5460 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5461 if (rc) {
5462 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5463 } else { /* decode response */
5464 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5465
5466 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5467 rc = -EIO; /* bad smb */
5468 } else {
5469 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5470 response_data =
5471 (FILE_SYSTEM_POSIX_INFO
5472 *) (((char *) &pSMBr->hdr.Protocol) +
5473 data_offset);
5474 FSData->f_bsize =
5475 le32_to_cpu(response_data->BlockSize);
5476 /*
5477 * much prefer larger but if server doesn't report
5478 * a valid size than 4K is a reasonable minimum
5479 */
5480 if (FSData->f_bsize < 512)
5481 FSData->f_bsize = 4096;
5482
5483 FSData->f_blocks =
5484 le64_to_cpu(response_data->TotalBlocks);
5485 FSData->f_bfree =
5486 le64_to_cpu(response_data->BlocksAvail);
5487 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5488 FSData->f_bavail = FSData->f_bfree;
5489 } else {
5490 FSData->f_bavail =
5491 le64_to_cpu(response_data->UserBlocksAvail);
5492 }
5493 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5494 FSData->f_files =
5495 le64_to_cpu(response_data->TotalFileNodes);
5496 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5497 FSData->f_ffree =
5498 le64_to_cpu(response_data->FreeFileNodes);
5499 }
5500 }
5501 cifs_buf_release(pSMB);
5502
5503 if (rc == -EAGAIN)
5504 goto QFSPosixRetry;
5505
5506 return rc;
5507 }
5508
5509
5510 /*
5511 * We can not use write of zero bytes trick to set file size due to need for
5512 * large file support. Also note that this SetPathInfo is preferred to
5513 * SetFileInfo based method in next routine which is only needed to work around
5514 * a sharing violation bugin Samba which this routine can run into.
5515 */
5516 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)5517 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5518 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5519 bool set_allocation)
5520 {
5521 struct smb_com_transaction2_spi_req *pSMB = NULL;
5522 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5523 struct file_end_of_file_info *parm_data;
5524 int name_len;
5525 int rc = 0;
5526 int bytes_returned = 0;
5527 int remap = cifs_remap(cifs_sb);
5528
5529 __u16 params, byte_count, data_count, param_offset, offset;
5530
5531 cifs_dbg(FYI, "In SetEOF\n");
5532 SetEOFRetry:
5533 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5534 (void **) &pSMBr);
5535 if (rc)
5536 return rc;
5537
5538 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5539 name_len =
5540 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5541 PATH_MAX, cifs_sb->local_nls, remap);
5542 name_len++; /* trailing null */
5543 name_len *= 2;
5544 } else {
5545 name_len = copy_path_name(pSMB->FileName, file_name);
5546 }
5547 params = 6 + name_len;
5548 data_count = sizeof(struct file_end_of_file_info);
5549 pSMB->MaxParameterCount = cpu_to_le16(2);
5550 pSMB->MaxDataCount = cpu_to_le16(4100);
5551 pSMB->MaxSetupCount = 0;
5552 pSMB->Reserved = 0;
5553 pSMB->Flags = 0;
5554 pSMB->Timeout = 0;
5555 pSMB->Reserved2 = 0;
5556 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5557 InformationLevel) - 4;
5558 offset = param_offset + params;
5559 if (set_allocation) {
5560 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5561 pSMB->InformationLevel =
5562 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5563 else
5564 pSMB->InformationLevel =
5565 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5566 } else /* Set File Size */ {
5567 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5568 pSMB->InformationLevel =
5569 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5570 else
5571 pSMB->InformationLevel =
5572 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5573 }
5574
5575 parm_data =
5576 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5577 offset);
5578 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5579 pSMB->DataOffset = cpu_to_le16(offset);
5580 pSMB->SetupCount = 1;
5581 pSMB->Reserved3 = 0;
5582 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5583 byte_count = 3 /* pad */ + params + data_count;
5584 pSMB->DataCount = cpu_to_le16(data_count);
5585 pSMB->TotalDataCount = pSMB->DataCount;
5586 pSMB->ParameterCount = cpu_to_le16(params);
5587 pSMB->TotalParameterCount = pSMB->ParameterCount;
5588 pSMB->Reserved4 = 0;
5589 inc_rfc1001_len(pSMB, byte_count);
5590 parm_data->FileSize = cpu_to_le64(size);
5591 pSMB->ByteCount = cpu_to_le16(byte_count);
5592 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5593 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5594 if (rc)
5595 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5596
5597 cifs_buf_release(pSMB);
5598
5599 if (rc == -EAGAIN)
5600 goto SetEOFRetry;
5601
5602 return rc;
5603 }
5604
5605 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5606 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5607 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5608 {
5609 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5610 struct file_end_of_file_info *parm_data;
5611 int rc = 0;
5612 __u16 params, param_offset, offset, byte_count, count;
5613
5614 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5615 (long long)size);
5616 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5617
5618 if (rc)
5619 return rc;
5620
5621 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5622 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5623
5624 params = 6;
5625 pSMB->MaxSetupCount = 0;
5626 pSMB->Reserved = 0;
5627 pSMB->Flags = 0;
5628 pSMB->Timeout = 0;
5629 pSMB->Reserved2 = 0;
5630 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5631 offset = param_offset + params;
5632
5633 count = sizeof(struct file_end_of_file_info);
5634 pSMB->MaxParameterCount = cpu_to_le16(2);
5635 /* BB find exact max SMB PDU from sess structure BB */
5636 pSMB->MaxDataCount = cpu_to_le16(1000);
5637 pSMB->SetupCount = 1;
5638 pSMB->Reserved3 = 0;
5639 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5640 byte_count = 3 /* pad */ + params + count;
5641 pSMB->DataCount = cpu_to_le16(count);
5642 pSMB->ParameterCount = cpu_to_le16(params);
5643 pSMB->TotalDataCount = pSMB->DataCount;
5644 pSMB->TotalParameterCount = pSMB->ParameterCount;
5645 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5646 parm_data =
5647 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5648 + offset);
5649 pSMB->DataOffset = cpu_to_le16(offset);
5650 parm_data->FileSize = cpu_to_le64(size);
5651 pSMB->Fid = cfile->fid.netfid;
5652 if (set_allocation) {
5653 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5654 pSMB->InformationLevel =
5655 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5656 else
5657 pSMB->InformationLevel =
5658 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5659 } else /* Set File Size */ {
5660 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5661 pSMB->InformationLevel =
5662 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5663 else
5664 pSMB->InformationLevel =
5665 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5666 }
5667 pSMB->Reserved4 = 0;
5668 inc_rfc1001_len(pSMB, byte_count);
5669 pSMB->ByteCount = cpu_to_le16(byte_count);
5670 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5671 cifs_small_buf_release(pSMB);
5672 if (rc) {
5673 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5674 rc);
5675 }
5676
5677 /* Note: On -EAGAIN error only caller can retry on handle based calls
5678 since file handle passed in no longer valid */
5679
5680 return rc;
5681 }
5682
5683 /* Some legacy servers such as NT4 require that the file times be set on
5684 an open handle, rather than by pathname - this is awkward due to
5685 potential access conflicts on the open, but it is unavoidable for these
5686 old servers since the only other choice is to go from 100 nanosecond DCE
5687 time and resort to the original setpathinfo level which takes the ancient
5688 DOS time format with 2 second granularity */
5689 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5690 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5691 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5692 {
5693 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5694 char *data_offset;
5695 int rc = 0;
5696 __u16 params, param_offset, offset, byte_count, count;
5697
5698 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5699 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5700
5701 if (rc)
5702 return rc;
5703
5704 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5705 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5706
5707 params = 6;
5708 pSMB->MaxSetupCount = 0;
5709 pSMB->Reserved = 0;
5710 pSMB->Flags = 0;
5711 pSMB->Timeout = 0;
5712 pSMB->Reserved2 = 0;
5713 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5714 offset = param_offset + params;
5715
5716 data_offset = (char *)pSMB +
5717 offsetof(struct smb_hdr, Protocol) + offset;
5718
5719 count = sizeof(FILE_BASIC_INFO);
5720 pSMB->MaxParameterCount = cpu_to_le16(2);
5721 /* BB find max SMB PDU from sess */
5722 pSMB->MaxDataCount = cpu_to_le16(1000);
5723 pSMB->SetupCount = 1;
5724 pSMB->Reserved3 = 0;
5725 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5726 byte_count = 3 /* pad */ + params + count;
5727 pSMB->DataCount = cpu_to_le16(count);
5728 pSMB->ParameterCount = cpu_to_le16(params);
5729 pSMB->TotalDataCount = pSMB->DataCount;
5730 pSMB->TotalParameterCount = pSMB->ParameterCount;
5731 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5732 pSMB->DataOffset = cpu_to_le16(offset);
5733 pSMB->Fid = fid;
5734 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5735 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5736 else
5737 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5738 pSMB->Reserved4 = 0;
5739 inc_rfc1001_len(pSMB, byte_count);
5740 pSMB->ByteCount = cpu_to_le16(byte_count);
5741 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5742 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5743 cifs_small_buf_release(pSMB);
5744 if (rc)
5745 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5746 rc);
5747
5748 /* Note: On -EAGAIN error only caller can retry on handle based calls
5749 since file handle passed in no longer valid */
5750
5751 return rc;
5752 }
5753
5754 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5755 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5756 bool delete_file, __u16 fid, __u32 pid_of_opener)
5757 {
5758 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5759 char *data_offset;
5760 int rc = 0;
5761 __u16 params, param_offset, offset, byte_count, count;
5762
5763 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5764 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5765
5766 if (rc)
5767 return rc;
5768
5769 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5770 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5771
5772 params = 6;
5773 pSMB->MaxSetupCount = 0;
5774 pSMB->Reserved = 0;
5775 pSMB->Flags = 0;
5776 pSMB->Timeout = 0;
5777 pSMB->Reserved2 = 0;
5778 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5779 offset = param_offset + params;
5780
5781 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5782
5783 count = 1;
5784 pSMB->MaxParameterCount = cpu_to_le16(2);
5785 /* BB find max SMB PDU from sess */
5786 pSMB->MaxDataCount = cpu_to_le16(1000);
5787 pSMB->SetupCount = 1;
5788 pSMB->Reserved3 = 0;
5789 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5790 byte_count = 3 /* pad */ + params + count;
5791 pSMB->DataCount = cpu_to_le16(count);
5792 pSMB->ParameterCount = cpu_to_le16(params);
5793 pSMB->TotalDataCount = pSMB->DataCount;
5794 pSMB->TotalParameterCount = pSMB->ParameterCount;
5795 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5796 pSMB->DataOffset = cpu_to_le16(offset);
5797 pSMB->Fid = fid;
5798 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5799 pSMB->Reserved4 = 0;
5800 inc_rfc1001_len(pSMB, byte_count);
5801 pSMB->ByteCount = cpu_to_le16(byte_count);
5802 *data_offset = delete_file ? 1 : 0;
5803 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5804 cifs_small_buf_release(pSMB);
5805 if (rc)
5806 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5807
5808 return rc;
5809 }
5810
5811 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)5812 CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
5813 const char *fileName, const FILE_BASIC_INFO *data,
5814 const struct nls_table *nls_codepage,
5815 struct cifs_sb_info *cifs_sb)
5816 {
5817 int oplock = 0;
5818 struct cifs_open_parms oparms;
5819 struct cifs_fid fid;
5820 int rc;
5821
5822 oparms.tcon = tcon;
5823 oparms.cifs_sb = cifs_sb;
5824 oparms.desired_access = GENERIC_WRITE;
5825 oparms.create_options = cifs_create_options(cifs_sb, 0);
5826 oparms.disposition = FILE_OPEN;
5827 oparms.path = fileName;
5828 oparms.fid = &fid;
5829 oparms.reconnect = false;
5830
5831 rc = CIFS_open(xid, &oparms, &oplock, NULL);
5832 if (rc)
5833 goto out;
5834
5835 rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
5836 CIFSSMBClose(xid, tcon, fid.netfid);
5837 out:
5838
5839 return rc;
5840 }
5841
5842 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)5843 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5844 const char *fileName, const FILE_BASIC_INFO *data,
5845 const struct nls_table *nls_codepage,
5846 struct cifs_sb_info *cifs_sb)
5847 {
5848 TRANSACTION2_SPI_REQ *pSMB = NULL;
5849 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5850 int name_len;
5851 int rc = 0;
5852 int bytes_returned = 0;
5853 char *data_offset;
5854 __u16 params, param_offset, offset, byte_count, count;
5855 int remap = cifs_remap(cifs_sb);
5856
5857 cifs_dbg(FYI, "In SetTimes\n");
5858
5859 SetTimesRetry:
5860 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5861 (void **) &pSMBr);
5862 if (rc)
5863 return rc;
5864
5865 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5866 name_len =
5867 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5868 PATH_MAX, nls_codepage, remap);
5869 name_len++; /* trailing null */
5870 name_len *= 2;
5871 } else {
5872 name_len = copy_path_name(pSMB->FileName, fileName);
5873 }
5874
5875 params = 6 + name_len;
5876 count = sizeof(FILE_BASIC_INFO);
5877 pSMB->MaxParameterCount = cpu_to_le16(2);
5878 /* BB find max SMB PDU from sess structure BB */
5879 pSMB->MaxDataCount = cpu_to_le16(1000);
5880 pSMB->MaxSetupCount = 0;
5881 pSMB->Reserved = 0;
5882 pSMB->Flags = 0;
5883 pSMB->Timeout = 0;
5884 pSMB->Reserved2 = 0;
5885 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5886 InformationLevel) - 4;
5887 offset = param_offset + params;
5888 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5889 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5890 pSMB->DataOffset = cpu_to_le16(offset);
5891 pSMB->SetupCount = 1;
5892 pSMB->Reserved3 = 0;
5893 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5894 byte_count = 3 /* pad */ + params + count;
5895
5896 pSMB->DataCount = cpu_to_le16(count);
5897 pSMB->ParameterCount = cpu_to_le16(params);
5898 pSMB->TotalDataCount = pSMB->DataCount;
5899 pSMB->TotalParameterCount = pSMB->ParameterCount;
5900 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5901 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5902 else
5903 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5904 pSMB->Reserved4 = 0;
5905 inc_rfc1001_len(pSMB, byte_count);
5906 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5907 pSMB->ByteCount = cpu_to_le16(byte_count);
5908 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5909 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5910 if (rc)
5911 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5912
5913 cifs_buf_release(pSMB);
5914
5915 if (rc == -EAGAIN)
5916 goto SetTimesRetry;
5917
5918 if (rc == -EOPNOTSUPP)
5919 return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
5920 nls_codepage, cifs_sb);
5921
5922 return rc;
5923 }
5924
5925 /* Can not be used to set time stamps yet (due to old DOS time format) */
5926 /* Can be used to set attributes */
5927 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5928 handling it anyway and NT4 was what we thought it would be needed for
5929 Do not delete it until we prove whether needed for Win9x though */
5930 int
5931 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5932 __u16 dos_attrs, const struct nls_table *nls_codepage)
5933 {
5934 SETATTR_REQ *pSMB = NULL;
5935 SETATTR_RSP *pSMBr = NULL;
5936 int rc = 0;
5937 int bytes_returned;
5938 int name_len;
5939
5940 cifs_dbg(FYI, "In SetAttrLegacy\n");
5941
5942 SetAttrLgcyRetry:
5943 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5944 (void **) &pSMBr);
5945 if (rc)
5946 return rc;
5947
5948 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5949 name_len =
5950 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5951 PATH_MAX, nls_codepage);
5952 name_len++; /* trailing null */
5953 name_len *= 2;
5954 } else {
5955 name_len = copy_path_name(pSMB->fileName, fileName);
5956 }
5957 pSMB->attr = cpu_to_le16(dos_attrs);
5958 pSMB->BufferFormat = 0x04;
5959 inc_rfc1001_len(pSMB, name_len + 1);
5960 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5961 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5962 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5963 if (rc)
5964 cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5965
5966 cifs_buf_release(pSMB);
5967
5968 if (rc == -EAGAIN)
5969 goto SetAttrLgcyRetry;
5970
5971 return rc;
5972 }
5973 #endif /* temporarily unneeded SetAttr legacy function */
5974
5975 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5976 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5977 const struct cifs_unix_set_info_args *args)
5978 {
5979 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5980 u64 mode = args->mode;
5981
5982 if (uid_valid(args->uid))
5983 uid = from_kuid(&init_user_ns, args->uid);
5984 if (gid_valid(args->gid))
5985 gid = from_kgid(&init_user_ns, args->gid);
5986
5987 /*
5988 * Samba server ignores set of file size to zero due to bugs in some
5989 * older clients, but we should be precise - we use SetFileSize to
5990 * set file size and do not want to truncate file size to zero
5991 * accidentally as happened on one Samba server beta by putting
5992 * zero instead of -1 here
5993 */
5994 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5995 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5996 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5997 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5998 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5999 data_offset->Uid = cpu_to_le64(uid);
6000 data_offset->Gid = cpu_to_le64(gid);
6001 /* better to leave device as zero when it is */
6002 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
6003 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
6004 data_offset->Permissions = cpu_to_le64(mode);
6005
6006 if (S_ISREG(mode))
6007 data_offset->Type = cpu_to_le32(UNIX_FILE);
6008 else if (S_ISDIR(mode))
6009 data_offset->Type = cpu_to_le32(UNIX_DIR);
6010 else if (S_ISLNK(mode))
6011 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
6012 else if (S_ISCHR(mode))
6013 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
6014 else if (S_ISBLK(mode))
6015 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
6016 else if (S_ISFIFO(mode))
6017 data_offset->Type = cpu_to_le32(UNIX_FIFO);
6018 else if (S_ISSOCK(mode))
6019 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
6020 }
6021
6022 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)6023 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
6024 const struct cifs_unix_set_info_args *args,
6025 u16 fid, u32 pid_of_opener)
6026 {
6027 struct smb_com_transaction2_sfi_req *pSMB = NULL;
6028 char *data_offset;
6029 int rc = 0;
6030 u16 params, param_offset, offset, byte_count, count;
6031
6032 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
6033 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
6034
6035 if (rc)
6036 return rc;
6037
6038 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
6039 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
6040
6041 params = 6;
6042 pSMB->MaxSetupCount = 0;
6043 pSMB->Reserved = 0;
6044 pSMB->Flags = 0;
6045 pSMB->Timeout = 0;
6046 pSMB->Reserved2 = 0;
6047 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6048 offset = param_offset + params;
6049
6050 data_offset = (char *)pSMB +
6051 offsetof(struct smb_hdr, Protocol) + offset;
6052
6053 count = sizeof(FILE_UNIX_BASIC_INFO);
6054
6055 pSMB->MaxParameterCount = cpu_to_le16(2);
6056 /* BB find max SMB PDU from sess */
6057 pSMB->MaxDataCount = cpu_to_le16(1000);
6058 pSMB->SetupCount = 1;
6059 pSMB->Reserved3 = 0;
6060 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6061 byte_count = 3 /* pad */ + params + count;
6062 pSMB->DataCount = cpu_to_le16(count);
6063 pSMB->ParameterCount = cpu_to_le16(params);
6064 pSMB->TotalDataCount = pSMB->DataCount;
6065 pSMB->TotalParameterCount = pSMB->ParameterCount;
6066 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6067 pSMB->DataOffset = cpu_to_le16(offset);
6068 pSMB->Fid = fid;
6069 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6070 pSMB->Reserved4 = 0;
6071 inc_rfc1001_len(pSMB, byte_count);
6072 pSMB->ByteCount = cpu_to_le16(byte_count);
6073
6074 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6075
6076 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6077 cifs_small_buf_release(pSMB);
6078 if (rc)
6079 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6080 rc);
6081
6082 /* Note: On -EAGAIN error only caller can retry on handle based calls
6083 since file handle passed in no longer valid */
6084
6085 return rc;
6086 }
6087
6088 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)6089 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6090 const char *file_name,
6091 const struct cifs_unix_set_info_args *args,
6092 const struct nls_table *nls_codepage, int remap)
6093 {
6094 TRANSACTION2_SPI_REQ *pSMB = NULL;
6095 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6096 int name_len;
6097 int rc = 0;
6098 int bytes_returned = 0;
6099 FILE_UNIX_BASIC_INFO *data_offset;
6100 __u16 params, param_offset, offset, count, byte_count;
6101
6102 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6103 setPermsRetry:
6104 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6105 (void **) &pSMBr);
6106 if (rc)
6107 return rc;
6108
6109 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6110 name_len =
6111 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6112 PATH_MAX, nls_codepage, remap);
6113 name_len++; /* trailing null */
6114 name_len *= 2;
6115 } else {
6116 name_len = copy_path_name(pSMB->FileName, file_name);
6117 }
6118
6119 params = 6 + name_len;
6120 count = sizeof(FILE_UNIX_BASIC_INFO);
6121 pSMB->MaxParameterCount = cpu_to_le16(2);
6122 /* BB find max SMB PDU from sess structure BB */
6123 pSMB->MaxDataCount = cpu_to_le16(1000);
6124 pSMB->MaxSetupCount = 0;
6125 pSMB->Reserved = 0;
6126 pSMB->Flags = 0;
6127 pSMB->Timeout = 0;
6128 pSMB->Reserved2 = 0;
6129 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6130 InformationLevel) - 4;
6131 offset = param_offset + params;
6132 data_offset =
6133 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6134 offset);
6135 memset(data_offset, 0, count);
6136 pSMB->DataOffset = cpu_to_le16(offset);
6137 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6138 pSMB->SetupCount = 1;
6139 pSMB->Reserved3 = 0;
6140 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6141 byte_count = 3 /* pad */ + params + count;
6142 pSMB->ParameterCount = cpu_to_le16(params);
6143 pSMB->DataCount = cpu_to_le16(count);
6144 pSMB->TotalParameterCount = pSMB->ParameterCount;
6145 pSMB->TotalDataCount = pSMB->DataCount;
6146 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6147 pSMB->Reserved4 = 0;
6148 inc_rfc1001_len(pSMB, byte_count);
6149
6150 cifs_fill_unix_set_info(data_offset, args);
6151
6152 pSMB->ByteCount = cpu_to_le16(byte_count);
6153 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6154 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6155 if (rc)
6156 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6157
6158 cifs_buf_release(pSMB);
6159 if (rc == -EAGAIN)
6160 goto setPermsRetry;
6161 return rc;
6162 }
6163
6164 #ifdef CONFIG_CIFS_XATTR
6165 /*
6166 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6167 * function used by listxattr and getxattr type calls. When ea_name is set,
6168 * it looks for that attribute name and stuffs that value into the EAData
6169 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6170 * buffer. In both cases, the return value is either the length of the
6171 * resulting data or a negative error code. If EAData is a NULL pointer then
6172 * the data isn't copied to it, but the length is returned.
6173 */
6174 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)6175 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6176 const unsigned char *searchName, const unsigned char *ea_name,
6177 char *EAData, size_t buf_size,
6178 struct cifs_sb_info *cifs_sb)
6179 {
6180 /* BB assumes one setup word */
6181 TRANSACTION2_QPI_REQ *pSMB = NULL;
6182 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6183 int remap = cifs_remap(cifs_sb);
6184 struct nls_table *nls_codepage = cifs_sb->local_nls;
6185 int rc = 0;
6186 int bytes_returned;
6187 int list_len;
6188 struct fealist *ea_response_data;
6189 struct fea *temp_fea;
6190 char *temp_ptr;
6191 char *end_of_smb;
6192 __u16 params, byte_count, data_offset;
6193 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6194
6195 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6196 QAllEAsRetry:
6197 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6198 (void **) &pSMBr);
6199 if (rc)
6200 return rc;
6201
6202 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6203 list_len =
6204 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6205 PATH_MAX, nls_codepage, remap);
6206 list_len++; /* trailing null */
6207 list_len *= 2;
6208 } else {
6209 list_len = copy_path_name(pSMB->FileName, searchName);
6210 }
6211
6212 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6213 pSMB->TotalDataCount = 0;
6214 pSMB->MaxParameterCount = cpu_to_le16(2);
6215 /* BB find exact max SMB PDU from sess structure BB */
6216 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6217 pSMB->MaxSetupCount = 0;
6218 pSMB->Reserved = 0;
6219 pSMB->Flags = 0;
6220 pSMB->Timeout = 0;
6221 pSMB->Reserved2 = 0;
6222 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6223 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6224 pSMB->DataCount = 0;
6225 pSMB->DataOffset = 0;
6226 pSMB->SetupCount = 1;
6227 pSMB->Reserved3 = 0;
6228 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6229 byte_count = params + 1 /* pad */ ;
6230 pSMB->TotalParameterCount = cpu_to_le16(params);
6231 pSMB->ParameterCount = pSMB->TotalParameterCount;
6232 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6233 pSMB->Reserved4 = 0;
6234 inc_rfc1001_len(pSMB, byte_count);
6235 pSMB->ByteCount = cpu_to_le16(byte_count);
6236
6237 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6238 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6239 if (rc) {
6240 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6241 goto QAllEAsOut;
6242 }
6243
6244
6245 /* BB also check enough total bytes returned */
6246 /* BB we need to improve the validity checking
6247 of these trans2 responses */
6248
6249 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6250 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6251 rc = -EIO; /* bad smb */
6252 goto QAllEAsOut;
6253 }
6254
6255 /* check that length of list is not more than bcc */
6256 /* check that each entry does not go beyond length
6257 of list */
6258 /* check that each element of each entry does not
6259 go beyond end of list */
6260 /* validate_trans2_offsets() */
6261 /* BB check if start of smb + data_offset > &bcc+ bcc */
6262
6263 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6264 ea_response_data = (struct fealist *)
6265 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6266
6267 list_len = le32_to_cpu(ea_response_data->list_len);
6268 cifs_dbg(FYI, "ea length %d\n", list_len);
6269 if (list_len <= 8) {
6270 cifs_dbg(FYI, "empty EA list returned from server\n");
6271 /* didn't find the named attribute */
6272 if (ea_name)
6273 rc = -ENODATA;
6274 goto QAllEAsOut;
6275 }
6276
6277 /* make sure list_len doesn't go past end of SMB */
6278 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6279 if ((char *)ea_response_data + list_len > end_of_smb) {
6280 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6281 rc = -EIO;
6282 goto QAllEAsOut;
6283 }
6284
6285 /* account for ea list len */
6286 list_len -= 4;
6287 temp_fea = ea_response_data->list;
6288 temp_ptr = (char *)temp_fea;
6289 while (list_len > 0) {
6290 unsigned int name_len;
6291 __u16 value_len;
6292
6293 list_len -= 4;
6294 temp_ptr += 4;
6295 /* make sure we can read name_len and value_len */
6296 if (list_len < 0) {
6297 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6298 rc = -EIO;
6299 goto QAllEAsOut;
6300 }
6301
6302 name_len = temp_fea->name_len;
6303 value_len = le16_to_cpu(temp_fea->value_len);
6304 list_len -= name_len + 1 + value_len;
6305 if (list_len < 0) {
6306 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6307 rc = -EIO;
6308 goto QAllEAsOut;
6309 }
6310
6311 if (ea_name) {
6312 if (ea_name_len == name_len &&
6313 memcmp(ea_name, temp_ptr, name_len) == 0) {
6314 temp_ptr += name_len + 1;
6315 rc = value_len;
6316 if (buf_size == 0)
6317 goto QAllEAsOut;
6318 if ((size_t)value_len > buf_size) {
6319 rc = -ERANGE;
6320 goto QAllEAsOut;
6321 }
6322 memcpy(EAData, temp_ptr, value_len);
6323 goto QAllEAsOut;
6324 }
6325 } else {
6326 /* account for prefix user. and trailing null */
6327 rc += (5 + 1 + name_len);
6328 if (rc < (int) buf_size) {
6329 memcpy(EAData, "user.", 5);
6330 EAData += 5;
6331 memcpy(EAData, temp_ptr, name_len);
6332 EAData += name_len;
6333 /* null terminate name */
6334 *EAData = 0;
6335 ++EAData;
6336 } else if (buf_size == 0) {
6337 /* skip copy - calc size only */
6338 } else {
6339 /* stop before overrun buffer */
6340 rc = -ERANGE;
6341 break;
6342 }
6343 }
6344 temp_ptr += name_len + 1 + value_len;
6345 temp_fea = (struct fea *)temp_ptr;
6346 }
6347
6348 /* didn't find the named attribute */
6349 if (ea_name)
6350 rc = -ENODATA;
6351
6352 QAllEAsOut:
6353 cifs_buf_release(pSMB);
6354 if (rc == -EAGAIN)
6355 goto QAllEAsRetry;
6356
6357 return (ssize_t)rc;
6358 }
6359
6360 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)6361 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6362 const char *fileName, const char *ea_name, const void *ea_value,
6363 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6364 struct cifs_sb_info *cifs_sb)
6365 {
6366 struct smb_com_transaction2_spi_req *pSMB = NULL;
6367 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6368 struct fealist *parm_data;
6369 int name_len;
6370 int rc = 0;
6371 int bytes_returned = 0;
6372 __u16 params, param_offset, byte_count, offset, count;
6373 int remap = cifs_remap(cifs_sb);
6374
6375 cifs_dbg(FYI, "In SetEA\n");
6376 SetEARetry:
6377 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6378 (void **) &pSMBr);
6379 if (rc)
6380 return rc;
6381
6382 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6383 name_len =
6384 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6385 PATH_MAX, nls_codepage, remap);
6386 name_len++; /* trailing null */
6387 name_len *= 2;
6388 } else {
6389 name_len = copy_path_name(pSMB->FileName, fileName);
6390 }
6391
6392 params = 6 + name_len;
6393
6394 /* done calculating parms using name_len of file name,
6395 now use name_len to calculate length of ea name
6396 we are going to create in the inode xattrs */
6397 if (ea_name == NULL)
6398 name_len = 0;
6399 else
6400 name_len = strnlen(ea_name, 255);
6401
6402 count = sizeof(*parm_data) + ea_value_len + name_len;
6403 pSMB->MaxParameterCount = cpu_to_le16(2);
6404 /* BB find max SMB PDU from sess */
6405 pSMB->MaxDataCount = cpu_to_le16(1000);
6406 pSMB->MaxSetupCount = 0;
6407 pSMB->Reserved = 0;
6408 pSMB->Flags = 0;
6409 pSMB->Timeout = 0;
6410 pSMB->Reserved2 = 0;
6411 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6412 InformationLevel) - 4;
6413 offset = param_offset + params;
6414 pSMB->InformationLevel =
6415 cpu_to_le16(SMB_SET_FILE_EA);
6416
6417 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6418 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6419 pSMB->DataOffset = cpu_to_le16(offset);
6420 pSMB->SetupCount = 1;
6421 pSMB->Reserved3 = 0;
6422 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6423 byte_count = 3 /* pad */ + params + count;
6424 pSMB->DataCount = cpu_to_le16(count);
6425 parm_data->list_len = cpu_to_le32(count);
6426 parm_data->list[0].EA_flags = 0;
6427 /* we checked above that name len is less than 255 */
6428 parm_data->list[0].name_len = (__u8)name_len;
6429 /* EA names are always ASCII */
6430 if (ea_name)
6431 strncpy(parm_data->list[0].name, ea_name, name_len);
6432 parm_data->list[0].name[name_len] = 0;
6433 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6434 /* caller ensures that ea_value_len is less than 64K but
6435 we need to ensure that it fits within the smb */
6436
6437 /*BB add length check to see if it would fit in
6438 negotiated SMB buffer size BB */
6439 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6440 if (ea_value_len)
6441 memcpy(parm_data->list[0].name+name_len+1,
6442 ea_value, ea_value_len);
6443
6444 pSMB->TotalDataCount = pSMB->DataCount;
6445 pSMB->ParameterCount = cpu_to_le16(params);
6446 pSMB->TotalParameterCount = pSMB->ParameterCount;
6447 pSMB->Reserved4 = 0;
6448 inc_rfc1001_len(pSMB, byte_count);
6449 pSMB->ByteCount = cpu_to_le16(byte_count);
6450 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6451 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6452 if (rc)
6453 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6454
6455 cifs_buf_release(pSMB);
6456
6457 if (rc == -EAGAIN)
6458 goto SetEARetry;
6459
6460 return rc;
6461 }
6462 #endif
6463