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)1461 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1462 {
1463 int length;
1464 struct cifs_readdata *rdata = mid->callback_data;
1465
1466 length = cifs_discard_remaining_data(server);
1467 dequeue_mid(mid, rdata->result);
1468 mid->resp_buf = server->smallbuf;
1469 server->smallbuf = NULL;
1470 return length;
1471 }
1472
1473 int
cifs_readv_receive(struct TCP_Server_Info * server,struct mid_q_entry * mid)1474 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1475 {
1476 int length, len;
1477 unsigned int data_offset, data_len;
1478 struct cifs_readdata *rdata = mid->callback_data;
1479 char *buf = server->smallbuf;
1480 unsigned int buflen = server->pdu_size +
1481 server->vals->header_preamble_size;
1482 bool use_rdma_mr = false;
1483
1484 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1485 __func__, mid->mid, rdata->offset, rdata->bytes);
1486
1487 /*
1488 * read the rest of READ_RSP header (sans Data array), or whatever we
1489 * can if there's not enough data. At this point, we've read down to
1490 * the Mid.
1491 */
1492 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1493 HEADER_SIZE(server) + 1;
1494
1495 length = cifs_read_from_socket(server,
1496 buf + HEADER_SIZE(server) - 1, len);
1497 if (length < 0)
1498 return length;
1499 server->total_read += length;
1500
1501 if (server->ops->is_session_expired &&
1502 server->ops->is_session_expired(buf)) {
1503 cifs_reconnect(server);
1504 wake_up(&server->response_q);
1505 return -1;
1506 }
1507
1508 if (server->ops->is_status_pending &&
1509 server->ops->is_status_pending(buf, server, 0)) {
1510 cifs_discard_remaining_data(server);
1511 return -1;
1512 }
1513
1514 /* Was the SMB read successful? */
1515 rdata->result = server->ops->map_error(buf, false);
1516 if (rdata->result != 0) {
1517 cifs_dbg(FYI, "%s: server returned error %d\n",
1518 __func__, rdata->result);
1519 return cifs_readv_discard(server, mid);
1520 }
1521
1522 /* Is there enough to get to the rest of the READ_RSP header? */
1523 if (server->total_read < server->vals->read_rsp_size) {
1524 cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1525 __func__, server->total_read,
1526 server->vals->read_rsp_size);
1527 rdata->result = -EIO;
1528 return cifs_readv_discard(server, mid);
1529 }
1530
1531 data_offset = server->ops->read_data_offset(buf) +
1532 server->vals->header_preamble_size;
1533 if (data_offset < server->total_read) {
1534 /*
1535 * win2k8 sometimes sends an offset of 0 when the read
1536 * is beyond the EOF. Treat it as if the data starts just after
1537 * the header.
1538 */
1539 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1540 __func__, data_offset);
1541 data_offset = server->total_read;
1542 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1543 /* data_offset is beyond the end of smallbuf */
1544 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1545 __func__, data_offset);
1546 rdata->result = -EIO;
1547 return cifs_readv_discard(server, mid);
1548 }
1549
1550 cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1551 __func__, server->total_read, data_offset);
1552
1553 len = data_offset - server->total_read;
1554 if (len > 0) {
1555 /* read any junk before data into the rest of smallbuf */
1556 length = cifs_read_from_socket(server,
1557 buf + server->total_read, len);
1558 if (length < 0)
1559 return length;
1560 server->total_read += length;
1561 }
1562
1563 /* set up first iov for signature check */
1564 rdata->iov[0].iov_base = buf;
1565 rdata->iov[0].iov_len = 4;
1566 rdata->iov[1].iov_base = buf + 4;
1567 rdata->iov[1].iov_len = server->total_read - 4;
1568 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1569 rdata->iov[0].iov_base, server->total_read);
1570
1571 /* how much data is in the response? */
1572 #ifdef CONFIG_CIFS_SMB_DIRECT
1573 use_rdma_mr = rdata->mr;
1574 #endif
1575 data_len = server->ops->read_data_length(buf, use_rdma_mr);
1576 if (!use_rdma_mr && (data_offset + data_len > buflen)) {
1577 /* data_len is corrupt -- discard frame */
1578 rdata->result = -EIO;
1579 return cifs_readv_discard(server, mid);
1580 }
1581
1582 length = rdata->read_into_pages(server, rdata, data_len);
1583 if (length < 0)
1584 return length;
1585
1586 server->total_read += length;
1587
1588 cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1589 server->total_read, buflen, data_len);
1590
1591 /* discard anything left over */
1592 if (server->total_read < buflen)
1593 return cifs_readv_discard(server, mid);
1594
1595 dequeue_mid(mid, false);
1596 mid->resp_buf = server->smallbuf;
1597 server->smallbuf = NULL;
1598 return length;
1599 }
1600
1601 static void
cifs_readv_callback(struct mid_q_entry * mid)1602 cifs_readv_callback(struct mid_q_entry *mid)
1603 {
1604 struct cifs_readdata *rdata = mid->callback_data;
1605 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1606 struct TCP_Server_Info *server = tcon->ses->server;
1607 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1608 .rq_nvec = 2,
1609 .rq_pages = rdata->pages,
1610 .rq_npages = rdata->nr_pages,
1611 .rq_pagesz = rdata->pagesz,
1612 .rq_tailsz = rdata->tailsz };
1613
1614 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1615 __func__, mid->mid, mid->mid_state, rdata->result,
1616 rdata->bytes);
1617
1618 switch (mid->mid_state) {
1619 case MID_RESPONSE_RECEIVED:
1620 /* result already set, check signature */
1621 if (server->sign) {
1622 int rc = 0;
1623
1624 rc = cifs_verify_signature(&rqst, server,
1625 mid->sequence_number);
1626 if (rc)
1627 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1628 rc);
1629 }
1630 /* FIXME: should this be counted toward the initiating task? */
1631 task_io_account_read(rdata->got_bytes);
1632 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1633 break;
1634 case MID_REQUEST_SUBMITTED:
1635 case MID_RETRY_NEEDED:
1636 rdata->result = -EAGAIN;
1637 if (server->sign && rdata->got_bytes)
1638 /* reset bytes number since we can not check a sign */
1639 rdata->got_bytes = 0;
1640 /* FIXME: should this be counted toward the initiating task? */
1641 task_io_account_read(rdata->got_bytes);
1642 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1643 break;
1644 default:
1645 rdata->result = -EIO;
1646 }
1647
1648 queue_work(cifsiod_wq, &rdata->work);
1649 DeleteMidQEntry(mid);
1650 add_credits(server, 1, 0);
1651 }
1652
1653 /* cifs_async_readv - send an async write, and set up mid to handle result */
1654 int
cifs_async_readv(struct cifs_readdata * rdata)1655 cifs_async_readv(struct cifs_readdata *rdata)
1656 {
1657 int rc;
1658 READ_REQ *smb = NULL;
1659 int wct;
1660 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1661 struct smb_rqst rqst = { .rq_iov = rdata->iov,
1662 .rq_nvec = 2 };
1663
1664 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1665 __func__, rdata->offset, rdata->bytes);
1666
1667 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1668 wct = 12;
1669 else {
1670 wct = 10; /* old style read */
1671 if ((rdata->offset >> 32) > 0) {
1672 /* can not handle this big offset for old */
1673 return -EIO;
1674 }
1675 }
1676
1677 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1678 if (rc)
1679 return rc;
1680
1681 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1682 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1683
1684 smb->AndXCommand = 0xFF; /* none */
1685 smb->Fid = rdata->cfile->fid.netfid;
1686 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1687 if (wct == 12)
1688 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1689 smb->Remaining = 0;
1690 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1691 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1692 if (wct == 12)
1693 smb->ByteCount = 0;
1694 else {
1695 /* old style read */
1696 struct smb_com_readx_req *smbr =
1697 (struct smb_com_readx_req *)smb;
1698 smbr->ByteCount = 0;
1699 }
1700
1701 /* 4 for RFC1001 length + 1 for BCC */
1702 rdata->iov[0].iov_base = smb;
1703 rdata->iov[0].iov_len = 4;
1704 rdata->iov[1].iov_base = (char *)smb + 4;
1705 rdata->iov[1].iov_len = get_rfc1002_length(smb);
1706
1707 kref_get(&rdata->refcount);
1708 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1709 cifs_readv_callback, NULL, rdata, 0);
1710
1711 if (rc == 0)
1712 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1713 else
1714 kref_put(&rdata->refcount, cifs_readdata_release);
1715
1716 cifs_small_buf_release(smb);
1717 return rc;
1718 }
1719
1720 int
CIFSSMBRead(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,char ** buf,int * pbuf_type)1721 CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1722 unsigned int *nbytes, char **buf, int *pbuf_type)
1723 {
1724 int rc = -EACCES;
1725 READ_REQ *pSMB = NULL;
1726 READ_RSP *pSMBr = NULL;
1727 char *pReadData = NULL;
1728 int wct;
1729 int resp_buf_type = 0;
1730 struct kvec iov[1];
1731 struct kvec rsp_iov;
1732 __u32 pid = io_parms->pid;
1733 __u16 netfid = io_parms->netfid;
1734 __u64 offset = io_parms->offset;
1735 struct cifs_tcon *tcon = io_parms->tcon;
1736 unsigned int count = io_parms->length;
1737
1738 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1739 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1740 wct = 12;
1741 else {
1742 wct = 10; /* old style read */
1743 if ((offset >> 32) > 0) {
1744 /* can not handle this big offset for old */
1745 return -EIO;
1746 }
1747 }
1748
1749 *nbytes = 0;
1750 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1751 if (rc)
1752 return rc;
1753
1754 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1755 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1756
1757 /* tcon and ses pointer are checked in smb_init */
1758 if (tcon->ses->server == NULL)
1759 return -ECONNABORTED;
1760
1761 pSMB->AndXCommand = 0xFF; /* none */
1762 pSMB->Fid = netfid;
1763 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1764 if (wct == 12)
1765 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1766
1767 pSMB->Remaining = 0;
1768 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1769 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1770 if (wct == 12)
1771 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1772 else {
1773 /* old style read */
1774 struct smb_com_readx_req *pSMBW =
1775 (struct smb_com_readx_req *)pSMB;
1776 pSMBW->ByteCount = 0;
1777 }
1778
1779 iov[0].iov_base = (char *)pSMB;
1780 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1781 rc = SendReceive2(xid, tcon->ses, iov, 1, &resp_buf_type,
1782 CIFS_LOG_ERROR, &rsp_iov);
1783 cifs_small_buf_release(pSMB);
1784 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1785 pSMBr = (READ_RSP *)rsp_iov.iov_base;
1786 if (rc) {
1787 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1788 } else {
1789 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1790 data_length = data_length << 16;
1791 data_length += le16_to_cpu(pSMBr->DataLength);
1792 *nbytes = data_length;
1793
1794 /*check that DataLength would not go beyond end of SMB */
1795 if ((data_length > CIFSMaxBufSize)
1796 || (data_length > count)) {
1797 cifs_dbg(FYI, "bad length %d for count %d\n",
1798 data_length, count);
1799 rc = -EIO;
1800 *nbytes = 0;
1801 } else {
1802 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1803 le16_to_cpu(pSMBr->DataOffset);
1804 /* if (rc = copy_to_user(buf, pReadData, data_length)) {
1805 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1806 rc = -EFAULT;
1807 }*/ /* can not use copy_to_user when using page cache*/
1808 if (*buf)
1809 memcpy(*buf, pReadData, data_length);
1810 }
1811 }
1812
1813 if (*buf) {
1814 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
1815 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1816 /* return buffer to caller to free */
1817 *buf = rsp_iov.iov_base;
1818 if (resp_buf_type == CIFS_SMALL_BUFFER)
1819 *pbuf_type = CIFS_SMALL_BUFFER;
1820 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1821 *pbuf_type = CIFS_LARGE_BUFFER;
1822 } /* else no valid buffer on return - leave as null */
1823
1824 /* Note: On -EAGAIN error only caller can retry on handle based calls
1825 since file handle passed in no longer valid */
1826 return rc;
1827 }
1828
1829
1830 int
CIFSSMBWrite(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,const char * buf)1831 CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1832 unsigned int *nbytes, const char *buf)
1833 {
1834 int rc = -EACCES;
1835 WRITE_REQ *pSMB = NULL;
1836 WRITE_RSP *pSMBr = NULL;
1837 int bytes_returned, wct;
1838 __u32 bytes_sent;
1839 __u16 byte_count;
1840 __u32 pid = io_parms->pid;
1841 __u16 netfid = io_parms->netfid;
1842 __u64 offset = io_parms->offset;
1843 struct cifs_tcon *tcon = io_parms->tcon;
1844 unsigned int count = io_parms->length;
1845
1846 *nbytes = 0;
1847
1848 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1849 if (tcon->ses == NULL)
1850 return -ECONNABORTED;
1851
1852 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1853 wct = 14;
1854 else {
1855 wct = 12;
1856 if ((offset >> 32) > 0) {
1857 /* can not handle big offset for old srv */
1858 return -EIO;
1859 }
1860 }
1861
1862 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1863 (void **) &pSMBr);
1864 if (rc)
1865 return rc;
1866
1867 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1868 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1869
1870 /* tcon and ses pointer are checked in smb_init */
1871 if (tcon->ses->server == NULL)
1872 return -ECONNABORTED;
1873
1874 pSMB->AndXCommand = 0xFF; /* none */
1875 pSMB->Fid = netfid;
1876 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1877 if (wct == 14)
1878 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1879
1880 pSMB->Reserved = 0xFFFFFFFF;
1881 pSMB->WriteMode = 0;
1882 pSMB->Remaining = 0;
1883
1884 /* Can increase buffer size if buffer is big enough in some cases ie we
1885 can send more if LARGE_WRITE_X capability returned by the server and if
1886 our buffer is big enough or if we convert to iovecs on socket writes
1887 and eliminate the copy to the CIFS buffer */
1888 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1889 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1890 } else {
1891 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1892 & ~0xFF;
1893 }
1894
1895 if (bytes_sent > count)
1896 bytes_sent = count;
1897 pSMB->DataOffset =
1898 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1899 if (buf)
1900 memcpy(pSMB->Data, buf, bytes_sent);
1901 else if (count != 0) {
1902 /* No buffer */
1903 cifs_buf_release(pSMB);
1904 return -EINVAL;
1905 } /* else setting file size with write of zero bytes */
1906 if (wct == 14)
1907 byte_count = bytes_sent + 1; /* pad */
1908 else /* wct == 12 */
1909 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1910
1911 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1912 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1913 inc_rfc1001_len(pSMB, byte_count);
1914
1915 if (wct == 14)
1916 pSMB->ByteCount = cpu_to_le16(byte_count);
1917 else { /* old style write has byte count 4 bytes earlier
1918 so 4 bytes pad */
1919 struct smb_com_writex_req *pSMBW =
1920 (struct smb_com_writex_req *)pSMB;
1921 pSMBW->ByteCount = cpu_to_le16(byte_count);
1922 }
1923
1924 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1925 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1926 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1927 if (rc) {
1928 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1929 } else {
1930 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1931 *nbytes = (*nbytes) << 16;
1932 *nbytes += le16_to_cpu(pSMBr->Count);
1933
1934 /*
1935 * Mask off high 16 bits when bytes written as returned by the
1936 * server is greater than bytes requested by the client. Some
1937 * OS/2 servers are known to set incorrect CountHigh values.
1938 */
1939 if (*nbytes > count)
1940 *nbytes &= 0xFFFF;
1941 }
1942
1943 cifs_buf_release(pSMB);
1944
1945 /* Note: On -EAGAIN error only caller can retry on handle based calls
1946 since file handle passed in no longer valid */
1947
1948 return rc;
1949 }
1950
1951 void
cifs_writedata_release(struct kref * refcount)1952 cifs_writedata_release(struct kref *refcount)
1953 {
1954 struct cifs_writedata *wdata = container_of(refcount,
1955 struct cifs_writedata, refcount);
1956 #ifdef CONFIG_CIFS_SMB_DIRECT
1957 if (wdata->mr) {
1958 smbd_deregister_mr(wdata->mr);
1959 wdata->mr = NULL;
1960 }
1961 #endif
1962
1963 if (wdata->cfile)
1964 cifsFileInfo_put(wdata->cfile);
1965
1966 kvfree(wdata->pages);
1967 kfree(wdata);
1968 }
1969
1970 /*
1971 * Write failed with a retryable error. Resend the write request. It's also
1972 * possible that the page was redirtied so re-clean the page.
1973 */
1974 static void
cifs_writev_requeue(struct cifs_writedata * wdata)1975 cifs_writev_requeue(struct cifs_writedata *wdata)
1976 {
1977 int i, rc = 0;
1978 struct inode *inode = d_inode(wdata->cfile->dentry);
1979 struct TCP_Server_Info *server;
1980 unsigned int rest_len;
1981
1982 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1983 i = 0;
1984 rest_len = wdata->bytes;
1985 do {
1986 struct cifs_writedata *wdata2;
1987 unsigned int j, nr_pages, wsize, tailsz, cur_len;
1988
1989 wsize = server->ops->wp_retry_size(inode);
1990 if (wsize < rest_len) {
1991 nr_pages = wsize / PAGE_SIZE;
1992 if (!nr_pages) {
1993 rc = -ENOTSUPP;
1994 break;
1995 }
1996 cur_len = nr_pages * PAGE_SIZE;
1997 tailsz = PAGE_SIZE;
1998 } else {
1999 nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
2000 cur_len = rest_len;
2001 tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
2002 }
2003
2004 wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
2005 if (!wdata2) {
2006 rc = -ENOMEM;
2007 break;
2008 }
2009
2010 for (j = 0; j < nr_pages; j++) {
2011 wdata2->pages[j] = wdata->pages[i + j];
2012 lock_page(wdata2->pages[j]);
2013 clear_page_dirty_for_io(wdata2->pages[j]);
2014 }
2015
2016 wdata2->sync_mode = wdata->sync_mode;
2017 wdata2->nr_pages = nr_pages;
2018 wdata2->offset = page_offset(wdata2->pages[0]);
2019 wdata2->pagesz = PAGE_SIZE;
2020 wdata2->tailsz = tailsz;
2021 wdata2->bytes = cur_len;
2022
2023 wdata2->cfile = find_writable_file(CIFS_I(inode), false);
2024 if (!wdata2->cfile) {
2025 cifs_dbg(VFS, "No writable handles for inode\n");
2026 rc = -EBADF;
2027 break;
2028 }
2029 wdata2->pid = wdata2->cfile->pid;
2030 rc = server->ops->async_writev(wdata2, cifs_writedata_release);
2031
2032 for (j = 0; j < nr_pages; j++) {
2033 unlock_page(wdata2->pages[j]);
2034 if (rc != 0 && rc != -EAGAIN) {
2035 SetPageError(wdata2->pages[j]);
2036 end_page_writeback(wdata2->pages[j]);
2037 put_page(wdata2->pages[j]);
2038 }
2039 }
2040
2041 if (rc) {
2042 kref_put(&wdata2->refcount, cifs_writedata_release);
2043 if (rc == -EAGAIN)
2044 continue;
2045 break;
2046 }
2047
2048 rest_len -= cur_len;
2049 i += nr_pages;
2050 } while (i < wdata->nr_pages);
2051
2052 mapping_set_error(inode->i_mapping, rc);
2053 kref_put(&wdata->refcount, cifs_writedata_release);
2054 }
2055
2056 void
cifs_writev_complete(struct work_struct * work)2057 cifs_writev_complete(struct work_struct *work)
2058 {
2059 struct cifs_writedata *wdata = container_of(work,
2060 struct cifs_writedata, work);
2061 struct inode *inode = d_inode(wdata->cfile->dentry);
2062 int i = 0;
2063
2064 if (wdata->result == 0) {
2065 spin_lock(&inode->i_lock);
2066 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2067 spin_unlock(&inode->i_lock);
2068 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2069 wdata->bytes);
2070 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2071 return cifs_writev_requeue(wdata);
2072
2073 for (i = 0; i < wdata->nr_pages; i++) {
2074 struct page *page = wdata->pages[i];
2075 if (wdata->result == -EAGAIN)
2076 __set_page_dirty_nobuffers(page);
2077 else if (wdata->result < 0)
2078 SetPageError(page);
2079 end_page_writeback(page);
2080 put_page(page);
2081 }
2082 if (wdata->result != -EAGAIN)
2083 mapping_set_error(inode->i_mapping, wdata->result);
2084 kref_put(&wdata->refcount, cifs_writedata_release);
2085 }
2086
2087 struct cifs_writedata *
cifs_writedata_alloc(unsigned int nr_pages,work_func_t complete)2088 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2089 {
2090 struct page **pages =
2091 kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
2092 if (pages)
2093 return cifs_writedata_direct_alloc(pages, complete);
2094
2095 return NULL;
2096 }
2097
2098 struct cifs_writedata *
cifs_writedata_direct_alloc(struct page ** pages,work_func_t complete)2099 cifs_writedata_direct_alloc(struct page **pages, work_func_t complete)
2100 {
2101 struct cifs_writedata *wdata;
2102
2103 wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
2104 if (wdata != NULL) {
2105 wdata->pages = pages;
2106 kref_init(&wdata->refcount);
2107 INIT_LIST_HEAD(&wdata->list);
2108 init_completion(&wdata->done);
2109 INIT_WORK(&wdata->work, complete);
2110 }
2111 return wdata;
2112 }
2113
2114 /*
2115 * Check the mid_state and signature on received buffer (if any), and queue the
2116 * workqueue completion task.
2117 */
2118 static void
cifs_writev_callback(struct mid_q_entry * mid)2119 cifs_writev_callback(struct mid_q_entry *mid)
2120 {
2121 struct cifs_writedata *wdata = mid->callback_data;
2122 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2123 unsigned int written;
2124 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2125
2126 switch (mid->mid_state) {
2127 case MID_RESPONSE_RECEIVED:
2128 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2129 if (wdata->result != 0)
2130 break;
2131
2132 written = le16_to_cpu(smb->CountHigh);
2133 written <<= 16;
2134 written += le16_to_cpu(smb->Count);
2135 /*
2136 * Mask off high 16 bits when bytes written as returned
2137 * by the server is greater than bytes requested by the
2138 * client. OS/2 servers are known to set incorrect
2139 * CountHigh values.
2140 */
2141 if (written > wdata->bytes)
2142 written &= 0xFFFF;
2143
2144 if (written < wdata->bytes)
2145 wdata->result = -ENOSPC;
2146 else
2147 wdata->bytes = written;
2148 break;
2149 case MID_REQUEST_SUBMITTED:
2150 case MID_RETRY_NEEDED:
2151 wdata->result = -EAGAIN;
2152 break;
2153 default:
2154 wdata->result = -EIO;
2155 break;
2156 }
2157
2158 queue_work(cifsiod_wq, &wdata->work);
2159 DeleteMidQEntry(mid);
2160 add_credits(tcon->ses->server, 1, 0);
2161 }
2162
2163 /* cifs_async_writev - send an async write, and set up mid to handle result */
2164 int
cifs_async_writev(struct cifs_writedata * wdata,void (* release)(struct kref * kref))2165 cifs_async_writev(struct cifs_writedata *wdata,
2166 void (*release)(struct kref *kref))
2167 {
2168 int rc = -EACCES;
2169 WRITE_REQ *smb = NULL;
2170 int wct;
2171 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2172 struct kvec iov[2];
2173 struct smb_rqst rqst = { };
2174
2175 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2176 wct = 14;
2177 } else {
2178 wct = 12;
2179 if (wdata->offset >> 32 > 0) {
2180 /* can not handle big offset for old srv */
2181 return -EIO;
2182 }
2183 }
2184
2185 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2186 if (rc)
2187 goto async_writev_out;
2188
2189 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2190 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2191
2192 smb->AndXCommand = 0xFF; /* none */
2193 smb->Fid = wdata->cfile->fid.netfid;
2194 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2195 if (wct == 14)
2196 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2197 smb->Reserved = 0xFFFFFFFF;
2198 smb->WriteMode = 0;
2199 smb->Remaining = 0;
2200
2201 smb->DataOffset =
2202 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2203
2204 /* 4 for RFC1001 length + 1 for BCC */
2205 iov[0].iov_len = 4;
2206 iov[0].iov_base = smb;
2207 iov[1].iov_len = get_rfc1002_length(smb) + 1;
2208 iov[1].iov_base = (char *)smb + 4;
2209
2210 rqst.rq_iov = iov;
2211 rqst.rq_nvec = 2;
2212 rqst.rq_pages = wdata->pages;
2213 rqst.rq_npages = wdata->nr_pages;
2214 rqst.rq_pagesz = wdata->pagesz;
2215 rqst.rq_tailsz = wdata->tailsz;
2216
2217 cifs_dbg(FYI, "async write at %llu %u bytes\n",
2218 wdata->offset, wdata->bytes);
2219
2220 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2221 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2222
2223 if (wct == 14) {
2224 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2225 put_bcc(wdata->bytes + 1, &smb->hdr);
2226 } else {
2227 /* wct == 12 */
2228 struct smb_com_writex_req *smbw =
2229 (struct smb_com_writex_req *)smb;
2230 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2231 put_bcc(wdata->bytes + 5, &smbw->hdr);
2232 iov[1].iov_len += 4; /* pad bigger by four bytes */
2233 }
2234
2235 kref_get(&wdata->refcount);
2236 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2237 cifs_writev_callback, NULL, wdata, 0);
2238
2239 if (rc == 0)
2240 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2241 else
2242 kref_put(&wdata->refcount, release);
2243
2244 async_writev_out:
2245 cifs_small_buf_release(smb);
2246 return rc;
2247 }
2248
2249 int
CIFSSMBWrite2(const unsigned int xid,struct cifs_io_parms * io_parms,unsigned int * nbytes,struct kvec * iov,int n_vec)2250 CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2251 unsigned int *nbytes, struct kvec *iov, int n_vec)
2252 {
2253 int rc = -EACCES;
2254 WRITE_REQ *pSMB = NULL;
2255 int wct;
2256 int smb_hdr_len;
2257 int resp_buf_type = 0;
2258 __u32 pid = io_parms->pid;
2259 __u16 netfid = io_parms->netfid;
2260 __u64 offset = io_parms->offset;
2261 struct cifs_tcon *tcon = io_parms->tcon;
2262 unsigned int count = io_parms->length;
2263 struct kvec rsp_iov;
2264
2265 *nbytes = 0;
2266
2267 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2268
2269 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2270 wct = 14;
2271 } else {
2272 wct = 12;
2273 if ((offset >> 32) > 0) {
2274 /* can not handle big offset for old srv */
2275 return -EIO;
2276 }
2277 }
2278 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2279 if (rc)
2280 return rc;
2281
2282 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2283 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2284
2285 /* tcon and ses pointer are checked in smb_init */
2286 if (tcon->ses->server == NULL)
2287 return -ECONNABORTED;
2288
2289 pSMB->AndXCommand = 0xFF; /* none */
2290 pSMB->Fid = netfid;
2291 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2292 if (wct == 14)
2293 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2294 pSMB->Reserved = 0xFFFFFFFF;
2295 pSMB->WriteMode = 0;
2296 pSMB->Remaining = 0;
2297
2298 pSMB->DataOffset =
2299 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2300
2301 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2302 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2303 /* header + 1 byte pad */
2304 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2305 if (wct == 14)
2306 inc_rfc1001_len(pSMB, count + 1);
2307 else /* wct == 12 */
2308 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2309 if (wct == 14)
2310 pSMB->ByteCount = cpu_to_le16(count + 1);
2311 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2312 struct smb_com_writex_req *pSMBW =
2313 (struct smb_com_writex_req *)pSMB;
2314 pSMBW->ByteCount = cpu_to_le16(count + 5);
2315 }
2316 iov[0].iov_base = pSMB;
2317 if (wct == 14)
2318 iov[0].iov_len = smb_hdr_len + 4;
2319 else /* wct == 12 pad bigger by four bytes */
2320 iov[0].iov_len = smb_hdr_len + 8;
2321
2322 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0,
2323 &rsp_iov);
2324 cifs_small_buf_release(pSMB);
2325 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2326 if (rc) {
2327 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2328 } else if (resp_buf_type == 0) {
2329 /* presumably this can not happen, but best to be safe */
2330 rc = -EIO;
2331 } else {
2332 WRITE_RSP *pSMBr = (WRITE_RSP *)rsp_iov.iov_base;
2333 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2334 *nbytes = (*nbytes) << 16;
2335 *nbytes += le16_to_cpu(pSMBr->Count);
2336
2337 /*
2338 * Mask off high 16 bits when bytes written as returned by the
2339 * server is greater than bytes requested by the client. OS/2
2340 * servers are known to set incorrect CountHigh values.
2341 */
2342 if (*nbytes > count)
2343 *nbytes &= 0xFFFF;
2344 }
2345
2346 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2347
2348 /* Note: On -EAGAIN error only caller can retry on handle based calls
2349 since file handle passed in no longer valid */
2350
2351 return rc;
2352 }
2353
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)2354 int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2355 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2356 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2357 {
2358 int rc = 0;
2359 LOCK_REQ *pSMB = NULL;
2360 struct kvec iov[2];
2361 struct kvec rsp_iov;
2362 int resp_buf_type;
2363 __u16 count;
2364
2365 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2366 num_lock, num_unlock);
2367
2368 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2369 if (rc)
2370 return rc;
2371
2372 pSMB->Timeout = 0;
2373 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2374 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2375 pSMB->LockType = lock_type;
2376 pSMB->AndXCommand = 0xFF; /* none */
2377 pSMB->Fid = netfid; /* netfid stays le */
2378
2379 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2380 inc_rfc1001_len(pSMB, count);
2381 pSMB->ByteCount = cpu_to_le16(count);
2382
2383 iov[0].iov_base = (char *)pSMB;
2384 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2385 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2386 iov[1].iov_base = (char *)buf;
2387 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2388
2389 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2390 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP,
2391 &rsp_iov);
2392 cifs_small_buf_release(pSMB);
2393 if (rc)
2394 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2395
2396 return rc;
2397 }
2398
2399 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)2400 CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2401 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2402 const __u64 offset, const __u32 numUnlock,
2403 const __u32 numLock, const __u8 lockType,
2404 const bool waitFlag, const __u8 oplock_level)
2405 {
2406 int rc = 0;
2407 LOCK_REQ *pSMB = NULL;
2408 /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2409 int bytes_returned;
2410 int flags = 0;
2411 __u16 count;
2412
2413 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2414 (int)waitFlag, numLock);
2415 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2416
2417 if (rc)
2418 return rc;
2419
2420 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2421 /* no response expected */
2422 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2423 pSMB->Timeout = 0;
2424 } else if (waitFlag) {
2425 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2426 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2427 } else {
2428 pSMB->Timeout = 0;
2429 }
2430
2431 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2432 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2433 pSMB->LockType = lockType;
2434 pSMB->OplockLevel = oplock_level;
2435 pSMB->AndXCommand = 0xFF; /* none */
2436 pSMB->Fid = smb_file_id; /* netfid stays le */
2437
2438 if ((numLock != 0) || (numUnlock != 0)) {
2439 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2440 /* BB where to store pid high? */
2441 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2442 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2443 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2444 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2445 count = sizeof(LOCKING_ANDX_RANGE);
2446 } else {
2447 /* oplock break */
2448 count = 0;
2449 }
2450 inc_rfc1001_len(pSMB, count);
2451 pSMB->ByteCount = cpu_to_le16(count);
2452
2453 if (waitFlag)
2454 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2455 (struct smb_hdr *) pSMB, &bytes_returned);
2456 else
2457 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2458 cifs_small_buf_release(pSMB);
2459 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2460 if (rc)
2461 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2462
2463 /* Note: On -EAGAIN error only caller can retry on handle based calls
2464 since file handle passed in no longer valid */
2465 return rc;
2466 }
2467
2468 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)2469 CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2470 const __u16 smb_file_id, const __u32 netpid,
2471 const loff_t start_offset, const __u64 len,
2472 struct file_lock *pLockData, const __u16 lock_type,
2473 const bool waitFlag)
2474 {
2475 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2476 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2477 struct cifs_posix_lock *parm_data;
2478 int rc = 0;
2479 int timeout = 0;
2480 int bytes_returned = 0;
2481 int resp_buf_type = 0;
2482 __u16 params, param_offset, offset, byte_count, count;
2483 struct kvec iov[1];
2484 struct kvec rsp_iov;
2485
2486 cifs_dbg(FYI, "Posix Lock\n");
2487
2488 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2489
2490 if (rc)
2491 return rc;
2492
2493 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2494
2495 params = 6;
2496 pSMB->MaxSetupCount = 0;
2497 pSMB->Reserved = 0;
2498 pSMB->Flags = 0;
2499 pSMB->Reserved2 = 0;
2500 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2501 offset = param_offset + params;
2502
2503 count = sizeof(struct cifs_posix_lock);
2504 pSMB->MaxParameterCount = cpu_to_le16(2);
2505 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2506 pSMB->SetupCount = 1;
2507 pSMB->Reserved3 = 0;
2508 if (pLockData)
2509 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2510 else
2511 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2512 byte_count = 3 /* pad */ + params + count;
2513 pSMB->DataCount = cpu_to_le16(count);
2514 pSMB->ParameterCount = cpu_to_le16(params);
2515 pSMB->TotalDataCount = pSMB->DataCount;
2516 pSMB->TotalParameterCount = pSMB->ParameterCount;
2517 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2518 parm_data = (struct cifs_posix_lock *)
2519 (((char *) &pSMB->hdr.Protocol) + offset);
2520
2521 parm_data->lock_type = cpu_to_le16(lock_type);
2522 if (waitFlag) {
2523 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2524 parm_data->lock_flags = cpu_to_le16(1);
2525 pSMB->Timeout = cpu_to_le32(-1);
2526 } else
2527 pSMB->Timeout = 0;
2528
2529 parm_data->pid = cpu_to_le32(netpid);
2530 parm_data->start = cpu_to_le64(start_offset);
2531 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2532
2533 pSMB->DataOffset = cpu_to_le16(offset);
2534 pSMB->Fid = smb_file_id;
2535 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2536 pSMB->Reserved4 = 0;
2537 inc_rfc1001_len(pSMB, byte_count);
2538 pSMB->ByteCount = cpu_to_le16(byte_count);
2539 if (waitFlag) {
2540 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2541 (struct smb_hdr *) pSMBr, &bytes_returned);
2542 } else {
2543 iov[0].iov_base = (char *)pSMB;
2544 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2545 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2546 &resp_buf_type, timeout, &rsp_iov);
2547 pSMBr = (struct smb_com_transaction2_sfi_rsp *)rsp_iov.iov_base;
2548 }
2549 cifs_small_buf_release(pSMB);
2550
2551 if (rc) {
2552 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2553 } else if (pLockData) {
2554 /* lock structure can be returned on get */
2555 __u16 data_offset;
2556 __u16 data_count;
2557 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2558
2559 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2560 rc = -EIO; /* bad smb */
2561 goto plk_err_exit;
2562 }
2563 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2564 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2565 if (data_count < sizeof(struct cifs_posix_lock)) {
2566 rc = -EIO;
2567 goto plk_err_exit;
2568 }
2569 parm_data = (struct cifs_posix_lock *)
2570 ((char *)&pSMBr->hdr.Protocol + data_offset);
2571 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2572 pLockData->fl_type = F_UNLCK;
2573 else {
2574 if (parm_data->lock_type ==
2575 cpu_to_le16(CIFS_RDLCK))
2576 pLockData->fl_type = F_RDLCK;
2577 else if (parm_data->lock_type ==
2578 cpu_to_le16(CIFS_WRLCK))
2579 pLockData->fl_type = F_WRLCK;
2580
2581 pLockData->fl_start = le64_to_cpu(parm_data->start);
2582 pLockData->fl_end = pLockData->fl_start +
2583 le64_to_cpu(parm_data->length) - 1;
2584 pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
2585 }
2586 }
2587
2588 plk_err_exit:
2589 free_rsp_buf(resp_buf_type, rsp_iov.iov_base);
2590
2591 /* Note: On -EAGAIN error only caller can retry on handle based calls
2592 since file handle passed in no longer valid */
2593
2594 return rc;
2595 }
2596
2597
2598 int
CIFSSMBClose(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2599 CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2600 {
2601 int rc = 0;
2602 CLOSE_REQ *pSMB = NULL;
2603 cifs_dbg(FYI, "In CIFSSMBClose\n");
2604
2605 /* do not retry on dead session on close */
2606 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2607 if (rc == -EAGAIN)
2608 return 0;
2609 if (rc)
2610 return rc;
2611
2612 pSMB->FileID = (__u16) smb_file_id;
2613 pSMB->LastWriteTime = 0xFFFFFFFF;
2614 pSMB->ByteCount = 0;
2615 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2616 cifs_small_buf_release(pSMB);
2617 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2618 if (rc) {
2619 if (rc != -EINTR) {
2620 /* EINTR is expected when user ctl-c to kill app */
2621 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2622 }
2623 }
2624
2625 /* Since session is dead, file will be closed on server already */
2626 if (rc == -EAGAIN)
2627 rc = 0;
2628
2629 return rc;
2630 }
2631
2632 int
CIFSSMBFlush(const unsigned int xid,struct cifs_tcon * tcon,int smb_file_id)2633 CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2634 {
2635 int rc = 0;
2636 FLUSH_REQ *pSMB = NULL;
2637 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2638
2639 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2640 if (rc)
2641 return rc;
2642
2643 pSMB->FileID = (__u16) smb_file_id;
2644 pSMB->ByteCount = 0;
2645 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2646 cifs_small_buf_release(pSMB);
2647 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2648 if (rc)
2649 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2650
2651 return rc;
2652 }
2653
2654 int
CIFSSMBRename(const unsigned int xid,struct cifs_tcon * tcon,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)2655 CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2656 const char *from_name, const char *to_name,
2657 struct cifs_sb_info *cifs_sb)
2658 {
2659 int rc = 0;
2660 RENAME_REQ *pSMB = NULL;
2661 RENAME_RSP *pSMBr = NULL;
2662 int bytes_returned;
2663 int name_len, name_len2;
2664 __u16 count;
2665 int remap = cifs_remap(cifs_sb);
2666
2667 cifs_dbg(FYI, "In CIFSSMBRename\n");
2668 renameRetry:
2669 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2670 (void **) &pSMBr);
2671 if (rc)
2672 return rc;
2673
2674 pSMB->BufferFormat = 0x04;
2675 pSMB->SearchAttributes =
2676 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2677 ATTR_DIRECTORY);
2678
2679 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2680 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2681 from_name, PATH_MAX,
2682 cifs_sb->local_nls, remap);
2683 name_len++; /* trailing null */
2684 name_len *= 2;
2685 pSMB->OldFileName[name_len] = 0x04; /* pad */
2686 /* protocol requires ASCII signature byte on Unicode string */
2687 pSMB->OldFileName[name_len + 1] = 0x00;
2688 name_len2 =
2689 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2690 to_name, PATH_MAX, cifs_sb->local_nls,
2691 remap);
2692 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2693 name_len2 *= 2; /* convert to bytes */
2694 } else { /* BB improve the check for buffer overruns BB */
2695 name_len = strnlen(from_name, PATH_MAX);
2696 name_len++; /* trailing null */
2697 strncpy(pSMB->OldFileName, from_name, name_len);
2698 name_len2 = strnlen(to_name, PATH_MAX);
2699 name_len2++; /* trailing null */
2700 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2701 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2702 name_len2++; /* trailing null */
2703 name_len2++; /* signature byte */
2704 }
2705
2706 count = 1 /* 1st signature byte */ + name_len + name_len2;
2707 inc_rfc1001_len(pSMB, count);
2708 pSMB->ByteCount = cpu_to_le16(count);
2709
2710 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2711 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2712 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2713 if (rc)
2714 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2715
2716 cifs_buf_release(pSMB);
2717
2718 if (rc == -EAGAIN)
2719 goto renameRetry;
2720
2721 return rc;
2722 }
2723
CIFSSMBRenameOpenFile(const unsigned int xid,struct cifs_tcon * pTcon,int netfid,const char * target_name,const struct nls_table * nls_codepage,int remap)2724 int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2725 int netfid, const char *target_name,
2726 const struct nls_table *nls_codepage, int remap)
2727 {
2728 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2729 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2730 struct set_file_rename *rename_info;
2731 char *data_offset;
2732 char dummy_string[30];
2733 int rc = 0;
2734 int bytes_returned = 0;
2735 int len_of_str;
2736 __u16 params, param_offset, offset, count, byte_count;
2737
2738 cifs_dbg(FYI, "Rename to File by handle\n");
2739 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2740 (void **) &pSMBr);
2741 if (rc)
2742 return rc;
2743
2744 params = 6;
2745 pSMB->MaxSetupCount = 0;
2746 pSMB->Reserved = 0;
2747 pSMB->Flags = 0;
2748 pSMB->Timeout = 0;
2749 pSMB->Reserved2 = 0;
2750 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2751 offset = param_offset + params;
2752
2753 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2754 rename_info = (struct set_file_rename *) data_offset;
2755 pSMB->MaxParameterCount = cpu_to_le16(2);
2756 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2757 pSMB->SetupCount = 1;
2758 pSMB->Reserved3 = 0;
2759 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2760 byte_count = 3 /* pad */ + params;
2761 pSMB->ParameterCount = cpu_to_le16(params);
2762 pSMB->TotalParameterCount = pSMB->ParameterCount;
2763 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2764 pSMB->DataOffset = cpu_to_le16(offset);
2765 /* construct random name ".cifs_tmp<inodenum><mid>" */
2766 rename_info->overwrite = cpu_to_le32(1);
2767 rename_info->root_fid = 0;
2768 /* unicode only call */
2769 if (target_name == NULL) {
2770 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2771 len_of_str =
2772 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2773 dummy_string, 24, nls_codepage, remap);
2774 } else {
2775 len_of_str =
2776 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2777 target_name, PATH_MAX, nls_codepage,
2778 remap);
2779 }
2780 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2781 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2782 byte_count += count;
2783 pSMB->DataCount = cpu_to_le16(count);
2784 pSMB->TotalDataCount = pSMB->DataCount;
2785 pSMB->Fid = netfid;
2786 pSMB->InformationLevel =
2787 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2788 pSMB->Reserved4 = 0;
2789 inc_rfc1001_len(pSMB, byte_count);
2790 pSMB->ByteCount = cpu_to_le16(byte_count);
2791 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2792 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2793 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2794 if (rc)
2795 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2796 rc);
2797
2798 cifs_buf_release(pSMB);
2799
2800 /* Note: On -EAGAIN error only caller can retry on handle based calls
2801 since file handle passed in no longer valid */
2802
2803 return rc;
2804 }
2805
2806 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)2807 CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2808 const char *fromName, const __u16 target_tid, const char *toName,
2809 const int flags, const struct nls_table *nls_codepage, int remap)
2810 {
2811 int rc = 0;
2812 COPY_REQ *pSMB = NULL;
2813 COPY_RSP *pSMBr = NULL;
2814 int bytes_returned;
2815 int name_len, name_len2;
2816 __u16 count;
2817
2818 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2819 copyRetry:
2820 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2821 (void **) &pSMBr);
2822 if (rc)
2823 return rc;
2824
2825 pSMB->BufferFormat = 0x04;
2826 pSMB->Tid2 = target_tid;
2827
2828 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2829
2830 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2831 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2832 fromName, PATH_MAX, nls_codepage,
2833 remap);
2834 name_len++; /* trailing null */
2835 name_len *= 2;
2836 pSMB->OldFileName[name_len] = 0x04; /* pad */
2837 /* protocol requires ASCII signature byte on Unicode string */
2838 pSMB->OldFileName[name_len + 1] = 0x00;
2839 name_len2 =
2840 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2841 toName, PATH_MAX, nls_codepage, remap);
2842 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2843 name_len2 *= 2; /* convert to bytes */
2844 } else { /* BB improve the check for buffer overruns BB */
2845 name_len = strnlen(fromName, PATH_MAX);
2846 name_len++; /* trailing null */
2847 strncpy(pSMB->OldFileName, fromName, name_len);
2848 name_len2 = strnlen(toName, PATH_MAX);
2849 name_len2++; /* trailing null */
2850 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2851 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2852 name_len2++; /* trailing null */
2853 name_len2++; /* signature byte */
2854 }
2855
2856 count = 1 /* 1st signature byte */ + name_len + name_len2;
2857 inc_rfc1001_len(pSMB, count);
2858 pSMB->ByteCount = cpu_to_le16(count);
2859
2860 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2861 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2862 if (rc) {
2863 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2864 rc, le16_to_cpu(pSMBr->CopyCount));
2865 }
2866 cifs_buf_release(pSMB);
2867
2868 if (rc == -EAGAIN)
2869 goto copyRetry;
2870
2871 return rc;
2872 }
2873
2874 int
CIFSUnixCreateSymLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2875 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2876 const char *fromName, const char *toName,
2877 const struct nls_table *nls_codepage, int remap)
2878 {
2879 TRANSACTION2_SPI_REQ *pSMB = NULL;
2880 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2881 char *data_offset;
2882 int name_len;
2883 int name_len_target;
2884 int rc = 0;
2885 int bytes_returned = 0;
2886 __u16 params, param_offset, offset, byte_count;
2887
2888 cifs_dbg(FYI, "In Symlink Unix style\n");
2889 createSymLinkRetry:
2890 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2891 (void **) &pSMBr);
2892 if (rc)
2893 return rc;
2894
2895 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2896 name_len =
2897 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2898 /* find define for this maxpathcomponent */
2899 PATH_MAX, nls_codepage, remap);
2900 name_len++; /* trailing null */
2901 name_len *= 2;
2902
2903 } else { /* BB improve the check for buffer overruns BB */
2904 name_len = strnlen(fromName, PATH_MAX);
2905 name_len++; /* trailing null */
2906 strncpy(pSMB->FileName, fromName, name_len);
2907 }
2908 params = 6 + name_len;
2909 pSMB->MaxSetupCount = 0;
2910 pSMB->Reserved = 0;
2911 pSMB->Flags = 0;
2912 pSMB->Timeout = 0;
2913 pSMB->Reserved2 = 0;
2914 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2915 InformationLevel) - 4;
2916 offset = param_offset + params;
2917
2918 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2919 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2920 name_len_target =
2921 cifsConvertToUTF16((__le16 *) data_offset, toName,
2922 /* find define for this maxpathcomponent */
2923 PATH_MAX, nls_codepage, remap);
2924 name_len_target++; /* trailing null */
2925 name_len_target *= 2;
2926 } else { /* BB improve the check for buffer overruns BB */
2927 name_len_target = strnlen(toName, PATH_MAX);
2928 name_len_target++; /* trailing null */
2929 strncpy(data_offset, toName, name_len_target);
2930 }
2931
2932 pSMB->MaxParameterCount = cpu_to_le16(2);
2933 /* BB find exact max on data count below from sess */
2934 pSMB->MaxDataCount = cpu_to_le16(1000);
2935 pSMB->SetupCount = 1;
2936 pSMB->Reserved3 = 0;
2937 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2938 byte_count = 3 /* pad */ + params + name_len_target;
2939 pSMB->DataCount = cpu_to_le16(name_len_target);
2940 pSMB->ParameterCount = cpu_to_le16(params);
2941 pSMB->TotalDataCount = pSMB->DataCount;
2942 pSMB->TotalParameterCount = pSMB->ParameterCount;
2943 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2944 pSMB->DataOffset = cpu_to_le16(offset);
2945 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2946 pSMB->Reserved4 = 0;
2947 inc_rfc1001_len(pSMB, byte_count);
2948 pSMB->ByteCount = cpu_to_le16(byte_count);
2949 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2950 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2951 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2952 if (rc)
2953 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2954 rc);
2955
2956 cifs_buf_release(pSMB);
2957
2958 if (rc == -EAGAIN)
2959 goto createSymLinkRetry;
2960
2961 return rc;
2962 }
2963
2964 int
CIFSUnixCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * fromName,const char * toName,const struct nls_table * nls_codepage,int remap)2965 CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2966 const char *fromName, const char *toName,
2967 const struct nls_table *nls_codepage, int remap)
2968 {
2969 TRANSACTION2_SPI_REQ *pSMB = NULL;
2970 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2971 char *data_offset;
2972 int name_len;
2973 int name_len_target;
2974 int rc = 0;
2975 int bytes_returned = 0;
2976 __u16 params, param_offset, offset, byte_count;
2977
2978 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2979 createHardLinkRetry:
2980 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2981 (void **) &pSMBr);
2982 if (rc)
2983 return rc;
2984
2985 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2986 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2987 PATH_MAX, nls_codepage, remap);
2988 name_len++; /* trailing null */
2989 name_len *= 2;
2990
2991 } else { /* BB improve the check for buffer overruns BB */
2992 name_len = strnlen(toName, PATH_MAX);
2993 name_len++; /* trailing null */
2994 strncpy(pSMB->FileName, toName, name_len);
2995 }
2996 params = 6 + name_len;
2997 pSMB->MaxSetupCount = 0;
2998 pSMB->Reserved = 0;
2999 pSMB->Flags = 0;
3000 pSMB->Timeout = 0;
3001 pSMB->Reserved2 = 0;
3002 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3003 InformationLevel) - 4;
3004 offset = param_offset + params;
3005
3006 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3007 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3008 name_len_target =
3009 cifsConvertToUTF16((__le16 *) data_offset, fromName,
3010 PATH_MAX, nls_codepage, remap);
3011 name_len_target++; /* trailing null */
3012 name_len_target *= 2;
3013 } else { /* BB improve the check for buffer overruns BB */
3014 name_len_target = strnlen(fromName, PATH_MAX);
3015 name_len_target++; /* trailing null */
3016 strncpy(data_offset, fromName, name_len_target);
3017 }
3018
3019 pSMB->MaxParameterCount = cpu_to_le16(2);
3020 /* BB find exact max on data count below from sess*/
3021 pSMB->MaxDataCount = cpu_to_le16(1000);
3022 pSMB->SetupCount = 1;
3023 pSMB->Reserved3 = 0;
3024 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3025 byte_count = 3 /* pad */ + params + name_len_target;
3026 pSMB->ParameterCount = cpu_to_le16(params);
3027 pSMB->TotalParameterCount = pSMB->ParameterCount;
3028 pSMB->DataCount = cpu_to_le16(name_len_target);
3029 pSMB->TotalDataCount = pSMB->DataCount;
3030 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3031 pSMB->DataOffset = cpu_to_le16(offset);
3032 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
3033 pSMB->Reserved4 = 0;
3034 inc_rfc1001_len(pSMB, byte_count);
3035 pSMB->ByteCount = cpu_to_le16(byte_count);
3036 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3037 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3038 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3039 if (rc)
3040 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
3041 rc);
3042
3043 cifs_buf_release(pSMB);
3044 if (rc == -EAGAIN)
3045 goto createHardLinkRetry;
3046
3047 return rc;
3048 }
3049
3050 int
CIFSCreateHardLink(const unsigned int xid,struct cifs_tcon * tcon,const char * from_name,const char * to_name,struct cifs_sb_info * cifs_sb)3051 CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
3052 const char *from_name, const char *to_name,
3053 struct cifs_sb_info *cifs_sb)
3054 {
3055 int rc = 0;
3056 NT_RENAME_REQ *pSMB = NULL;
3057 RENAME_RSP *pSMBr = NULL;
3058 int bytes_returned;
3059 int name_len, name_len2;
3060 __u16 count;
3061 int remap = cifs_remap(cifs_sb);
3062
3063 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
3064 winCreateHardLinkRetry:
3065
3066 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
3067 (void **) &pSMBr);
3068 if (rc)
3069 return rc;
3070
3071 pSMB->SearchAttributes =
3072 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3073 ATTR_DIRECTORY);
3074 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
3075 pSMB->ClusterCount = 0;
3076
3077 pSMB->BufferFormat = 0x04;
3078
3079 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3080 name_len =
3081 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3082 PATH_MAX, cifs_sb->local_nls, remap);
3083 name_len++; /* trailing null */
3084 name_len *= 2;
3085
3086 /* protocol specifies ASCII buffer format (0x04) for unicode */
3087 pSMB->OldFileName[name_len] = 0x04;
3088 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3089 name_len2 =
3090 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3091 to_name, PATH_MAX, cifs_sb->local_nls,
3092 remap);
3093 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3094 name_len2 *= 2; /* convert to bytes */
3095 } else { /* BB improve the check for buffer overruns BB */
3096 name_len = strnlen(from_name, PATH_MAX);
3097 name_len++; /* trailing null */
3098 strncpy(pSMB->OldFileName, from_name, name_len);
3099 name_len2 = strnlen(to_name, PATH_MAX);
3100 name_len2++; /* trailing null */
3101 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3102 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
3103 name_len2++; /* trailing null */
3104 name_len2++; /* signature byte */
3105 }
3106
3107 count = 1 /* string type byte */ + name_len + name_len2;
3108 inc_rfc1001_len(pSMB, count);
3109 pSMB->ByteCount = cpu_to_le16(count);
3110
3111 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3112 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3113 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3114 if (rc)
3115 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3116
3117 cifs_buf_release(pSMB);
3118 if (rc == -EAGAIN)
3119 goto winCreateHardLinkRetry;
3120
3121 return rc;
3122 }
3123
3124 int
CIFSSMBUnixQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,const unsigned char * searchName,char ** symlinkinfo,const struct nls_table * nls_codepage,int remap)3125 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3126 const unsigned char *searchName, char **symlinkinfo,
3127 const struct nls_table *nls_codepage, int remap)
3128 {
3129 /* SMB_QUERY_FILE_UNIX_LINK */
3130 TRANSACTION2_QPI_REQ *pSMB = NULL;
3131 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3132 int rc = 0;
3133 int bytes_returned;
3134 int name_len;
3135 __u16 params, byte_count;
3136 char *data_start;
3137
3138 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3139
3140 querySymLinkRetry:
3141 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3142 (void **) &pSMBr);
3143 if (rc)
3144 return rc;
3145
3146 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3147 name_len =
3148 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3149 searchName, PATH_MAX, nls_codepage,
3150 remap);
3151 name_len++; /* trailing null */
3152 name_len *= 2;
3153 } else { /* BB improve the check for buffer overruns BB */
3154 name_len = strnlen(searchName, PATH_MAX);
3155 name_len++; /* trailing null */
3156 strncpy(pSMB->FileName, searchName, name_len);
3157 }
3158
3159 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3160 pSMB->TotalDataCount = 0;
3161 pSMB->MaxParameterCount = cpu_to_le16(2);
3162 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3163 pSMB->MaxSetupCount = 0;
3164 pSMB->Reserved = 0;
3165 pSMB->Flags = 0;
3166 pSMB->Timeout = 0;
3167 pSMB->Reserved2 = 0;
3168 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3169 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3170 pSMB->DataCount = 0;
3171 pSMB->DataOffset = 0;
3172 pSMB->SetupCount = 1;
3173 pSMB->Reserved3 = 0;
3174 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3175 byte_count = params + 1 /* pad */ ;
3176 pSMB->TotalParameterCount = cpu_to_le16(params);
3177 pSMB->ParameterCount = pSMB->TotalParameterCount;
3178 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3179 pSMB->Reserved4 = 0;
3180 inc_rfc1001_len(pSMB, byte_count);
3181 pSMB->ByteCount = cpu_to_le16(byte_count);
3182
3183 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3184 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3185 if (rc) {
3186 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3187 } else {
3188 /* decode response */
3189
3190 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3191 /* BB also check enough total bytes returned */
3192 if (rc || get_bcc(&pSMBr->hdr) < 2)
3193 rc = -EIO;
3194 else {
3195 bool is_unicode;
3196 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3197
3198 data_start = ((char *) &pSMBr->hdr.Protocol) +
3199 le16_to_cpu(pSMBr->t2.DataOffset);
3200
3201 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3202 is_unicode = true;
3203 else
3204 is_unicode = false;
3205
3206 /* BB FIXME investigate remapping reserved chars here */
3207 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3208 count, is_unicode, nls_codepage);
3209 if (!*symlinkinfo)
3210 rc = -ENOMEM;
3211 }
3212 }
3213 cifs_buf_release(pSMB);
3214 if (rc == -EAGAIN)
3215 goto querySymLinkRetry;
3216 return rc;
3217 }
3218
3219 /*
3220 * Recent Windows versions now create symlinks more frequently
3221 * and they use the "reparse point" mechanism below. We can of course
3222 * do symlinks nicely to Samba and other servers which support the
3223 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3224 * "MF" symlinks optionally, but for recent Windows we really need to
3225 * reenable the code below and fix the cifs_symlink callers to handle this.
3226 * In the interim this code has been moved to its own config option so
3227 * it is not compiled in by default until callers fixed up and more tested.
3228 */
3229 int
CIFSSMBQuerySymLink(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,char ** symlinkinfo,const struct nls_table * nls_codepage)3230 CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3231 __u16 fid, char **symlinkinfo,
3232 const struct nls_table *nls_codepage)
3233 {
3234 int rc = 0;
3235 int bytes_returned;
3236 struct smb_com_transaction_ioctl_req *pSMB;
3237 struct smb_com_transaction_ioctl_rsp *pSMBr;
3238 bool is_unicode;
3239 unsigned int sub_len;
3240 char *sub_start;
3241 struct reparse_symlink_data *reparse_buf;
3242 struct reparse_posix_data *posix_buf;
3243 __u32 data_offset, data_count;
3244 char *end_of_smb;
3245
3246 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3247 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3248 (void **) &pSMBr);
3249 if (rc)
3250 return rc;
3251
3252 pSMB->TotalParameterCount = 0 ;
3253 pSMB->TotalDataCount = 0;
3254 pSMB->MaxParameterCount = cpu_to_le32(2);
3255 /* BB find exact data count max from sess structure BB */
3256 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3257 pSMB->MaxSetupCount = 4;
3258 pSMB->Reserved = 0;
3259 pSMB->ParameterOffset = 0;
3260 pSMB->DataCount = 0;
3261 pSMB->DataOffset = 0;
3262 pSMB->SetupCount = 4;
3263 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3264 pSMB->ParameterCount = pSMB->TotalParameterCount;
3265 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3266 pSMB->IsFsctl = 1; /* FSCTL */
3267 pSMB->IsRootFlag = 0;
3268 pSMB->Fid = fid; /* file handle always le */
3269 pSMB->ByteCount = 0;
3270
3271 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3272 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3273 if (rc) {
3274 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3275 goto qreparse_out;
3276 }
3277
3278 data_offset = le32_to_cpu(pSMBr->DataOffset);
3279 data_count = le32_to_cpu(pSMBr->DataCount);
3280 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3281 /* BB also check enough total bytes returned */
3282 rc = -EIO; /* bad smb */
3283 goto qreparse_out;
3284 }
3285 if (!data_count || (data_count > 2048)) {
3286 rc = -EIO;
3287 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3288 goto qreparse_out;
3289 }
3290 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3291 reparse_buf = (struct reparse_symlink_data *)
3292 ((char *)&pSMBr->hdr.Protocol + data_offset);
3293 if ((char *)reparse_buf >= end_of_smb) {
3294 rc = -EIO;
3295 goto qreparse_out;
3296 }
3297 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3298 cifs_dbg(FYI, "NFS style reparse tag\n");
3299 posix_buf = (struct reparse_posix_data *)reparse_buf;
3300
3301 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3302 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3303 le64_to_cpu(posix_buf->InodeType));
3304 rc = -EOPNOTSUPP;
3305 goto qreparse_out;
3306 }
3307 is_unicode = true;
3308 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3309 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3310 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3311 rc = -EIO;
3312 goto qreparse_out;
3313 }
3314 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3315 sub_len, is_unicode, nls_codepage);
3316 goto qreparse_out;
3317 } else if (reparse_buf->ReparseTag !=
3318 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3319 rc = -EOPNOTSUPP;
3320 goto qreparse_out;
3321 }
3322
3323 /* Reparse tag is NTFS symlink */
3324 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3325 reparse_buf->PathBuffer;
3326 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3327 if (sub_start + sub_len > end_of_smb) {
3328 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3329 rc = -EIO;
3330 goto qreparse_out;
3331 }
3332 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3333 is_unicode = true;
3334 else
3335 is_unicode = false;
3336
3337 /* BB FIXME investigate remapping reserved chars here */
3338 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3339 nls_codepage);
3340 if (!*symlinkinfo)
3341 rc = -ENOMEM;
3342 qreparse_out:
3343 cifs_buf_release(pSMB);
3344
3345 /*
3346 * Note: On -EAGAIN error only caller can retry on handle based calls
3347 * since file handle passed in no longer valid.
3348 */
3349 return rc;
3350 }
3351
3352 int
CIFSSMB_set_compression(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid)3353 CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3354 __u16 fid)
3355 {
3356 int rc = 0;
3357 int bytes_returned;
3358 struct smb_com_transaction_compr_ioctl_req *pSMB;
3359 struct smb_com_transaction_ioctl_rsp *pSMBr;
3360
3361 cifs_dbg(FYI, "Set compression for %u\n", fid);
3362 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3363 (void **) &pSMBr);
3364 if (rc)
3365 return rc;
3366
3367 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3368
3369 pSMB->TotalParameterCount = 0;
3370 pSMB->TotalDataCount = cpu_to_le32(2);
3371 pSMB->MaxParameterCount = 0;
3372 pSMB->MaxDataCount = 0;
3373 pSMB->MaxSetupCount = 4;
3374 pSMB->Reserved = 0;
3375 pSMB->ParameterOffset = 0;
3376 pSMB->DataCount = cpu_to_le32(2);
3377 pSMB->DataOffset =
3378 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3379 compression_state) - 4); /* 84 */
3380 pSMB->SetupCount = 4;
3381 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3382 pSMB->ParameterCount = 0;
3383 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3384 pSMB->IsFsctl = 1; /* FSCTL */
3385 pSMB->IsRootFlag = 0;
3386 pSMB->Fid = fid; /* file handle always le */
3387 /* 3 byte pad, followed by 2 byte compress state */
3388 pSMB->ByteCount = cpu_to_le16(5);
3389 inc_rfc1001_len(pSMB, 5);
3390
3391 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3392 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3393 if (rc)
3394 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3395
3396 cifs_buf_release(pSMB);
3397
3398 /*
3399 * Note: On -EAGAIN error only caller can retry on handle based calls
3400 * since file handle passed in no longer valid.
3401 */
3402 return rc;
3403 }
3404
3405
3406 #ifdef CONFIG_CIFS_POSIX
3407
3408 /*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)3409 static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3410 struct cifs_posix_ace *cifs_ace)
3411 {
3412 /* u8 cifs fields do not need le conversion */
3413 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3414 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3415 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3416 /*
3417 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3418 ace->e_perm, ace->e_tag, ace->e_id);
3419 */
3420
3421 return;
3422 }
3423
3424 /* 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)3425 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3426 const int acl_type, const int size_of_data_area)
3427 {
3428 int size = 0;
3429 int i;
3430 __u16 count;
3431 struct cifs_posix_ace *pACE;
3432 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3433 struct posix_acl_xattr_header *local_acl = (void *)trgt;
3434
3435 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3436 return -EOPNOTSUPP;
3437
3438 if (acl_type == ACL_TYPE_ACCESS) {
3439 count = le16_to_cpu(cifs_acl->access_entry_count);
3440 pACE = &cifs_acl->ace_array[0];
3441 size = sizeof(struct cifs_posix_acl);
3442 size += sizeof(struct cifs_posix_ace) * count;
3443 /* check if we would go beyond end of SMB */
3444 if (size_of_data_area < size) {
3445 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3446 size_of_data_area, size);
3447 return -EINVAL;
3448 }
3449 } else if (acl_type == ACL_TYPE_DEFAULT) {
3450 count = le16_to_cpu(cifs_acl->access_entry_count);
3451 size = sizeof(struct cifs_posix_acl);
3452 size += sizeof(struct cifs_posix_ace) * count;
3453 /* skip past access ACEs to get to default ACEs */
3454 pACE = &cifs_acl->ace_array[count];
3455 count = le16_to_cpu(cifs_acl->default_entry_count);
3456 size += sizeof(struct cifs_posix_ace) * count;
3457 /* check if we would go beyond end of SMB */
3458 if (size_of_data_area < size)
3459 return -EINVAL;
3460 } else {
3461 /* illegal type */
3462 return -EINVAL;
3463 }
3464
3465 size = posix_acl_xattr_size(count);
3466 if ((buflen == 0) || (local_acl == NULL)) {
3467 /* used to query ACL EA size */
3468 } else if (size > buflen) {
3469 return -ERANGE;
3470 } else /* buffer big enough */ {
3471 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3472
3473 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3474 for (i = 0; i < count ; i++) {
3475 cifs_convert_ace(&ace[i], pACE);
3476 pACE++;
3477 }
3478 }
3479 return size;
3480 }
3481
convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,const struct posix_acl_xattr_entry * local_ace)3482 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3483 const struct posix_acl_xattr_entry *local_ace)
3484 {
3485 __u16 rc = 0; /* 0 = ACL converted ok */
3486
3487 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3488 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3489 /* BB is there a better way to handle the large uid? */
3490 if (local_ace->e_id == cpu_to_le32(-1)) {
3491 /* Probably no need to le convert -1 on any arch but can not hurt */
3492 cifs_ace->cifs_uid = cpu_to_le64(-1);
3493 } else
3494 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3495 /*
3496 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3497 ace->e_perm, ace->e_tag, ace->e_id);
3498 */
3499 return rc;
3500 }
3501
3502 /* 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)3503 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3504 const int buflen, const int acl_type)
3505 {
3506 __u16 rc = 0;
3507 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3508 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3509 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3510 int count;
3511 int i;
3512
3513 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3514 return 0;
3515
3516 count = posix_acl_xattr_count((size_t)buflen);
3517 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3518 count, buflen, le32_to_cpu(local_acl->a_version));
3519 if (le32_to_cpu(local_acl->a_version) != 2) {
3520 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3521 le32_to_cpu(local_acl->a_version));
3522 return 0;
3523 }
3524 cifs_acl->version = cpu_to_le16(1);
3525 if (acl_type == ACL_TYPE_ACCESS) {
3526 cifs_acl->access_entry_count = cpu_to_le16(count);
3527 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3528 } else if (acl_type == ACL_TYPE_DEFAULT) {
3529 cifs_acl->default_entry_count = cpu_to_le16(count);
3530 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3531 } else {
3532 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3533 return 0;
3534 }
3535 for (i = 0; i < count; i++) {
3536 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3537 if (rc != 0) {
3538 /* ACE not converted */
3539 break;
3540 }
3541 }
3542 if (rc == 0) {
3543 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3544 rc += sizeof(struct cifs_posix_acl);
3545 /* BB add check to make sure ACL does not overflow SMB */
3546 }
3547 return rc;
3548 }
3549
3550 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)3551 CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3552 const unsigned char *searchName,
3553 char *acl_inf, const int buflen, const int acl_type,
3554 const struct nls_table *nls_codepage, int remap)
3555 {
3556 /* SMB_QUERY_POSIX_ACL */
3557 TRANSACTION2_QPI_REQ *pSMB = NULL;
3558 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3559 int rc = 0;
3560 int bytes_returned;
3561 int name_len;
3562 __u16 params, byte_count;
3563
3564 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3565
3566 queryAclRetry:
3567 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3568 (void **) &pSMBr);
3569 if (rc)
3570 return rc;
3571
3572 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3573 name_len =
3574 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3575 searchName, PATH_MAX, nls_codepage,
3576 remap);
3577 name_len++; /* trailing null */
3578 name_len *= 2;
3579 pSMB->FileName[name_len] = 0;
3580 pSMB->FileName[name_len+1] = 0;
3581 } else { /* BB improve the check for buffer overruns BB */
3582 name_len = strnlen(searchName, PATH_MAX);
3583 name_len++; /* trailing null */
3584 strncpy(pSMB->FileName, searchName, name_len);
3585 }
3586
3587 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3588 pSMB->TotalDataCount = 0;
3589 pSMB->MaxParameterCount = cpu_to_le16(2);
3590 /* BB find exact max data count below from sess structure BB */
3591 pSMB->MaxDataCount = cpu_to_le16(4000);
3592 pSMB->MaxSetupCount = 0;
3593 pSMB->Reserved = 0;
3594 pSMB->Flags = 0;
3595 pSMB->Timeout = 0;
3596 pSMB->Reserved2 = 0;
3597 pSMB->ParameterOffset = cpu_to_le16(
3598 offsetof(struct smb_com_transaction2_qpi_req,
3599 InformationLevel) - 4);
3600 pSMB->DataCount = 0;
3601 pSMB->DataOffset = 0;
3602 pSMB->SetupCount = 1;
3603 pSMB->Reserved3 = 0;
3604 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3605 byte_count = params + 1 /* pad */ ;
3606 pSMB->TotalParameterCount = cpu_to_le16(params);
3607 pSMB->ParameterCount = pSMB->TotalParameterCount;
3608 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3609 pSMB->Reserved4 = 0;
3610 inc_rfc1001_len(pSMB, byte_count);
3611 pSMB->ByteCount = cpu_to_le16(byte_count);
3612
3613 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3614 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3615 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3616 if (rc) {
3617 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3618 } else {
3619 /* decode response */
3620
3621 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3622 /* BB also check enough total bytes returned */
3623 if (rc || get_bcc(&pSMBr->hdr) < 2)
3624 rc = -EIO; /* bad smb */
3625 else {
3626 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3627 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3628 rc = cifs_copy_posix_acl(acl_inf,
3629 (char *)&pSMBr->hdr.Protocol+data_offset,
3630 buflen, acl_type, count);
3631 }
3632 }
3633 cifs_buf_release(pSMB);
3634 if (rc == -EAGAIN)
3635 goto queryAclRetry;
3636 return rc;
3637 }
3638
3639 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)3640 CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3641 const unsigned char *fileName,
3642 const char *local_acl, const int buflen,
3643 const int acl_type,
3644 const struct nls_table *nls_codepage, int remap)
3645 {
3646 struct smb_com_transaction2_spi_req *pSMB = NULL;
3647 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3648 char *parm_data;
3649 int name_len;
3650 int rc = 0;
3651 int bytes_returned = 0;
3652 __u16 params, byte_count, data_count, param_offset, offset;
3653
3654 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3655 setAclRetry:
3656 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3657 (void **) &pSMBr);
3658 if (rc)
3659 return rc;
3660 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3661 name_len =
3662 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3663 PATH_MAX, nls_codepage, remap);
3664 name_len++; /* trailing null */
3665 name_len *= 2;
3666 } else { /* BB improve the check for buffer overruns BB */
3667 name_len = strnlen(fileName, PATH_MAX);
3668 name_len++; /* trailing null */
3669 strncpy(pSMB->FileName, fileName, name_len);
3670 }
3671 params = 6 + name_len;
3672 pSMB->MaxParameterCount = cpu_to_le16(2);
3673 /* BB find max SMB size from sess */
3674 pSMB->MaxDataCount = cpu_to_le16(1000);
3675 pSMB->MaxSetupCount = 0;
3676 pSMB->Reserved = 0;
3677 pSMB->Flags = 0;
3678 pSMB->Timeout = 0;
3679 pSMB->Reserved2 = 0;
3680 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3681 InformationLevel) - 4;
3682 offset = param_offset + params;
3683 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3684 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3685
3686 /* convert to on the wire format for POSIX ACL */
3687 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3688
3689 if (data_count == 0) {
3690 rc = -EOPNOTSUPP;
3691 goto setACLerrorExit;
3692 }
3693 pSMB->DataOffset = cpu_to_le16(offset);
3694 pSMB->SetupCount = 1;
3695 pSMB->Reserved3 = 0;
3696 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3697 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3698 byte_count = 3 /* pad */ + params + data_count;
3699 pSMB->DataCount = cpu_to_le16(data_count);
3700 pSMB->TotalDataCount = pSMB->DataCount;
3701 pSMB->ParameterCount = cpu_to_le16(params);
3702 pSMB->TotalParameterCount = pSMB->ParameterCount;
3703 pSMB->Reserved4 = 0;
3704 inc_rfc1001_len(pSMB, byte_count);
3705 pSMB->ByteCount = cpu_to_le16(byte_count);
3706 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3707 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3708 if (rc)
3709 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3710
3711 setACLerrorExit:
3712 cifs_buf_release(pSMB);
3713 if (rc == -EAGAIN)
3714 goto setAclRetry;
3715 return rc;
3716 }
3717
3718 /* BB fix tabs in this function FIXME BB */
3719 int
CIFSGetExtAttr(const unsigned int xid,struct cifs_tcon * tcon,const int netfid,__u64 * pExtAttrBits,__u64 * pMask)3720 CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3721 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3722 {
3723 int rc = 0;
3724 struct smb_t2_qfi_req *pSMB = NULL;
3725 struct smb_t2_qfi_rsp *pSMBr = NULL;
3726 int bytes_returned;
3727 __u16 params, byte_count;
3728
3729 cifs_dbg(FYI, "In GetExtAttr\n");
3730 if (tcon == NULL)
3731 return -ENODEV;
3732
3733 GetExtAttrRetry:
3734 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3735 (void **) &pSMBr);
3736 if (rc)
3737 return rc;
3738
3739 params = 2 /* level */ + 2 /* fid */;
3740 pSMB->t2.TotalDataCount = 0;
3741 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3742 /* BB find exact max data count below from sess structure BB */
3743 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3744 pSMB->t2.MaxSetupCount = 0;
3745 pSMB->t2.Reserved = 0;
3746 pSMB->t2.Flags = 0;
3747 pSMB->t2.Timeout = 0;
3748 pSMB->t2.Reserved2 = 0;
3749 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3750 Fid) - 4);
3751 pSMB->t2.DataCount = 0;
3752 pSMB->t2.DataOffset = 0;
3753 pSMB->t2.SetupCount = 1;
3754 pSMB->t2.Reserved3 = 0;
3755 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3756 byte_count = params + 1 /* pad */ ;
3757 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3758 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3759 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3760 pSMB->Pad = 0;
3761 pSMB->Fid = netfid;
3762 inc_rfc1001_len(pSMB, byte_count);
3763 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3764
3765 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3766 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3767 if (rc) {
3768 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3769 } else {
3770 /* decode response */
3771 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3772 /* BB also check enough total bytes returned */
3773 if (rc || get_bcc(&pSMBr->hdr) < 2)
3774 /* If rc should we check for EOPNOSUPP and
3775 disable the srvino flag? or in caller? */
3776 rc = -EIO; /* bad smb */
3777 else {
3778 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3779 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3780 struct file_chattr_info *pfinfo;
3781 /* BB Do we need a cast or hash here ? */
3782 if (count != 16) {
3783 cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3784 rc = -EIO;
3785 goto GetExtAttrOut;
3786 }
3787 pfinfo = (struct file_chattr_info *)
3788 (data_offset + (char *) &pSMBr->hdr.Protocol);
3789 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3790 *pMask = le64_to_cpu(pfinfo->mask);
3791 }
3792 }
3793 GetExtAttrOut:
3794 cifs_buf_release(pSMB);
3795 if (rc == -EAGAIN)
3796 goto GetExtAttrRetry;
3797 return rc;
3798 }
3799
3800 #endif /* CONFIG_POSIX */
3801
3802 #ifdef CONFIG_CIFS_ACL
3803 /*
3804 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3805 * all NT TRANSACTS that we init here have total parm and data under about 400
3806 * bytes (to fit in small cifs buffer size), which is the case so far, it
3807 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3808 * returned setup area) and MaxParameterCount (returned parms size) must be set
3809 * by caller
3810 */
3811 static int
smb_init_nttransact(const __u16 sub_command,const int setup_count,const int parm_len,struct cifs_tcon * tcon,void ** ret_buf)3812 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3813 const int parm_len, struct cifs_tcon *tcon,
3814 void **ret_buf)
3815 {
3816 int rc;
3817 __u32 temp_offset;
3818 struct smb_com_ntransact_req *pSMB;
3819
3820 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3821 (void **)&pSMB);
3822 if (rc)
3823 return rc;
3824 *ret_buf = (void *)pSMB;
3825 pSMB->Reserved = 0;
3826 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3827 pSMB->TotalDataCount = 0;
3828 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3829 pSMB->ParameterCount = pSMB->TotalParameterCount;
3830 pSMB->DataCount = pSMB->TotalDataCount;
3831 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3832 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3833 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3834 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3835 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3836 pSMB->SubCommand = cpu_to_le16(sub_command);
3837 return 0;
3838 }
3839
3840 static int
validate_ntransact(char * buf,char ** ppparm,char ** ppdata,__u32 * pparmlen,__u32 * pdatalen)3841 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3842 __u32 *pparmlen, __u32 *pdatalen)
3843 {
3844 char *end_of_smb;
3845 __u32 data_count, data_offset, parm_count, parm_offset;
3846 struct smb_com_ntransact_rsp *pSMBr;
3847 u16 bcc;
3848
3849 *pdatalen = 0;
3850 *pparmlen = 0;
3851
3852 if (buf == NULL)
3853 return -EINVAL;
3854
3855 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3856
3857 bcc = get_bcc(&pSMBr->hdr);
3858 end_of_smb = 2 /* sizeof byte count */ + bcc +
3859 (char *)&pSMBr->ByteCount;
3860
3861 data_offset = le32_to_cpu(pSMBr->DataOffset);
3862 data_count = le32_to_cpu(pSMBr->DataCount);
3863 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3864 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3865
3866 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3867 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3868
3869 /* should we also check that parm and data areas do not overlap? */
3870 if (*ppparm > end_of_smb) {
3871 cifs_dbg(FYI, "parms start after end of smb\n");
3872 return -EINVAL;
3873 } else if (parm_count + *ppparm > end_of_smb) {
3874 cifs_dbg(FYI, "parm end after end of smb\n");
3875 return -EINVAL;
3876 } else if (*ppdata > end_of_smb) {
3877 cifs_dbg(FYI, "data starts after end of smb\n");
3878 return -EINVAL;
3879 } else if (data_count + *ppdata > end_of_smb) {
3880 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3881 *ppdata, data_count, (data_count + *ppdata),
3882 end_of_smb, pSMBr);
3883 return -EINVAL;
3884 } else if (parm_count + data_count > bcc) {
3885 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3886 return -EINVAL;
3887 }
3888 *pdatalen = data_count;
3889 *pparmlen = parm_count;
3890 return 0;
3891 }
3892
3893 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3894 int
CIFSSMBGetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd ** acl_inf,__u32 * pbuflen)3895 CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3896 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3897 {
3898 int rc = 0;
3899 int buf_type = 0;
3900 QUERY_SEC_DESC_REQ *pSMB;
3901 struct kvec iov[1];
3902 struct kvec rsp_iov;
3903
3904 cifs_dbg(FYI, "GetCifsACL\n");
3905
3906 *pbuflen = 0;
3907 *acl_inf = NULL;
3908
3909 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3910 8 /* parm len */, tcon, (void **) &pSMB);
3911 if (rc)
3912 return rc;
3913
3914 pSMB->MaxParameterCount = cpu_to_le32(4);
3915 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3916 pSMB->MaxSetupCount = 0;
3917 pSMB->Fid = fid; /* file handle always le */
3918 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3919 CIFS_ACL_DACL);
3920 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3921 inc_rfc1001_len(pSMB, 11);
3922 iov[0].iov_base = (char *)pSMB;
3923 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3924
3925 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3926 0, &rsp_iov);
3927 cifs_small_buf_release(pSMB);
3928 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3929 if (rc) {
3930 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3931 } else { /* decode response */
3932 __le32 *parm;
3933 __u32 parm_len;
3934 __u32 acl_len;
3935 struct smb_com_ntransact_rsp *pSMBr;
3936 char *pdata;
3937
3938 /* validate_nttransact */
3939 rc = validate_ntransact(rsp_iov.iov_base, (char **)&parm,
3940 &pdata, &parm_len, pbuflen);
3941 if (rc)
3942 goto qsec_out;
3943 pSMBr = (struct smb_com_ntransact_rsp *)rsp_iov.iov_base;
3944
3945 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3946 pSMBr, parm, *acl_inf);
3947
3948 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3949 rc = -EIO; /* bad smb */
3950 *pbuflen = 0;
3951 goto qsec_out;
3952 }
3953
3954 /* BB check that data area is minimum length and as big as acl_len */
3955
3956 acl_len = le32_to_cpu(*parm);
3957 if (acl_len != *pbuflen) {
3958 cifs_dbg(VFS, "acl length %d does not match %d\n",
3959 acl_len, *pbuflen);
3960 if (*pbuflen > acl_len)
3961 *pbuflen = acl_len;
3962 }
3963
3964 /* check if buffer is big enough for the acl
3965 header followed by the smallest SID */
3966 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3967 (*pbuflen >= 64 * 1024)) {
3968 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3969 rc = -EINVAL;
3970 *pbuflen = 0;
3971 } else {
3972 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3973 if (*acl_inf == NULL) {
3974 *pbuflen = 0;
3975 rc = -ENOMEM;
3976 }
3977 }
3978 }
3979 qsec_out:
3980 free_rsp_buf(buf_type, rsp_iov.iov_base);
3981 return rc;
3982 }
3983
3984 int
CIFSSMBSetCIFSACL(const unsigned int xid,struct cifs_tcon * tcon,__u16 fid,struct cifs_ntsd * pntsd,__u32 acllen,int aclflag)3985 CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3986 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3987 {
3988 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3989 int rc = 0;
3990 int bytes_returned = 0;
3991 SET_SEC_DESC_REQ *pSMB = NULL;
3992 void *pSMBr;
3993
3994 setCifsAclRetry:
3995 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3996 if (rc)
3997 return rc;
3998
3999 pSMB->MaxSetupCount = 0;
4000 pSMB->Reserved = 0;
4001
4002 param_count = 8;
4003 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
4004 data_count = acllen;
4005 data_offset = param_offset + param_count;
4006 byte_count = 3 /* pad */ + param_count;
4007
4008 pSMB->DataCount = cpu_to_le32(data_count);
4009 pSMB->TotalDataCount = pSMB->DataCount;
4010 pSMB->MaxParameterCount = cpu_to_le32(4);
4011 pSMB->MaxDataCount = cpu_to_le32(16384);
4012 pSMB->ParameterCount = cpu_to_le32(param_count);
4013 pSMB->ParameterOffset = cpu_to_le32(param_offset);
4014 pSMB->TotalParameterCount = pSMB->ParameterCount;
4015 pSMB->DataOffset = cpu_to_le32(data_offset);
4016 pSMB->SetupCount = 0;
4017 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
4018 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
4019
4020 pSMB->Fid = fid; /* file handle always le */
4021 pSMB->Reserved2 = 0;
4022 pSMB->AclFlags = cpu_to_le32(aclflag);
4023
4024 if (pntsd && acllen) {
4025 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
4026 data_offset, pntsd, acllen);
4027 inc_rfc1001_len(pSMB, byte_count + data_count);
4028 } else
4029 inc_rfc1001_len(pSMB, byte_count);
4030
4031 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4032 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4033
4034 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
4035 bytes_returned, rc);
4036 if (rc)
4037 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
4038 cifs_buf_release(pSMB);
4039
4040 if (rc == -EAGAIN)
4041 goto setCifsAclRetry;
4042
4043 return (rc);
4044 }
4045
4046 #endif /* CONFIG_CIFS_ACL */
4047
4048 /* Legacy Query Path Information call for lookup to old servers such
4049 as Win9x/WinME */
4050 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)4051 SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
4052 const char *search_name, FILE_ALL_INFO *data,
4053 const struct nls_table *nls_codepage, int remap)
4054 {
4055 QUERY_INFORMATION_REQ *pSMB;
4056 QUERY_INFORMATION_RSP *pSMBr;
4057 int rc = 0;
4058 int bytes_returned;
4059 int name_len;
4060
4061 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
4062 QInfRetry:
4063 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
4064 (void **) &pSMBr);
4065 if (rc)
4066 return rc;
4067
4068 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4069 name_len =
4070 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4071 search_name, PATH_MAX, nls_codepage,
4072 remap);
4073 name_len++; /* trailing null */
4074 name_len *= 2;
4075 } else {
4076 name_len = strnlen(search_name, PATH_MAX);
4077 name_len++; /* trailing null */
4078 strncpy(pSMB->FileName, search_name, name_len);
4079 }
4080 pSMB->BufferFormat = 0x04;
4081 name_len++; /* account for buffer type byte */
4082 inc_rfc1001_len(pSMB, (__u16)name_len);
4083 pSMB->ByteCount = cpu_to_le16(name_len);
4084
4085 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4086 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4087 if (rc) {
4088 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4089 } else if (data) {
4090 struct timespec64 ts;
4091 __u32 time = le32_to_cpu(pSMBr->last_write_time);
4092
4093 /* decode response */
4094 /* BB FIXME - add time zone adjustment BB */
4095 memset(data, 0, sizeof(FILE_ALL_INFO));
4096 ts.tv_nsec = 0;
4097 ts.tv_sec = time;
4098 /* decode time fields */
4099 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4100 data->LastWriteTime = data->ChangeTime;
4101 data->LastAccessTime = 0;
4102 data->AllocationSize =
4103 cpu_to_le64(le32_to_cpu(pSMBr->size));
4104 data->EndOfFile = data->AllocationSize;
4105 data->Attributes =
4106 cpu_to_le32(le16_to_cpu(pSMBr->attr));
4107 } else
4108 rc = -EIO; /* bad buffer passed in */
4109
4110 cifs_buf_release(pSMB);
4111
4112 if (rc == -EAGAIN)
4113 goto QInfRetry;
4114
4115 return rc;
4116 }
4117
4118 int
CIFSSMBQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_ALL_INFO * pFindData)4119 CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4120 u16 netfid, FILE_ALL_INFO *pFindData)
4121 {
4122 struct smb_t2_qfi_req *pSMB = NULL;
4123 struct smb_t2_qfi_rsp *pSMBr = NULL;
4124 int rc = 0;
4125 int bytes_returned;
4126 __u16 params, byte_count;
4127
4128 QFileInfoRetry:
4129 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4130 (void **) &pSMBr);
4131 if (rc)
4132 return rc;
4133
4134 params = 2 /* level */ + 2 /* fid */;
4135 pSMB->t2.TotalDataCount = 0;
4136 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4137 /* BB find exact max data count below from sess structure BB */
4138 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4139 pSMB->t2.MaxSetupCount = 0;
4140 pSMB->t2.Reserved = 0;
4141 pSMB->t2.Flags = 0;
4142 pSMB->t2.Timeout = 0;
4143 pSMB->t2.Reserved2 = 0;
4144 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4145 Fid) - 4);
4146 pSMB->t2.DataCount = 0;
4147 pSMB->t2.DataOffset = 0;
4148 pSMB->t2.SetupCount = 1;
4149 pSMB->t2.Reserved3 = 0;
4150 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4151 byte_count = params + 1 /* pad */ ;
4152 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4153 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4154 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4155 pSMB->Pad = 0;
4156 pSMB->Fid = netfid;
4157 inc_rfc1001_len(pSMB, byte_count);
4158 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4159
4160 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4161 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4162 if (rc) {
4163 cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4164 } else { /* decode response */
4165 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4166
4167 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4168 rc = -EIO;
4169 else if (get_bcc(&pSMBr->hdr) < 40)
4170 rc = -EIO; /* bad smb */
4171 else if (pFindData) {
4172 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4173 memcpy((char *) pFindData,
4174 (char *) &pSMBr->hdr.Protocol +
4175 data_offset, sizeof(FILE_ALL_INFO));
4176 } else
4177 rc = -ENOMEM;
4178 }
4179 cifs_buf_release(pSMB);
4180 if (rc == -EAGAIN)
4181 goto QFileInfoRetry;
4182
4183 return rc;
4184 }
4185
4186 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)4187 CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4188 const char *search_name, FILE_ALL_INFO *data,
4189 int legacy /* old style infolevel */,
4190 const struct nls_table *nls_codepage, int remap)
4191 {
4192 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4193 TRANSACTION2_QPI_REQ *pSMB = NULL;
4194 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4195 int rc = 0;
4196 int bytes_returned;
4197 int name_len;
4198 __u16 params, byte_count;
4199
4200 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4201 QPathInfoRetry:
4202 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4203 (void **) &pSMBr);
4204 if (rc)
4205 return rc;
4206
4207 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4208 name_len =
4209 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4210 PATH_MAX, nls_codepage, remap);
4211 name_len++; /* trailing null */
4212 name_len *= 2;
4213 } else { /* BB improve the check for buffer overruns BB */
4214 name_len = strnlen(search_name, PATH_MAX);
4215 name_len++; /* trailing null */
4216 strncpy(pSMB->FileName, search_name, name_len);
4217 }
4218
4219 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4220 pSMB->TotalDataCount = 0;
4221 pSMB->MaxParameterCount = cpu_to_le16(2);
4222 /* BB find exact max SMB PDU from sess structure BB */
4223 pSMB->MaxDataCount = cpu_to_le16(4000);
4224 pSMB->MaxSetupCount = 0;
4225 pSMB->Reserved = 0;
4226 pSMB->Flags = 0;
4227 pSMB->Timeout = 0;
4228 pSMB->Reserved2 = 0;
4229 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4230 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4231 pSMB->DataCount = 0;
4232 pSMB->DataOffset = 0;
4233 pSMB->SetupCount = 1;
4234 pSMB->Reserved3 = 0;
4235 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4236 byte_count = params + 1 /* pad */ ;
4237 pSMB->TotalParameterCount = cpu_to_le16(params);
4238 pSMB->ParameterCount = pSMB->TotalParameterCount;
4239 if (legacy)
4240 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4241 else
4242 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4243 pSMB->Reserved4 = 0;
4244 inc_rfc1001_len(pSMB, byte_count);
4245 pSMB->ByteCount = cpu_to_le16(byte_count);
4246
4247 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4248 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4249 if (rc) {
4250 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4251 } else { /* decode response */
4252 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4253
4254 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4255 rc = -EIO;
4256 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4257 rc = -EIO; /* bad smb */
4258 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4259 rc = -EIO; /* 24 or 26 expected but we do not read
4260 last field */
4261 else if (data) {
4262 int size;
4263 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4264
4265 /*
4266 * On legacy responses we do not read the last field,
4267 * EAsize, fortunately since it varies by subdialect and
4268 * also note it differs on Set vs Get, ie two bytes or 4
4269 * bytes depending but we don't care here.
4270 */
4271 if (legacy)
4272 size = sizeof(FILE_INFO_STANDARD);
4273 else
4274 size = sizeof(FILE_ALL_INFO);
4275 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4276 data_offset, size);
4277 } else
4278 rc = -ENOMEM;
4279 }
4280 cifs_buf_release(pSMB);
4281 if (rc == -EAGAIN)
4282 goto QPathInfoRetry;
4283
4284 return rc;
4285 }
4286
4287 int
CIFSSMBUnixQFileInfo(const unsigned int xid,struct cifs_tcon * tcon,u16 netfid,FILE_UNIX_BASIC_INFO * pFindData)4288 CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4289 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4290 {
4291 struct smb_t2_qfi_req *pSMB = NULL;
4292 struct smb_t2_qfi_rsp *pSMBr = NULL;
4293 int rc = 0;
4294 int bytes_returned;
4295 __u16 params, byte_count;
4296
4297 UnixQFileInfoRetry:
4298 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4299 (void **) &pSMBr);
4300 if (rc)
4301 return rc;
4302
4303 params = 2 /* level */ + 2 /* fid */;
4304 pSMB->t2.TotalDataCount = 0;
4305 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4306 /* BB find exact max data count below from sess structure BB */
4307 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4308 pSMB->t2.MaxSetupCount = 0;
4309 pSMB->t2.Reserved = 0;
4310 pSMB->t2.Flags = 0;
4311 pSMB->t2.Timeout = 0;
4312 pSMB->t2.Reserved2 = 0;
4313 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4314 Fid) - 4);
4315 pSMB->t2.DataCount = 0;
4316 pSMB->t2.DataOffset = 0;
4317 pSMB->t2.SetupCount = 1;
4318 pSMB->t2.Reserved3 = 0;
4319 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4320 byte_count = params + 1 /* pad */ ;
4321 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4322 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4323 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4324 pSMB->Pad = 0;
4325 pSMB->Fid = netfid;
4326 inc_rfc1001_len(pSMB, byte_count);
4327 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4328
4329 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4330 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4331 if (rc) {
4332 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4333 } else { /* decode response */
4334 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4335
4336 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4337 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4338 rc = -EIO; /* bad smb */
4339 } else {
4340 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4341 memcpy((char *) pFindData,
4342 (char *) &pSMBr->hdr.Protocol +
4343 data_offset,
4344 sizeof(FILE_UNIX_BASIC_INFO));
4345 }
4346 }
4347
4348 cifs_buf_release(pSMB);
4349 if (rc == -EAGAIN)
4350 goto UnixQFileInfoRetry;
4351
4352 return rc;
4353 }
4354
4355 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)4356 CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4357 const unsigned char *searchName,
4358 FILE_UNIX_BASIC_INFO *pFindData,
4359 const struct nls_table *nls_codepage, int remap)
4360 {
4361 /* SMB_QUERY_FILE_UNIX_BASIC */
4362 TRANSACTION2_QPI_REQ *pSMB = NULL;
4363 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4364 int rc = 0;
4365 int bytes_returned = 0;
4366 int name_len;
4367 __u16 params, byte_count;
4368
4369 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4370 UnixQPathInfoRetry:
4371 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4372 (void **) &pSMBr);
4373 if (rc)
4374 return rc;
4375
4376 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4377 name_len =
4378 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4379 PATH_MAX, nls_codepage, remap);
4380 name_len++; /* trailing null */
4381 name_len *= 2;
4382 } else { /* BB improve the check for buffer overruns BB */
4383 name_len = strnlen(searchName, PATH_MAX);
4384 name_len++; /* trailing null */
4385 strncpy(pSMB->FileName, searchName, name_len);
4386 }
4387
4388 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4389 pSMB->TotalDataCount = 0;
4390 pSMB->MaxParameterCount = cpu_to_le16(2);
4391 /* BB find exact max SMB PDU from sess structure BB */
4392 pSMB->MaxDataCount = cpu_to_le16(4000);
4393 pSMB->MaxSetupCount = 0;
4394 pSMB->Reserved = 0;
4395 pSMB->Flags = 0;
4396 pSMB->Timeout = 0;
4397 pSMB->Reserved2 = 0;
4398 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4399 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4400 pSMB->DataCount = 0;
4401 pSMB->DataOffset = 0;
4402 pSMB->SetupCount = 1;
4403 pSMB->Reserved3 = 0;
4404 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4405 byte_count = params + 1 /* pad */ ;
4406 pSMB->TotalParameterCount = cpu_to_le16(params);
4407 pSMB->ParameterCount = pSMB->TotalParameterCount;
4408 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4409 pSMB->Reserved4 = 0;
4410 inc_rfc1001_len(pSMB, byte_count);
4411 pSMB->ByteCount = cpu_to_le16(byte_count);
4412
4413 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4414 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4415 if (rc) {
4416 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4417 } else { /* decode response */
4418 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4419
4420 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4421 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4422 rc = -EIO; /* bad smb */
4423 } else {
4424 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4425 memcpy((char *) pFindData,
4426 (char *) &pSMBr->hdr.Protocol +
4427 data_offset,
4428 sizeof(FILE_UNIX_BASIC_INFO));
4429 }
4430 }
4431 cifs_buf_release(pSMB);
4432 if (rc == -EAGAIN)
4433 goto UnixQPathInfoRetry;
4434
4435 return rc;
4436 }
4437
4438 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4439 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)4440 CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4441 const char *searchName, struct cifs_sb_info *cifs_sb,
4442 __u16 *pnetfid, __u16 search_flags,
4443 struct cifs_search_info *psrch_inf, bool msearch)
4444 {
4445 /* level 257 SMB_ */
4446 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4447 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4448 T2_FFIRST_RSP_PARMS *parms;
4449 int rc = 0;
4450 int bytes_returned = 0;
4451 int name_len, remap;
4452 __u16 params, byte_count;
4453 struct nls_table *nls_codepage;
4454
4455 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4456
4457 findFirstRetry:
4458 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4459 (void **) &pSMBr);
4460 if (rc)
4461 return rc;
4462
4463 nls_codepage = cifs_sb->local_nls;
4464 remap = cifs_remap(cifs_sb);
4465
4466 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4467 name_len =
4468 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4469 PATH_MAX, nls_codepage, remap);
4470 /* We can not add the asterik earlier in case
4471 it got remapped to 0xF03A as if it were part of the
4472 directory name instead of a wildcard */
4473 name_len *= 2;
4474 if (msearch) {
4475 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4476 pSMB->FileName[name_len+1] = 0;
4477 pSMB->FileName[name_len+2] = '*';
4478 pSMB->FileName[name_len+3] = 0;
4479 name_len += 4; /* now the trailing null */
4480 /* null terminate just in case */
4481 pSMB->FileName[name_len] = 0;
4482 pSMB->FileName[name_len+1] = 0;
4483 name_len += 2;
4484 }
4485 } else { /* BB add check for overrun of SMB buf BB */
4486 name_len = strnlen(searchName, PATH_MAX);
4487 /* BB fix here and in unicode clause above ie
4488 if (name_len > buffersize-header)
4489 free buffer exit; BB */
4490 strncpy(pSMB->FileName, searchName, name_len);
4491 if (msearch) {
4492 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4493 pSMB->FileName[name_len+1] = '*';
4494 pSMB->FileName[name_len+2] = 0;
4495 name_len += 3;
4496 }
4497 }
4498
4499 params = 12 + name_len /* includes null */ ;
4500 pSMB->TotalDataCount = 0; /* no EAs */
4501 pSMB->MaxParameterCount = cpu_to_le16(10);
4502 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4503 pSMB->MaxSetupCount = 0;
4504 pSMB->Reserved = 0;
4505 pSMB->Flags = 0;
4506 pSMB->Timeout = 0;
4507 pSMB->Reserved2 = 0;
4508 byte_count = params + 1 /* pad */ ;
4509 pSMB->TotalParameterCount = cpu_to_le16(params);
4510 pSMB->ParameterCount = pSMB->TotalParameterCount;
4511 pSMB->ParameterOffset = cpu_to_le16(
4512 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4513 - 4);
4514 pSMB->DataCount = 0;
4515 pSMB->DataOffset = 0;
4516 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4517 pSMB->Reserved3 = 0;
4518 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4519 pSMB->SearchAttributes =
4520 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4521 ATTR_DIRECTORY);
4522 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4523 pSMB->SearchFlags = cpu_to_le16(search_flags);
4524 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4525
4526 /* BB what should we set StorageType to? Does it matter? BB */
4527 pSMB->SearchStorageType = 0;
4528 inc_rfc1001_len(pSMB, byte_count);
4529 pSMB->ByteCount = cpu_to_le16(byte_count);
4530
4531 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4532 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4533 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4534
4535 if (rc) {/* BB add logic to retry regular search if Unix search
4536 rejected unexpectedly by server */
4537 /* BB Add code to handle unsupported level rc */
4538 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4539
4540 cifs_buf_release(pSMB);
4541
4542 /* BB eventually could optimize out free and realloc of buf */
4543 /* for this case */
4544 if (rc == -EAGAIN)
4545 goto findFirstRetry;
4546 } else { /* decode response */
4547 /* BB remember to free buffer if error BB */
4548 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4549 if (rc == 0) {
4550 unsigned int lnoff;
4551
4552 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4553 psrch_inf->unicode = true;
4554 else
4555 psrch_inf->unicode = false;
4556
4557 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4558 psrch_inf->smallBuf = 0;
4559 psrch_inf->srch_entries_start =
4560 (char *) &pSMBr->hdr.Protocol +
4561 le16_to_cpu(pSMBr->t2.DataOffset);
4562 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4563 le16_to_cpu(pSMBr->t2.ParameterOffset));
4564
4565 if (parms->EndofSearch)
4566 psrch_inf->endOfSearch = true;
4567 else
4568 psrch_inf->endOfSearch = false;
4569
4570 psrch_inf->entries_in_buffer =
4571 le16_to_cpu(parms->SearchCount);
4572 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4573 psrch_inf->entries_in_buffer;
4574 lnoff = le16_to_cpu(parms->LastNameOffset);
4575 if (CIFSMaxBufSize < lnoff) {
4576 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4577 psrch_inf->last_entry = NULL;
4578 return rc;
4579 }
4580
4581 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4582 lnoff;
4583
4584 if (pnetfid)
4585 *pnetfid = parms->SearchHandle;
4586 } else {
4587 cifs_buf_release(pSMB);
4588 }
4589 }
4590
4591 return rc;
4592 }
4593
CIFSFindNext(const unsigned int xid,struct cifs_tcon * tcon,__u16 searchHandle,__u16 search_flags,struct cifs_search_info * psrch_inf)4594 int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4595 __u16 searchHandle, __u16 search_flags,
4596 struct cifs_search_info *psrch_inf)
4597 {
4598 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4599 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4600 T2_FNEXT_RSP_PARMS *parms;
4601 char *response_data;
4602 int rc = 0;
4603 int bytes_returned;
4604 unsigned int name_len;
4605 __u16 params, byte_count;
4606
4607 cifs_dbg(FYI, "In FindNext\n");
4608
4609 if (psrch_inf->endOfSearch)
4610 return -ENOENT;
4611
4612 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4613 (void **) &pSMBr);
4614 if (rc)
4615 return rc;
4616
4617 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4618 byte_count = 0;
4619 pSMB->TotalDataCount = 0; /* no EAs */
4620 pSMB->MaxParameterCount = cpu_to_le16(8);
4621 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4622 pSMB->MaxSetupCount = 0;
4623 pSMB->Reserved = 0;
4624 pSMB->Flags = 0;
4625 pSMB->Timeout = 0;
4626 pSMB->Reserved2 = 0;
4627 pSMB->ParameterOffset = cpu_to_le16(
4628 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4629 pSMB->DataCount = 0;
4630 pSMB->DataOffset = 0;
4631 pSMB->SetupCount = 1;
4632 pSMB->Reserved3 = 0;
4633 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4634 pSMB->SearchHandle = searchHandle; /* always kept as le */
4635 pSMB->SearchCount =
4636 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4637 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4638 pSMB->ResumeKey = psrch_inf->resume_key;
4639 pSMB->SearchFlags = cpu_to_le16(search_flags);
4640
4641 name_len = psrch_inf->resume_name_len;
4642 params += name_len;
4643 if (name_len < PATH_MAX) {
4644 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4645 byte_count += name_len;
4646 /* 14 byte parm len above enough for 2 byte null terminator */
4647 pSMB->ResumeFileName[name_len] = 0;
4648 pSMB->ResumeFileName[name_len+1] = 0;
4649 } else {
4650 rc = -EINVAL;
4651 goto FNext2_err_exit;
4652 }
4653 byte_count = params + 1 /* pad */ ;
4654 pSMB->TotalParameterCount = cpu_to_le16(params);
4655 pSMB->ParameterCount = pSMB->TotalParameterCount;
4656 inc_rfc1001_len(pSMB, byte_count);
4657 pSMB->ByteCount = cpu_to_le16(byte_count);
4658
4659 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4660 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4661 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4662 if (rc) {
4663 if (rc == -EBADF) {
4664 psrch_inf->endOfSearch = true;
4665 cifs_buf_release(pSMB);
4666 rc = 0; /* search probably was closed at end of search*/
4667 } else
4668 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4669 } else { /* decode response */
4670 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4671
4672 if (rc == 0) {
4673 unsigned int lnoff;
4674
4675 /* BB fixme add lock for file (srch_info) struct here */
4676 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4677 psrch_inf->unicode = true;
4678 else
4679 psrch_inf->unicode = false;
4680 response_data = (char *) &pSMBr->hdr.Protocol +
4681 le16_to_cpu(pSMBr->t2.ParameterOffset);
4682 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4683 response_data = (char *)&pSMBr->hdr.Protocol +
4684 le16_to_cpu(pSMBr->t2.DataOffset);
4685 if (psrch_inf->smallBuf)
4686 cifs_small_buf_release(
4687 psrch_inf->ntwrk_buf_start);
4688 else
4689 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4690 psrch_inf->srch_entries_start = response_data;
4691 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4692 psrch_inf->smallBuf = 0;
4693 if (parms->EndofSearch)
4694 psrch_inf->endOfSearch = true;
4695 else
4696 psrch_inf->endOfSearch = false;
4697 psrch_inf->entries_in_buffer =
4698 le16_to_cpu(parms->SearchCount);
4699 psrch_inf->index_of_last_entry +=
4700 psrch_inf->entries_in_buffer;
4701 lnoff = le16_to_cpu(parms->LastNameOffset);
4702 if (CIFSMaxBufSize < lnoff) {
4703 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4704 psrch_inf->last_entry = NULL;
4705 return rc;
4706 } else
4707 psrch_inf->last_entry =
4708 psrch_inf->srch_entries_start + lnoff;
4709
4710 /* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4711 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4712
4713 /* BB fixme add unlock here */
4714 }
4715
4716 }
4717
4718 /* BB On error, should we leave previous search buf (and count and
4719 last entry fields) intact or free the previous one? */
4720
4721 /* Note: On -EAGAIN error only caller can retry on handle based calls
4722 since file handle passed in no longer valid */
4723 FNext2_err_exit:
4724 if (rc != 0)
4725 cifs_buf_release(pSMB);
4726 return rc;
4727 }
4728
4729 int
CIFSFindClose(const unsigned int xid,struct cifs_tcon * tcon,const __u16 searchHandle)4730 CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4731 const __u16 searchHandle)
4732 {
4733 int rc = 0;
4734 FINDCLOSE_REQ *pSMB = NULL;
4735
4736 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4737 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4738
4739 /* no sense returning error if session restarted
4740 as file handle has been closed */
4741 if (rc == -EAGAIN)
4742 return 0;
4743 if (rc)
4744 return rc;
4745
4746 pSMB->FileID = searchHandle;
4747 pSMB->ByteCount = 0;
4748 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4749 cifs_small_buf_release(pSMB);
4750 if (rc)
4751 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4752
4753 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4754
4755 /* Since session is dead, search handle closed on server already */
4756 if (rc == -EAGAIN)
4757 rc = 0;
4758
4759 return rc;
4760 }
4761
4762 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)4763 CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4764 const char *search_name, __u64 *inode_number,
4765 const struct nls_table *nls_codepage, int remap)
4766 {
4767 int rc = 0;
4768 TRANSACTION2_QPI_REQ *pSMB = NULL;
4769 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4770 int name_len, bytes_returned;
4771 __u16 params, byte_count;
4772
4773 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4774 if (tcon == NULL)
4775 return -ENODEV;
4776
4777 GetInodeNumberRetry:
4778 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4779 (void **) &pSMBr);
4780 if (rc)
4781 return rc;
4782
4783 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4784 name_len =
4785 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4786 search_name, PATH_MAX, nls_codepage,
4787 remap);
4788 name_len++; /* trailing null */
4789 name_len *= 2;
4790 } else { /* BB improve the check for buffer overruns BB */
4791 name_len = strnlen(search_name, PATH_MAX);
4792 name_len++; /* trailing null */
4793 strncpy(pSMB->FileName, search_name, name_len);
4794 }
4795
4796 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4797 pSMB->TotalDataCount = 0;
4798 pSMB->MaxParameterCount = cpu_to_le16(2);
4799 /* BB find exact max data count below from sess structure BB */
4800 pSMB->MaxDataCount = cpu_to_le16(4000);
4801 pSMB->MaxSetupCount = 0;
4802 pSMB->Reserved = 0;
4803 pSMB->Flags = 0;
4804 pSMB->Timeout = 0;
4805 pSMB->Reserved2 = 0;
4806 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4807 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4808 pSMB->DataCount = 0;
4809 pSMB->DataOffset = 0;
4810 pSMB->SetupCount = 1;
4811 pSMB->Reserved3 = 0;
4812 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4813 byte_count = params + 1 /* pad */ ;
4814 pSMB->TotalParameterCount = cpu_to_le16(params);
4815 pSMB->ParameterCount = pSMB->TotalParameterCount;
4816 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4817 pSMB->Reserved4 = 0;
4818 inc_rfc1001_len(pSMB, byte_count);
4819 pSMB->ByteCount = cpu_to_le16(byte_count);
4820
4821 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4822 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4823 if (rc) {
4824 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4825 } else {
4826 /* decode response */
4827 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4828 /* BB also check enough total bytes returned */
4829 if (rc || get_bcc(&pSMBr->hdr) < 2)
4830 /* If rc should we check for EOPNOSUPP and
4831 disable the srvino flag? or in caller? */
4832 rc = -EIO; /* bad smb */
4833 else {
4834 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4835 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4836 struct file_internal_info *pfinfo;
4837 /* BB Do we need a cast or hash here ? */
4838 if (count < 8) {
4839 cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4840 rc = -EIO;
4841 goto GetInodeNumOut;
4842 }
4843 pfinfo = (struct file_internal_info *)
4844 (data_offset + (char *) &pSMBr->hdr.Protocol);
4845 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4846 }
4847 }
4848 GetInodeNumOut:
4849 cifs_buf_release(pSMB);
4850 if (rc == -EAGAIN)
4851 goto GetInodeNumberRetry;
4852 return rc;
4853 }
4854
4855 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)4856 CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4857 const char *search_name, struct dfs_info3_param **target_nodes,
4858 unsigned int *num_of_nodes,
4859 const struct nls_table *nls_codepage, int remap)
4860 {
4861 /* TRANS2_GET_DFS_REFERRAL */
4862 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4863 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4864 int rc = 0;
4865 int bytes_returned;
4866 int name_len;
4867 __u16 params, byte_count;
4868 *num_of_nodes = 0;
4869 *target_nodes = NULL;
4870
4871 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4872 if (ses == NULL || ses->tcon_ipc == NULL)
4873 return -ENODEV;
4874
4875 getDFSRetry:
4876 rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
4877 (void **) &pSMBr);
4878 if (rc)
4879 return rc;
4880
4881 /* server pointer checked in called function,
4882 but should never be null here anyway */
4883 pSMB->hdr.Mid = get_next_mid(ses->server);
4884 pSMB->hdr.Tid = ses->tcon_ipc->tid;
4885 pSMB->hdr.Uid = ses->Suid;
4886 if (ses->capabilities & CAP_STATUS32)
4887 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4888 if (ses->capabilities & CAP_DFS)
4889 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4890
4891 if (ses->capabilities & CAP_UNICODE) {
4892 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4893 name_len =
4894 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4895 search_name, PATH_MAX, nls_codepage,
4896 remap);
4897 name_len++; /* trailing null */
4898 name_len *= 2;
4899 } else { /* BB improve the check for buffer overruns BB */
4900 name_len = strnlen(search_name, PATH_MAX);
4901 name_len++; /* trailing null */
4902 strncpy(pSMB->RequestFileName, search_name, name_len);
4903 }
4904
4905 if (ses->server->sign)
4906 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4907
4908 pSMB->hdr.Uid = ses->Suid;
4909
4910 params = 2 /* level */ + name_len /*includes null */ ;
4911 pSMB->TotalDataCount = 0;
4912 pSMB->DataCount = 0;
4913 pSMB->DataOffset = 0;
4914 pSMB->MaxParameterCount = 0;
4915 /* BB find exact max SMB PDU from sess structure BB */
4916 pSMB->MaxDataCount = cpu_to_le16(4000);
4917 pSMB->MaxSetupCount = 0;
4918 pSMB->Reserved = 0;
4919 pSMB->Flags = 0;
4920 pSMB->Timeout = 0;
4921 pSMB->Reserved2 = 0;
4922 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4923 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4924 pSMB->SetupCount = 1;
4925 pSMB->Reserved3 = 0;
4926 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4927 byte_count = params + 3 /* pad */ ;
4928 pSMB->ParameterCount = cpu_to_le16(params);
4929 pSMB->TotalParameterCount = pSMB->ParameterCount;
4930 pSMB->MaxReferralLevel = cpu_to_le16(3);
4931 inc_rfc1001_len(pSMB, byte_count);
4932 pSMB->ByteCount = cpu_to_le16(byte_count);
4933
4934 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4935 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4936 if (rc) {
4937 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4938 goto GetDFSRefExit;
4939 }
4940 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4941
4942 /* BB Also check if enough total bytes returned? */
4943 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4944 rc = -EIO; /* bad smb */
4945 goto GetDFSRefExit;
4946 }
4947
4948 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4949 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4950
4951 /* parse returned result into more usable form */
4952 rc = parse_dfs_referrals(&pSMBr->dfs_data,
4953 le16_to_cpu(pSMBr->t2.DataCount),
4954 num_of_nodes, target_nodes, nls_codepage,
4955 remap, search_name,
4956 (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) != 0);
4957
4958 GetDFSRefExit:
4959 cifs_buf_release(pSMB);
4960
4961 if (rc == -EAGAIN)
4962 goto getDFSRetry;
4963
4964 return rc;
4965 }
4966
4967 /* Query File System Info such as free space to old servers such as Win 9x */
4968 int
SMBOldQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)4969 SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4970 struct kstatfs *FSData)
4971 {
4972 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4973 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4974 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4975 FILE_SYSTEM_ALLOC_INFO *response_data;
4976 int rc = 0;
4977 int bytes_returned = 0;
4978 __u16 params, byte_count;
4979
4980 cifs_dbg(FYI, "OldQFSInfo\n");
4981 oldQFSInfoRetry:
4982 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4983 (void **) &pSMBr);
4984 if (rc)
4985 return rc;
4986
4987 params = 2; /* level */
4988 pSMB->TotalDataCount = 0;
4989 pSMB->MaxParameterCount = cpu_to_le16(2);
4990 pSMB->MaxDataCount = cpu_to_le16(1000);
4991 pSMB->MaxSetupCount = 0;
4992 pSMB->Reserved = 0;
4993 pSMB->Flags = 0;
4994 pSMB->Timeout = 0;
4995 pSMB->Reserved2 = 0;
4996 byte_count = params + 1 /* pad */ ;
4997 pSMB->TotalParameterCount = cpu_to_le16(params);
4998 pSMB->ParameterCount = pSMB->TotalParameterCount;
4999 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5000 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5001 pSMB->DataCount = 0;
5002 pSMB->DataOffset = 0;
5003 pSMB->SetupCount = 1;
5004 pSMB->Reserved3 = 0;
5005 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5006 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
5007 inc_rfc1001_len(pSMB, byte_count);
5008 pSMB->ByteCount = cpu_to_le16(byte_count);
5009
5010 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5011 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5012 if (rc) {
5013 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5014 } else { /* decode response */
5015 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5016
5017 if (rc || get_bcc(&pSMBr->hdr) < 18)
5018 rc = -EIO; /* bad smb */
5019 else {
5020 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5021 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
5022 get_bcc(&pSMBr->hdr), data_offset);
5023
5024 response_data = (FILE_SYSTEM_ALLOC_INFO *)
5025 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5026 FSData->f_bsize =
5027 le16_to_cpu(response_data->BytesPerSector) *
5028 le32_to_cpu(response_data->
5029 SectorsPerAllocationUnit);
5030 FSData->f_blocks =
5031 le32_to_cpu(response_data->TotalAllocationUnits);
5032 FSData->f_bfree = FSData->f_bavail =
5033 le32_to_cpu(response_data->FreeAllocationUnits);
5034 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5035 (unsigned long long)FSData->f_blocks,
5036 (unsigned long long)FSData->f_bfree,
5037 FSData->f_bsize);
5038 }
5039 }
5040 cifs_buf_release(pSMB);
5041
5042 if (rc == -EAGAIN)
5043 goto oldQFSInfoRetry;
5044
5045 return rc;
5046 }
5047
5048 int
CIFSSMBQFSInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5049 CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5050 struct kstatfs *FSData)
5051 {
5052 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5053 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5054 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5055 FILE_SYSTEM_INFO *response_data;
5056 int rc = 0;
5057 int bytes_returned = 0;
5058 __u16 params, byte_count;
5059
5060 cifs_dbg(FYI, "In QFSInfo\n");
5061 QFSInfoRetry:
5062 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5063 (void **) &pSMBr);
5064 if (rc)
5065 return rc;
5066
5067 params = 2; /* level */
5068 pSMB->TotalDataCount = 0;
5069 pSMB->MaxParameterCount = cpu_to_le16(2);
5070 pSMB->MaxDataCount = cpu_to_le16(1000);
5071 pSMB->MaxSetupCount = 0;
5072 pSMB->Reserved = 0;
5073 pSMB->Flags = 0;
5074 pSMB->Timeout = 0;
5075 pSMB->Reserved2 = 0;
5076 byte_count = params + 1 /* pad */ ;
5077 pSMB->TotalParameterCount = cpu_to_le16(params);
5078 pSMB->ParameterCount = pSMB->TotalParameterCount;
5079 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5080 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5081 pSMB->DataCount = 0;
5082 pSMB->DataOffset = 0;
5083 pSMB->SetupCount = 1;
5084 pSMB->Reserved3 = 0;
5085 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5086 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5087 inc_rfc1001_len(pSMB, byte_count);
5088 pSMB->ByteCount = cpu_to_le16(byte_count);
5089
5090 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5091 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5092 if (rc) {
5093 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5094 } else { /* decode response */
5095 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5096
5097 if (rc || get_bcc(&pSMBr->hdr) < 24)
5098 rc = -EIO; /* bad smb */
5099 else {
5100 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5101
5102 response_data =
5103 (FILE_SYSTEM_INFO
5104 *) (((char *) &pSMBr->hdr.Protocol) +
5105 data_offset);
5106 FSData->f_bsize =
5107 le32_to_cpu(response_data->BytesPerSector) *
5108 le32_to_cpu(response_data->
5109 SectorsPerAllocationUnit);
5110 FSData->f_blocks =
5111 le64_to_cpu(response_data->TotalAllocationUnits);
5112 FSData->f_bfree = FSData->f_bavail =
5113 le64_to_cpu(response_data->FreeAllocationUnits);
5114 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5115 (unsigned long long)FSData->f_blocks,
5116 (unsigned long long)FSData->f_bfree,
5117 FSData->f_bsize);
5118 }
5119 }
5120 cifs_buf_release(pSMB);
5121
5122 if (rc == -EAGAIN)
5123 goto QFSInfoRetry;
5124
5125 return rc;
5126 }
5127
5128 int
CIFSSMBQFSAttributeInfo(const unsigned int xid,struct cifs_tcon * tcon)5129 CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5130 {
5131 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5132 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5133 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5134 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5135 int rc = 0;
5136 int bytes_returned = 0;
5137 __u16 params, byte_count;
5138
5139 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5140 QFSAttributeRetry:
5141 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5142 (void **) &pSMBr);
5143 if (rc)
5144 return rc;
5145
5146 params = 2; /* level */
5147 pSMB->TotalDataCount = 0;
5148 pSMB->MaxParameterCount = cpu_to_le16(2);
5149 /* BB find exact max SMB PDU from sess structure BB */
5150 pSMB->MaxDataCount = cpu_to_le16(1000);
5151 pSMB->MaxSetupCount = 0;
5152 pSMB->Reserved = 0;
5153 pSMB->Flags = 0;
5154 pSMB->Timeout = 0;
5155 pSMB->Reserved2 = 0;
5156 byte_count = params + 1 /* pad */ ;
5157 pSMB->TotalParameterCount = cpu_to_le16(params);
5158 pSMB->ParameterCount = pSMB->TotalParameterCount;
5159 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5160 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5161 pSMB->DataCount = 0;
5162 pSMB->DataOffset = 0;
5163 pSMB->SetupCount = 1;
5164 pSMB->Reserved3 = 0;
5165 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5166 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5167 inc_rfc1001_len(pSMB, byte_count);
5168 pSMB->ByteCount = cpu_to_le16(byte_count);
5169
5170 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5171 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5172 if (rc) {
5173 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5174 } else { /* decode response */
5175 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5176
5177 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5178 /* BB also check if enough bytes returned */
5179 rc = -EIO; /* bad smb */
5180 } else {
5181 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5182 response_data =
5183 (FILE_SYSTEM_ATTRIBUTE_INFO
5184 *) (((char *) &pSMBr->hdr.Protocol) +
5185 data_offset);
5186 memcpy(&tcon->fsAttrInfo, response_data,
5187 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5188 }
5189 }
5190 cifs_buf_release(pSMB);
5191
5192 if (rc == -EAGAIN)
5193 goto QFSAttributeRetry;
5194
5195 return rc;
5196 }
5197
5198 int
CIFSSMBQFSDeviceInfo(const unsigned int xid,struct cifs_tcon * tcon)5199 CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5200 {
5201 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5202 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5203 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5204 FILE_SYSTEM_DEVICE_INFO *response_data;
5205 int rc = 0;
5206 int bytes_returned = 0;
5207 __u16 params, byte_count;
5208
5209 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5210 QFSDeviceRetry:
5211 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5212 (void **) &pSMBr);
5213 if (rc)
5214 return rc;
5215
5216 params = 2; /* level */
5217 pSMB->TotalDataCount = 0;
5218 pSMB->MaxParameterCount = cpu_to_le16(2);
5219 /* BB find exact max SMB PDU from sess structure BB */
5220 pSMB->MaxDataCount = cpu_to_le16(1000);
5221 pSMB->MaxSetupCount = 0;
5222 pSMB->Reserved = 0;
5223 pSMB->Flags = 0;
5224 pSMB->Timeout = 0;
5225 pSMB->Reserved2 = 0;
5226 byte_count = params + 1 /* pad */ ;
5227 pSMB->TotalParameterCount = cpu_to_le16(params);
5228 pSMB->ParameterCount = pSMB->TotalParameterCount;
5229 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5230 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5231
5232 pSMB->DataCount = 0;
5233 pSMB->DataOffset = 0;
5234 pSMB->SetupCount = 1;
5235 pSMB->Reserved3 = 0;
5236 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5237 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5238 inc_rfc1001_len(pSMB, byte_count);
5239 pSMB->ByteCount = cpu_to_le16(byte_count);
5240
5241 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5242 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5243 if (rc) {
5244 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5245 } else { /* decode response */
5246 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5247
5248 if (rc || get_bcc(&pSMBr->hdr) <
5249 sizeof(FILE_SYSTEM_DEVICE_INFO))
5250 rc = -EIO; /* bad smb */
5251 else {
5252 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5253 response_data =
5254 (FILE_SYSTEM_DEVICE_INFO *)
5255 (((char *) &pSMBr->hdr.Protocol) +
5256 data_offset);
5257 memcpy(&tcon->fsDevInfo, response_data,
5258 sizeof(FILE_SYSTEM_DEVICE_INFO));
5259 }
5260 }
5261 cifs_buf_release(pSMB);
5262
5263 if (rc == -EAGAIN)
5264 goto QFSDeviceRetry;
5265
5266 return rc;
5267 }
5268
5269 int
CIFSSMBQFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon)5270 CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5271 {
5272 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5273 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5274 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5275 FILE_SYSTEM_UNIX_INFO *response_data;
5276 int rc = 0;
5277 int bytes_returned = 0;
5278 __u16 params, byte_count;
5279
5280 cifs_dbg(FYI, "In QFSUnixInfo\n");
5281 QFSUnixRetry:
5282 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5283 (void **) &pSMB, (void **) &pSMBr);
5284 if (rc)
5285 return rc;
5286
5287 params = 2; /* level */
5288 pSMB->TotalDataCount = 0;
5289 pSMB->DataCount = 0;
5290 pSMB->DataOffset = 0;
5291 pSMB->MaxParameterCount = cpu_to_le16(2);
5292 /* BB find exact max SMB PDU from sess structure BB */
5293 pSMB->MaxDataCount = cpu_to_le16(100);
5294 pSMB->MaxSetupCount = 0;
5295 pSMB->Reserved = 0;
5296 pSMB->Flags = 0;
5297 pSMB->Timeout = 0;
5298 pSMB->Reserved2 = 0;
5299 byte_count = params + 1 /* pad */ ;
5300 pSMB->ParameterCount = cpu_to_le16(params);
5301 pSMB->TotalParameterCount = pSMB->ParameterCount;
5302 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5303 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5304 pSMB->SetupCount = 1;
5305 pSMB->Reserved3 = 0;
5306 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5307 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5308 inc_rfc1001_len(pSMB, byte_count);
5309 pSMB->ByteCount = cpu_to_le16(byte_count);
5310
5311 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5312 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5313 if (rc) {
5314 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5315 } else { /* decode response */
5316 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5317
5318 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5319 rc = -EIO; /* bad smb */
5320 } else {
5321 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5322 response_data =
5323 (FILE_SYSTEM_UNIX_INFO
5324 *) (((char *) &pSMBr->hdr.Protocol) +
5325 data_offset);
5326 memcpy(&tcon->fsUnixInfo, response_data,
5327 sizeof(FILE_SYSTEM_UNIX_INFO));
5328 }
5329 }
5330 cifs_buf_release(pSMB);
5331
5332 if (rc == -EAGAIN)
5333 goto QFSUnixRetry;
5334
5335
5336 return rc;
5337 }
5338
5339 int
CIFSSMBSetFSUnixInfo(const unsigned int xid,struct cifs_tcon * tcon,__u64 cap)5340 CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5341 {
5342 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5343 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5344 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5345 int rc = 0;
5346 int bytes_returned = 0;
5347 __u16 params, param_offset, offset, byte_count;
5348
5349 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5350 SETFSUnixRetry:
5351 /* BB switch to small buf init to save memory */
5352 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5353 (void **) &pSMB, (void **) &pSMBr);
5354 if (rc)
5355 return rc;
5356
5357 params = 4; /* 2 bytes zero followed by info level. */
5358 pSMB->MaxSetupCount = 0;
5359 pSMB->Reserved = 0;
5360 pSMB->Flags = 0;
5361 pSMB->Timeout = 0;
5362 pSMB->Reserved2 = 0;
5363 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5364 - 4;
5365 offset = param_offset + params;
5366
5367 pSMB->MaxParameterCount = cpu_to_le16(4);
5368 /* BB find exact max SMB PDU from sess structure BB */
5369 pSMB->MaxDataCount = cpu_to_le16(100);
5370 pSMB->SetupCount = 1;
5371 pSMB->Reserved3 = 0;
5372 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5373 byte_count = 1 /* pad */ + params + 12;
5374
5375 pSMB->DataCount = cpu_to_le16(12);
5376 pSMB->ParameterCount = cpu_to_le16(params);
5377 pSMB->TotalDataCount = pSMB->DataCount;
5378 pSMB->TotalParameterCount = pSMB->ParameterCount;
5379 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5380 pSMB->DataOffset = cpu_to_le16(offset);
5381
5382 /* Params. */
5383 pSMB->FileNum = 0;
5384 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5385
5386 /* Data. */
5387 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5388 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5389 pSMB->ClientUnixCap = cpu_to_le64(cap);
5390
5391 inc_rfc1001_len(pSMB, byte_count);
5392 pSMB->ByteCount = cpu_to_le16(byte_count);
5393
5394 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5395 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5396 if (rc) {
5397 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5398 } else { /* decode response */
5399 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5400 if (rc)
5401 rc = -EIO; /* bad smb */
5402 }
5403 cifs_buf_release(pSMB);
5404
5405 if (rc == -EAGAIN)
5406 goto SETFSUnixRetry;
5407
5408 return rc;
5409 }
5410
5411
5412
5413 int
CIFSSMBQFSPosixInfo(const unsigned int xid,struct cifs_tcon * tcon,struct kstatfs * FSData)5414 CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5415 struct kstatfs *FSData)
5416 {
5417 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5418 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5419 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5420 FILE_SYSTEM_POSIX_INFO *response_data;
5421 int rc = 0;
5422 int bytes_returned = 0;
5423 __u16 params, byte_count;
5424
5425 cifs_dbg(FYI, "In QFSPosixInfo\n");
5426 QFSPosixRetry:
5427 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5428 (void **) &pSMBr);
5429 if (rc)
5430 return rc;
5431
5432 params = 2; /* level */
5433 pSMB->TotalDataCount = 0;
5434 pSMB->DataCount = 0;
5435 pSMB->DataOffset = 0;
5436 pSMB->MaxParameterCount = cpu_to_le16(2);
5437 /* BB find exact max SMB PDU from sess structure BB */
5438 pSMB->MaxDataCount = cpu_to_le16(100);
5439 pSMB->MaxSetupCount = 0;
5440 pSMB->Reserved = 0;
5441 pSMB->Flags = 0;
5442 pSMB->Timeout = 0;
5443 pSMB->Reserved2 = 0;
5444 byte_count = params + 1 /* pad */ ;
5445 pSMB->ParameterCount = cpu_to_le16(params);
5446 pSMB->TotalParameterCount = pSMB->ParameterCount;
5447 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5448 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5449 pSMB->SetupCount = 1;
5450 pSMB->Reserved3 = 0;
5451 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5452 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5453 inc_rfc1001_len(pSMB, byte_count);
5454 pSMB->ByteCount = cpu_to_le16(byte_count);
5455
5456 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5457 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5458 if (rc) {
5459 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5460 } else { /* decode response */
5461 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5462
5463 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5464 rc = -EIO; /* bad smb */
5465 } else {
5466 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5467 response_data =
5468 (FILE_SYSTEM_POSIX_INFO
5469 *) (((char *) &pSMBr->hdr.Protocol) +
5470 data_offset);
5471 FSData->f_bsize =
5472 le32_to_cpu(response_data->BlockSize);
5473 FSData->f_blocks =
5474 le64_to_cpu(response_data->TotalBlocks);
5475 FSData->f_bfree =
5476 le64_to_cpu(response_data->BlocksAvail);
5477 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5478 FSData->f_bavail = FSData->f_bfree;
5479 } else {
5480 FSData->f_bavail =
5481 le64_to_cpu(response_data->UserBlocksAvail);
5482 }
5483 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5484 FSData->f_files =
5485 le64_to_cpu(response_data->TotalFileNodes);
5486 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5487 FSData->f_ffree =
5488 le64_to_cpu(response_data->FreeFileNodes);
5489 }
5490 }
5491 cifs_buf_release(pSMB);
5492
5493 if (rc == -EAGAIN)
5494 goto QFSPosixRetry;
5495
5496 return rc;
5497 }
5498
5499
5500 /*
5501 * We can not use write of zero bytes trick to set file size due to need for
5502 * large file support. Also note that this SetPathInfo is preferred to
5503 * SetFileInfo based method in next routine which is only needed to work around
5504 * a sharing violation bugin Samba which this routine can run into.
5505 */
5506 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)5507 CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5508 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5509 bool set_allocation)
5510 {
5511 struct smb_com_transaction2_spi_req *pSMB = NULL;
5512 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5513 struct file_end_of_file_info *parm_data;
5514 int name_len;
5515 int rc = 0;
5516 int bytes_returned = 0;
5517 int remap = cifs_remap(cifs_sb);
5518
5519 __u16 params, byte_count, data_count, param_offset, offset;
5520
5521 cifs_dbg(FYI, "In SetEOF\n");
5522 SetEOFRetry:
5523 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5524 (void **) &pSMBr);
5525 if (rc)
5526 return rc;
5527
5528 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5529 name_len =
5530 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5531 PATH_MAX, cifs_sb->local_nls, remap);
5532 name_len++; /* trailing null */
5533 name_len *= 2;
5534 } else { /* BB improve the check for buffer overruns BB */
5535 name_len = strnlen(file_name, PATH_MAX);
5536 name_len++; /* trailing null */
5537 strncpy(pSMB->FileName, file_name, name_len);
5538 }
5539 params = 6 + name_len;
5540 data_count = sizeof(struct file_end_of_file_info);
5541 pSMB->MaxParameterCount = cpu_to_le16(2);
5542 pSMB->MaxDataCount = cpu_to_le16(4100);
5543 pSMB->MaxSetupCount = 0;
5544 pSMB->Reserved = 0;
5545 pSMB->Flags = 0;
5546 pSMB->Timeout = 0;
5547 pSMB->Reserved2 = 0;
5548 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5549 InformationLevel) - 4;
5550 offset = param_offset + params;
5551 if (set_allocation) {
5552 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5553 pSMB->InformationLevel =
5554 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5555 else
5556 pSMB->InformationLevel =
5557 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5558 } else /* Set File Size */ {
5559 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5560 pSMB->InformationLevel =
5561 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5562 else
5563 pSMB->InformationLevel =
5564 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5565 }
5566
5567 parm_data =
5568 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5569 offset);
5570 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5571 pSMB->DataOffset = cpu_to_le16(offset);
5572 pSMB->SetupCount = 1;
5573 pSMB->Reserved3 = 0;
5574 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5575 byte_count = 3 /* pad */ + params + data_count;
5576 pSMB->DataCount = cpu_to_le16(data_count);
5577 pSMB->TotalDataCount = pSMB->DataCount;
5578 pSMB->ParameterCount = cpu_to_le16(params);
5579 pSMB->TotalParameterCount = pSMB->ParameterCount;
5580 pSMB->Reserved4 = 0;
5581 inc_rfc1001_len(pSMB, byte_count);
5582 parm_data->FileSize = cpu_to_le64(size);
5583 pSMB->ByteCount = cpu_to_le16(byte_count);
5584 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5585 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5586 if (rc)
5587 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5588
5589 cifs_buf_release(pSMB);
5590
5591 if (rc == -EAGAIN)
5592 goto SetEOFRetry;
5593
5594 return rc;
5595 }
5596
5597 int
CIFSSMBSetFileSize(const unsigned int xid,struct cifs_tcon * tcon,struct cifsFileInfo * cfile,__u64 size,bool set_allocation)5598 CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5599 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5600 {
5601 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5602 struct file_end_of_file_info *parm_data;
5603 int rc = 0;
5604 __u16 params, param_offset, offset, byte_count, count;
5605
5606 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5607 (long long)size);
5608 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5609
5610 if (rc)
5611 return rc;
5612
5613 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5614 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5615
5616 params = 6;
5617 pSMB->MaxSetupCount = 0;
5618 pSMB->Reserved = 0;
5619 pSMB->Flags = 0;
5620 pSMB->Timeout = 0;
5621 pSMB->Reserved2 = 0;
5622 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5623 offset = param_offset + params;
5624
5625 count = sizeof(struct file_end_of_file_info);
5626 pSMB->MaxParameterCount = cpu_to_le16(2);
5627 /* BB find exact max SMB PDU from sess structure BB */
5628 pSMB->MaxDataCount = cpu_to_le16(1000);
5629 pSMB->SetupCount = 1;
5630 pSMB->Reserved3 = 0;
5631 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5632 byte_count = 3 /* pad */ + params + count;
5633 pSMB->DataCount = cpu_to_le16(count);
5634 pSMB->ParameterCount = cpu_to_le16(params);
5635 pSMB->TotalDataCount = pSMB->DataCount;
5636 pSMB->TotalParameterCount = pSMB->ParameterCount;
5637 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5638 parm_data =
5639 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5640 + offset);
5641 pSMB->DataOffset = cpu_to_le16(offset);
5642 parm_data->FileSize = cpu_to_le64(size);
5643 pSMB->Fid = cfile->fid.netfid;
5644 if (set_allocation) {
5645 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5646 pSMB->InformationLevel =
5647 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5648 else
5649 pSMB->InformationLevel =
5650 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5651 } else /* Set File Size */ {
5652 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5653 pSMB->InformationLevel =
5654 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5655 else
5656 pSMB->InformationLevel =
5657 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5658 }
5659 pSMB->Reserved4 = 0;
5660 inc_rfc1001_len(pSMB, byte_count);
5661 pSMB->ByteCount = cpu_to_le16(byte_count);
5662 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5663 cifs_small_buf_release(pSMB);
5664 if (rc) {
5665 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5666 rc);
5667 }
5668
5669 /* Note: On -EAGAIN error only caller can retry on handle based calls
5670 since file handle passed in no longer valid */
5671
5672 return rc;
5673 }
5674
5675 /* Some legacy servers such as NT4 require that the file times be set on
5676 an open handle, rather than by pathname - this is awkward due to
5677 potential access conflicts on the open, but it is unavoidable for these
5678 old servers since the only other choice is to go from 100 nanosecond DCE
5679 time and resort to the original setpathinfo level which takes the ancient
5680 DOS time format with 2 second granularity */
5681 int
CIFSSMBSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const FILE_BASIC_INFO * data,__u16 fid,__u32 pid_of_opener)5682 CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5683 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5684 {
5685 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5686 char *data_offset;
5687 int rc = 0;
5688 __u16 params, param_offset, offset, byte_count, count;
5689
5690 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5691 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5692
5693 if (rc)
5694 return rc;
5695
5696 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5697 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5698
5699 params = 6;
5700 pSMB->MaxSetupCount = 0;
5701 pSMB->Reserved = 0;
5702 pSMB->Flags = 0;
5703 pSMB->Timeout = 0;
5704 pSMB->Reserved2 = 0;
5705 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5706 offset = param_offset + params;
5707
5708 data_offset = (char *)pSMB +
5709 offsetof(struct smb_hdr, Protocol) + offset;
5710
5711 count = sizeof(FILE_BASIC_INFO);
5712 pSMB->MaxParameterCount = cpu_to_le16(2);
5713 /* BB find max SMB PDU from sess */
5714 pSMB->MaxDataCount = cpu_to_le16(1000);
5715 pSMB->SetupCount = 1;
5716 pSMB->Reserved3 = 0;
5717 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5718 byte_count = 3 /* pad */ + params + count;
5719 pSMB->DataCount = cpu_to_le16(count);
5720 pSMB->ParameterCount = cpu_to_le16(params);
5721 pSMB->TotalDataCount = pSMB->DataCount;
5722 pSMB->TotalParameterCount = pSMB->ParameterCount;
5723 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5724 pSMB->DataOffset = cpu_to_le16(offset);
5725 pSMB->Fid = fid;
5726 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5727 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5728 else
5729 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5730 pSMB->Reserved4 = 0;
5731 inc_rfc1001_len(pSMB, byte_count);
5732 pSMB->ByteCount = cpu_to_le16(byte_count);
5733 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5734 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5735 cifs_small_buf_release(pSMB);
5736 if (rc)
5737 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5738 rc);
5739
5740 /* Note: On -EAGAIN error only caller can retry on handle based calls
5741 since file handle passed in no longer valid */
5742
5743 return rc;
5744 }
5745
5746 int
CIFSSMBSetFileDisposition(const unsigned int xid,struct cifs_tcon * tcon,bool delete_file,__u16 fid,__u32 pid_of_opener)5747 CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5748 bool delete_file, __u16 fid, __u32 pid_of_opener)
5749 {
5750 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5751 char *data_offset;
5752 int rc = 0;
5753 __u16 params, param_offset, offset, byte_count, count;
5754
5755 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5756 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5757
5758 if (rc)
5759 return rc;
5760
5761 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5762 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5763
5764 params = 6;
5765 pSMB->MaxSetupCount = 0;
5766 pSMB->Reserved = 0;
5767 pSMB->Flags = 0;
5768 pSMB->Timeout = 0;
5769 pSMB->Reserved2 = 0;
5770 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5771 offset = param_offset + params;
5772
5773 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5774
5775 count = 1;
5776 pSMB->MaxParameterCount = cpu_to_le16(2);
5777 /* BB find max SMB PDU from sess */
5778 pSMB->MaxDataCount = cpu_to_le16(1000);
5779 pSMB->SetupCount = 1;
5780 pSMB->Reserved3 = 0;
5781 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5782 byte_count = 3 /* pad */ + params + count;
5783 pSMB->DataCount = cpu_to_le16(count);
5784 pSMB->ParameterCount = cpu_to_le16(params);
5785 pSMB->TotalDataCount = pSMB->DataCount;
5786 pSMB->TotalParameterCount = pSMB->ParameterCount;
5787 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5788 pSMB->DataOffset = cpu_to_le16(offset);
5789 pSMB->Fid = fid;
5790 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5791 pSMB->Reserved4 = 0;
5792 inc_rfc1001_len(pSMB, byte_count);
5793 pSMB->ByteCount = cpu_to_le16(byte_count);
5794 *data_offset = delete_file ? 1 : 0;
5795 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5796 cifs_small_buf_release(pSMB);
5797 if (rc)
5798 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5799
5800 return rc;
5801 }
5802
5803 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)5804 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5805 const char *fileName, const FILE_BASIC_INFO *data,
5806 const struct nls_table *nls_codepage, int remap)
5807 {
5808 TRANSACTION2_SPI_REQ *pSMB = NULL;
5809 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5810 int name_len;
5811 int rc = 0;
5812 int bytes_returned = 0;
5813 char *data_offset;
5814 __u16 params, param_offset, offset, byte_count, count;
5815
5816 cifs_dbg(FYI, "In SetTimes\n");
5817
5818 SetTimesRetry:
5819 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5820 (void **) &pSMBr);
5821 if (rc)
5822 return rc;
5823
5824 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5825 name_len =
5826 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5827 PATH_MAX, nls_codepage, remap);
5828 name_len++; /* trailing null */
5829 name_len *= 2;
5830 } else { /* BB improve the check for buffer overruns BB */
5831 name_len = strnlen(fileName, PATH_MAX);
5832 name_len++; /* trailing null */
5833 strncpy(pSMB->FileName, fileName, name_len);
5834 }
5835
5836 params = 6 + name_len;
5837 count = sizeof(FILE_BASIC_INFO);
5838 pSMB->MaxParameterCount = cpu_to_le16(2);
5839 /* BB find max SMB PDU from sess structure BB */
5840 pSMB->MaxDataCount = cpu_to_le16(1000);
5841 pSMB->MaxSetupCount = 0;
5842 pSMB->Reserved = 0;
5843 pSMB->Flags = 0;
5844 pSMB->Timeout = 0;
5845 pSMB->Reserved2 = 0;
5846 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5847 InformationLevel) - 4;
5848 offset = param_offset + params;
5849 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5850 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5851 pSMB->DataOffset = cpu_to_le16(offset);
5852 pSMB->SetupCount = 1;
5853 pSMB->Reserved3 = 0;
5854 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5855 byte_count = 3 /* pad */ + params + count;
5856
5857 pSMB->DataCount = cpu_to_le16(count);
5858 pSMB->ParameterCount = cpu_to_le16(params);
5859 pSMB->TotalDataCount = pSMB->DataCount;
5860 pSMB->TotalParameterCount = pSMB->ParameterCount;
5861 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5862 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5863 else
5864 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5865 pSMB->Reserved4 = 0;
5866 inc_rfc1001_len(pSMB, byte_count);
5867 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5868 pSMB->ByteCount = cpu_to_le16(byte_count);
5869 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5870 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5871 if (rc)
5872 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5873
5874 cifs_buf_release(pSMB);
5875
5876 if (rc == -EAGAIN)
5877 goto SetTimesRetry;
5878
5879 return rc;
5880 }
5881
5882 /* Can not be used to set time stamps yet (due to old DOS time format) */
5883 /* Can be used to set attributes */
5884 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5885 handling it anyway and NT4 was what we thought it would be needed for
5886 Do not delete it until we prove whether needed for Win9x though */
5887 int
5888 CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5889 __u16 dos_attrs, const struct nls_table *nls_codepage)
5890 {
5891 SETATTR_REQ *pSMB = NULL;
5892 SETATTR_RSP *pSMBr = NULL;
5893 int rc = 0;
5894 int bytes_returned;
5895 int name_len;
5896
5897 cifs_dbg(FYI, "In SetAttrLegacy\n");
5898
5899 SetAttrLgcyRetry:
5900 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5901 (void **) &pSMBr);
5902 if (rc)
5903 return rc;
5904
5905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5906 name_len =
5907 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5908 PATH_MAX, nls_codepage);
5909 name_len++; /* trailing null */
5910 name_len *= 2;
5911 } else { /* BB improve the check for buffer overruns BB */
5912 name_len = strnlen(fileName, PATH_MAX);
5913 name_len++; /* trailing null */
5914 strncpy(pSMB->fileName, fileName, name_len);
5915 }
5916 pSMB->attr = cpu_to_le16(dos_attrs);
5917 pSMB->BufferFormat = 0x04;
5918 inc_rfc1001_len(pSMB, name_len + 1);
5919 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5920 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5921 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5922 if (rc)
5923 cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5924
5925 cifs_buf_release(pSMB);
5926
5927 if (rc == -EAGAIN)
5928 goto SetAttrLgcyRetry;
5929
5930 return rc;
5931 }
5932 #endif /* temporarily unneeded SetAttr legacy function */
5933
5934 static void
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO * data_offset,const struct cifs_unix_set_info_args * args)5935 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5936 const struct cifs_unix_set_info_args *args)
5937 {
5938 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5939 u64 mode = args->mode;
5940
5941 if (uid_valid(args->uid))
5942 uid = from_kuid(&init_user_ns, args->uid);
5943 if (gid_valid(args->gid))
5944 gid = from_kgid(&init_user_ns, args->gid);
5945
5946 /*
5947 * Samba server ignores set of file size to zero due to bugs in some
5948 * older clients, but we should be precise - we use SetFileSize to
5949 * set file size and do not want to truncate file size to zero
5950 * accidentally as happened on one Samba server beta by putting
5951 * zero instead of -1 here
5952 */
5953 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5954 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5955 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5956 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5957 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5958 data_offset->Uid = cpu_to_le64(uid);
5959 data_offset->Gid = cpu_to_le64(gid);
5960 /* better to leave device as zero when it is */
5961 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5962 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5963 data_offset->Permissions = cpu_to_le64(mode);
5964
5965 if (S_ISREG(mode))
5966 data_offset->Type = cpu_to_le32(UNIX_FILE);
5967 else if (S_ISDIR(mode))
5968 data_offset->Type = cpu_to_le32(UNIX_DIR);
5969 else if (S_ISLNK(mode))
5970 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5971 else if (S_ISCHR(mode))
5972 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5973 else if (S_ISBLK(mode))
5974 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5975 else if (S_ISFIFO(mode))
5976 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5977 else if (S_ISSOCK(mode))
5978 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5979 }
5980
5981 int
CIFSSMBUnixSetFileInfo(const unsigned int xid,struct cifs_tcon * tcon,const struct cifs_unix_set_info_args * args,u16 fid,u32 pid_of_opener)5982 CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5983 const struct cifs_unix_set_info_args *args,
5984 u16 fid, u32 pid_of_opener)
5985 {
5986 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5987 char *data_offset;
5988 int rc = 0;
5989 u16 params, param_offset, offset, byte_count, count;
5990
5991 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
5992 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5993
5994 if (rc)
5995 return rc;
5996
5997 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5998 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5999
6000 params = 6;
6001 pSMB->MaxSetupCount = 0;
6002 pSMB->Reserved = 0;
6003 pSMB->Flags = 0;
6004 pSMB->Timeout = 0;
6005 pSMB->Reserved2 = 0;
6006 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6007 offset = param_offset + params;
6008
6009 data_offset = (char *)pSMB +
6010 offsetof(struct smb_hdr, Protocol) + offset;
6011
6012 count = sizeof(FILE_UNIX_BASIC_INFO);
6013
6014 pSMB->MaxParameterCount = cpu_to_le16(2);
6015 /* BB find max SMB PDU from sess */
6016 pSMB->MaxDataCount = cpu_to_le16(1000);
6017 pSMB->SetupCount = 1;
6018 pSMB->Reserved3 = 0;
6019 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6020 byte_count = 3 /* pad */ + params + count;
6021 pSMB->DataCount = cpu_to_le16(count);
6022 pSMB->ParameterCount = cpu_to_le16(params);
6023 pSMB->TotalDataCount = pSMB->DataCount;
6024 pSMB->TotalParameterCount = pSMB->ParameterCount;
6025 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6026 pSMB->DataOffset = cpu_to_le16(offset);
6027 pSMB->Fid = fid;
6028 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6029 pSMB->Reserved4 = 0;
6030 inc_rfc1001_len(pSMB, byte_count);
6031 pSMB->ByteCount = cpu_to_le16(byte_count);
6032
6033 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6034
6035 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6036 cifs_small_buf_release(pSMB);
6037 if (rc)
6038 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6039 rc);
6040
6041 /* Note: On -EAGAIN error only caller can retry on handle based calls
6042 since file handle passed in no longer valid */
6043
6044 return rc;
6045 }
6046
6047 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)6048 CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6049 const char *file_name,
6050 const struct cifs_unix_set_info_args *args,
6051 const struct nls_table *nls_codepage, int remap)
6052 {
6053 TRANSACTION2_SPI_REQ *pSMB = NULL;
6054 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6055 int name_len;
6056 int rc = 0;
6057 int bytes_returned = 0;
6058 FILE_UNIX_BASIC_INFO *data_offset;
6059 __u16 params, param_offset, offset, count, byte_count;
6060
6061 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6062 setPermsRetry:
6063 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6064 (void **) &pSMBr);
6065 if (rc)
6066 return rc;
6067
6068 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6069 name_len =
6070 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6071 PATH_MAX, nls_codepage, remap);
6072 name_len++; /* trailing null */
6073 name_len *= 2;
6074 } else { /* BB improve the check for buffer overruns BB */
6075 name_len = strnlen(file_name, PATH_MAX);
6076 name_len++; /* trailing null */
6077 strncpy(pSMB->FileName, file_name, name_len);
6078 }
6079
6080 params = 6 + name_len;
6081 count = sizeof(FILE_UNIX_BASIC_INFO);
6082 pSMB->MaxParameterCount = cpu_to_le16(2);
6083 /* BB find max SMB PDU from sess structure BB */
6084 pSMB->MaxDataCount = cpu_to_le16(1000);
6085 pSMB->MaxSetupCount = 0;
6086 pSMB->Reserved = 0;
6087 pSMB->Flags = 0;
6088 pSMB->Timeout = 0;
6089 pSMB->Reserved2 = 0;
6090 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6091 InformationLevel) - 4;
6092 offset = param_offset + params;
6093 data_offset =
6094 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6095 offset);
6096 memset(data_offset, 0, count);
6097 pSMB->DataOffset = cpu_to_le16(offset);
6098 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6099 pSMB->SetupCount = 1;
6100 pSMB->Reserved3 = 0;
6101 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6102 byte_count = 3 /* pad */ + params + count;
6103 pSMB->ParameterCount = cpu_to_le16(params);
6104 pSMB->DataCount = cpu_to_le16(count);
6105 pSMB->TotalParameterCount = pSMB->ParameterCount;
6106 pSMB->TotalDataCount = pSMB->DataCount;
6107 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6108 pSMB->Reserved4 = 0;
6109 inc_rfc1001_len(pSMB, byte_count);
6110
6111 cifs_fill_unix_set_info(data_offset, args);
6112
6113 pSMB->ByteCount = cpu_to_le16(byte_count);
6114 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6115 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6116 if (rc)
6117 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6118
6119 cifs_buf_release(pSMB);
6120 if (rc == -EAGAIN)
6121 goto setPermsRetry;
6122 return rc;
6123 }
6124
6125 #ifdef CONFIG_CIFS_XATTR
6126 /*
6127 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6128 * function used by listxattr and getxattr type calls. When ea_name is set,
6129 * it looks for that attribute name and stuffs that value into the EAData
6130 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6131 * buffer. In both cases, the return value is either the length of the
6132 * resulting data or a negative error code. If EAData is a NULL pointer then
6133 * the data isn't copied to it, but the length is returned.
6134 */
6135 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)6136 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6137 const unsigned char *searchName, const unsigned char *ea_name,
6138 char *EAData, size_t buf_size,
6139 struct cifs_sb_info *cifs_sb)
6140 {
6141 /* BB assumes one setup word */
6142 TRANSACTION2_QPI_REQ *pSMB = NULL;
6143 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6144 int remap = cifs_remap(cifs_sb);
6145 struct nls_table *nls_codepage = cifs_sb->local_nls;
6146 int rc = 0;
6147 int bytes_returned;
6148 int list_len;
6149 struct fealist *ea_response_data;
6150 struct fea *temp_fea;
6151 char *temp_ptr;
6152 char *end_of_smb;
6153 __u16 params, byte_count, data_offset;
6154 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6155
6156 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6157 QAllEAsRetry:
6158 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6159 (void **) &pSMBr);
6160 if (rc)
6161 return rc;
6162
6163 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6164 list_len =
6165 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6166 PATH_MAX, nls_codepage, remap);
6167 list_len++; /* trailing null */
6168 list_len *= 2;
6169 } else { /* BB improve the check for buffer overruns BB */
6170 list_len = strnlen(searchName, PATH_MAX);
6171 list_len++; /* trailing null */
6172 strncpy(pSMB->FileName, searchName, list_len);
6173 }
6174
6175 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6176 pSMB->TotalDataCount = 0;
6177 pSMB->MaxParameterCount = cpu_to_le16(2);
6178 /* BB find exact max SMB PDU from sess structure BB */
6179 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6180 pSMB->MaxSetupCount = 0;
6181 pSMB->Reserved = 0;
6182 pSMB->Flags = 0;
6183 pSMB->Timeout = 0;
6184 pSMB->Reserved2 = 0;
6185 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6186 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6187 pSMB->DataCount = 0;
6188 pSMB->DataOffset = 0;
6189 pSMB->SetupCount = 1;
6190 pSMB->Reserved3 = 0;
6191 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6192 byte_count = params + 1 /* pad */ ;
6193 pSMB->TotalParameterCount = cpu_to_le16(params);
6194 pSMB->ParameterCount = pSMB->TotalParameterCount;
6195 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6196 pSMB->Reserved4 = 0;
6197 inc_rfc1001_len(pSMB, byte_count);
6198 pSMB->ByteCount = cpu_to_le16(byte_count);
6199
6200 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6201 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6202 if (rc) {
6203 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6204 goto QAllEAsOut;
6205 }
6206
6207
6208 /* BB also check enough total bytes returned */
6209 /* BB we need to improve the validity checking
6210 of these trans2 responses */
6211
6212 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6213 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6214 rc = -EIO; /* bad smb */
6215 goto QAllEAsOut;
6216 }
6217
6218 /* check that length of list is not more than bcc */
6219 /* check that each entry does not go beyond length
6220 of list */
6221 /* check that each element of each entry does not
6222 go beyond end of list */
6223 /* validate_trans2_offsets() */
6224 /* BB check if start of smb + data_offset > &bcc+ bcc */
6225
6226 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6227 ea_response_data = (struct fealist *)
6228 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6229
6230 list_len = le32_to_cpu(ea_response_data->list_len);
6231 cifs_dbg(FYI, "ea length %d\n", list_len);
6232 if (list_len <= 8) {
6233 cifs_dbg(FYI, "empty EA list returned from server\n");
6234 /* didn't find the named attribute */
6235 if (ea_name)
6236 rc = -ENODATA;
6237 goto QAllEAsOut;
6238 }
6239
6240 /* make sure list_len doesn't go past end of SMB */
6241 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6242 if ((char *)ea_response_data + list_len > end_of_smb) {
6243 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6244 rc = -EIO;
6245 goto QAllEAsOut;
6246 }
6247
6248 /* account for ea list len */
6249 list_len -= 4;
6250 temp_fea = ea_response_data->list;
6251 temp_ptr = (char *)temp_fea;
6252 while (list_len > 0) {
6253 unsigned int name_len;
6254 __u16 value_len;
6255
6256 list_len -= 4;
6257 temp_ptr += 4;
6258 /* make sure we can read name_len and value_len */
6259 if (list_len < 0) {
6260 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6261 rc = -EIO;
6262 goto QAllEAsOut;
6263 }
6264
6265 name_len = temp_fea->name_len;
6266 value_len = le16_to_cpu(temp_fea->value_len);
6267 list_len -= name_len + 1 + value_len;
6268 if (list_len < 0) {
6269 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6270 rc = -EIO;
6271 goto QAllEAsOut;
6272 }
6273
6274 if (ea_name) {
6275 if (ea_name_len == name_len &&
6276 memcmp(ea_name, temp_ptr, name_len) == 0) {
6277 temp_ptr += name_len + 1;
6278 rc = value_len;
6279 if (buf_size == 0)
6280 goto QAllEAsOut;
6281 if ((size_t)value_len > buf_size) {
6282 rc = -ERANGE;
6283 goto QAllEAsOut;
6284 }
6285 memcpy(EAData, temp_ptr, value_len);
6286 goto QAllEAsOut;
6287 }
6288 } else {
6289 /* account for prefix user. and trailing null */
6290 rc += (5 + 1 + name_len);
6291 if (rc < (int) buf_size) {
6292 memcpy(EAData, "user.", 5);
6293 EAData += 5;
6294 memcpy(EAData, temp_ptr, name_len);
6295 EAData += name_len;
6296 /* null terminate name */
6297 *EAData = 0;
6298 ++EAData;
6299 } else if (buf_size == 0) {
6300 /* skip copy - calc size only */
6301 } else {
6302 /* stop before overrun buffer */
6303 rc = -ERANGE;
6304 break;
6305 }
6306 }
6307 temp_ptr += name_len + 1 + value_len;
6308 temp_fea = (struct fea *)temp_ptr;
6309 }
6310
6311 /* didn't find the named attribute */
6312 if (ea_name)
6313 rc = -ENODATA;
6314
6315 QAllEAsOut:
6316 cifs_buf_release(pSMB);
6317 if (rc == -EAGAIN)
6318 goto QAllEAsRetry;
6319
6320 return (ssize_t)rc;
6321 }
6322
6323 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)6324 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6325 const char *fileName, const char *ea_name, const void *ea_value,
6326 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6327 struct cifs_sb_info *cifs_sb)
6328 {
6329 struct smb_com_transaction2_spi_req *pSMB = NULL;
6330 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6331 struct fealist *parm_data;
6332 int name_len;
6333 int rc = 0;
6334 int bytes_returned = 0;
6335 __u16 params, param_offset, byte_count, offset, count;
6336 int remap = cifs_remap(cifs_sb);
6337
6338 cifs_dbg(FYI, "In SetEA\n");
6339 SetEARetry:
6340 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6341 (void **) &pSMBr);
6342 if (rc)
6343 return rc;
6344
6345 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6346 name_len =
6347 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6348 PATH_MAX, nls_codepage, remap);
6349 name_len++; /* trailing null */
6350 name_len *= 2;
6351 } else { /* BB improve the check for buffer overruns BB */
6352 name_len = strnlen(fileName, PATH_MAX);
6353 name_len++; /* trailing null */
6354 strncpy(pSMB->FileName, fileName, name_len);
6355 }
6356
6357 params = 6 + name_len;
6358
6359 /* done calculating parms using name_len of file name,
6360 now use name_len to calculate length of ea name
6361 we are going to create in the inode xattrs */
6362 if (ea_name == NULL)
6363 name_len = 0;
6364 else
6365 name_len = strnlen(ea_name, 255);
6366
6367 count = sizeof(*parm_data) + ea_value_len + name_len;
6368 pSMB->MaxParameterCount = cpu_to_le16(2);
6369 /* BB find max SMB PDU from sess */
6370 pSMB->MaxDataCount = cpu_to_le16(1000);
6371 pSMB->MaxSetupCount = 0;
6372 pSMB->Reserved = 0;
6373 pSMB->Flags = 0;
6374 pSMB->Timeout = 0;
6375 pSMB->Reserved2 = 0;
6376 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6377 InformationLevel) - 4;
6378 offset = param_offset + params;
6379 pSMB->InformationLevel =
6380 cpu_to_le16(SMB_SET_FILE_EA);
6381
6382 parm_data = (void *)pSMB + offsetof(struct smb_hdr, Protocol) + offset;
6383 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6384 pSMB->DataOffset = cpu_to_le16(offset);
6385 pSMB->SetupCount = 1;
6386 pSMB->Reserved3 = 0;
6387 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6388 byte_count = 3 /* pad */ + params + count;
6389 pSMB->DataCount = cpu_to_le16(count);
6390 parm_data->list_len = cpu_to_le32(count);
6391 parm_data->list[0].EA_flags = 0;
6392 /* we checked above that name len is less than 255 */
6393 parm_data->list[0].name_len = (__u8)name_len;
6394 /* EA names are always ASCII */
6395 if (ea_name)
6396 strncpy(parm_data->list[0].name, ea_name, name_len);
6397 parm_data->list[0].name[name_len] = 0;
6398 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6399 /* caller ensures that ea_value_len is less than 64K but
6400 we need to ensure that it fits within the smb */
6401
6402 /*BB add length check to see if it would fit in
6403 negotiated SMB buffer size BB */
6404 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6405 if (ea_value_len)
6406 memcpy(parm_data->list[0].name+name_len+1,
6407 ea_value, ea_value_len);
6408
6409 pSMB->TotalDataCount = pSMB->DataCount;
6410 pSMB->ParameterCount = cpu_to_le16(params);
6411 pSMB->TotalParameterCount = pSMB->ParameterCount;
6412 pSMB->Reserved4 = 0;
6413 inc_rfc1001_len(pSMB, byte_count);
6414 pSMB->ByteCount = cpu_to_le16(byte_count);
6415 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6416 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6417 if (rc)
6418 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6419
6420 cifs_buf_release(pSMB);
6421
6422 if (rc == -EAGAIN)
6423 goto SetEARetry;
6424
6425 return rc;
6426 }
6427 #endif
6428
6429 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6430 /*
6431 * Years ago the kernel added a "dnotify" function for Samba server,
6432 * to allow network clients (such as Windows) to display updated
6433 * lists of files in directory listings automatically when
6434 * files are added by one user when another user has the
6435 * same directory open on their desktop. The Linux cifs kernel
6436 * client hooked into the kernel side of this interface for
6437 * the same reason, but ironically when the VFS moved from
6438 * "dnotify" to "inotify" it became harder to plug in Linux
6439 * network file system clients (the most obvious use case
6440 * for notify interfaces is when multiple users can update
6441 * the contents of the same directory - exactly what network
6442 * file systems can do) although the server (Samba) could
6443 * still use it. For the short term we leave the worker
6444 * function ifdeffed out (below) until inotify is fixed
6445 * in the VFS to make it easier to plug in network file
6446 * system clients. If inotify turns out to be permanently
6447 * incompatible for network fs clients, we could instead simply
6448 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6449 */
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)6450 int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6451 const int notify_subdirs, const __u16 netfid,
6452 __u32 filter, struct file *pfile, int multishot,
6453 const struct nls_table *nls_codepage)
6454 {
6455 int rc = 0;
6456 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6457 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6458 struct dir_notify_req *dnotify_req;
6459 int bytes_returned;
6460
6461 cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid);
6462 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6463 (void **) &pSMBr);
6464 if (rc)
6465 return rc;
6466
6467 pSMB->TotalParameterCount = 0 ;
6468 pSMB->TotalDataCount = 0;
6469 pSMB->MaxParameterCount = cpu_to_le32(2);
6470 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6471 pSMB->MaxSetupCount = 4;
6472 pSMB->Reserved = 0;
6473 pSMB->ParameterOffset = 0;
6474 pSMB->DataCount = 0;
6475 pSMB->DataOffset = 0;
6476 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6477 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6478 pSMB->ParameterCount = pSMB->TotalParameterCount;
6479 if (notify_subdirs)
6480 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6481 pSMB->Reserved2 = 0;
6482 pSMB->CompletionFilter = cpu_to_le32(filter);
6483 pSMB->Fid = netfid; /* file handle always le */
6484 pSMB->ByteCount = 0;
6485
6486 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6487 (struct smb_hdr *)pSMBr, &bytes_returned,
6488 CIFS_ASYNC_OP);
6489 if (rc) {
6490 cifs_dbg(FYI, "Error in Notify = %d\n", rc);
6491 } else {
6492 /* Add file to outstanding requests */
6493 /* BB change to kmem cache alloc */
6494 dnotify_req = kmalloc(
6495 sizeof(struct dir_notify_req),
6496 GFP_KERNEL);
6497 if (dnotify_req) {
6498 dnotify_req->Pid = pSMB->hdr.Pid;
6499 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6500 dnotify_req->Mid = pSMB->hdr.Mid;
6501 dnotify_req->Tid = pSMB->hdr.Tid;
6502 dnotify_req->Uid = pSMB->hdr.Uid;
6503 dnotify_req->netfid = netfid;
6504 dnotify_req->pfile = pfile;
6505 dnotify_req->filter = filter;
6506 dnotify_req->multishot = multishot;
6507 spin_lock(&GlobalMid_Lock);
6508 list_add_tail(&dnotify_req->lhead,
6509 &GlobalDnotifyReqList);
6510 spin_unlock(&GlobalMid_Lock);
6511 } else
6512 rc = -ENOMEM;
6513 }
6514 cifs_buf_release(pSMB);
6515 return rc;
6516 }
6517 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
6518