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