Blame view
fs/cifs/smb2pdu.c
121 KB
ec2e4523f CIFS: Add capabil... |
1 2 3 |
/* * fs/cifs/smb2pdu.c * |
2b80d049e Charge at least o... |
4 |
* Copyright (C) International Business Machines Corp., 2009, 2013 |
ec2e4523f CIFS: Add capabil... |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
* Etersoft, 2012 * Author(s): Steve French (sfrench@us.ibm.com) * Pavel Shilovsky (pshilovsky@samba.org) 2012 * * Contains the routines for constructing the SMB2 PDUs themselves * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */ /* Note that there are handle based routines which must be */ /* treated slightly differently for reconnection purposes since we never */ /* want to reuse a stale file handle and only the caller knows the file info */ #include <linux/fs.h> #include <linux/kernel.h> #include <linux/vfs.h> |
09a4707e7 CIFS: Add SMB2 su... |
34 |
#include <linux/task_io_accounting_ops.h> |
ec2e4523f CIFS: Add capabil... |
35 |
#include <linux/uaccess.h> |
c6e970a04 net: break includ... |
36 |
#include <linux/uuid.h> |
333191412 CIFS: Add SMB2 su... |
37 |
#include <linux/pagemap.h> |
ec2e4523f CIFS: Add capabil... |
38 39 40 41 42 43 44 45 46 47 |
#include <linux/xattr.h> #include "smb2pdu.h" #include "cifsglob.h" #include "cifsacl.h" #include "cifsproto.h" #include "smb2proto.h" #include "cifs_unicode.h" #include "cifs_debug.h" #include "ntlmssp.h" #include "smb2status.h" |
09a4707e7 CIFS: Add SMB2 su... |
48 |
#include "smb2glob.h" |
d324f08d6 CIFS: Add readdir... |
49 |
#include "cifspdu.h" |
ceb1b0b9b [SMB3] Fix sec=kr... |
50 |
#include "cifs_spnego.h" |
db223a590 CIFS: SMBD: Upper... |
51 |
#include "smbdirect.h" |
eccb4422c smb3: Add ftrace ... |
52 |
#include "trace.h" |
ec2e4523f CIFS: Add capabil... |
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
/* * The following table defines the expected "StructureSize" of SMB2 requests * in order by SMB2 command. This is similar to "wct" in SMB/CIFS requests. * * Note that commands are defined in smb2pdu.h in le16 but the array below is * indexed by command in host byte order. */ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { /* SMB2_NEGOTIATE */ 36, /* SMB2_SESSION_SETUP */ 25, /* SMB2_LOGOFF */ 4, /* SMB2_TREE_CONNECT */ 9, /* SMB2_TREE_DISCONNECT */ 4, /* SMB2_CREATE */ 57, /* SMB2_CLOSE */ 24, /* SMB2_FLUSH */ 24, /* SMB2_READ */ 49, /* SMB2_WRITE */ 49, /* SMB2_LOCK */ 48, /* SMB2_IOCTL */ 57, /* SMB2_CANCEL */ 4, /* SMB2_ECHO */ 4, /* SMB2_QUERY_DIRECTORY */ 33, /* SMB2_CHANGE_NOTIFY */ 32, /* SMB2_QUERY_INFO */ 41, /* SMB2_SET_INFO */ 33, /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */ }; |
730928c8f cifs: update smb2... |
82 |
int smb3_encryption_required(const struct cifs_tcon *tcon) |
7fb8986e7 CIFS: Add capabil... |
83 |
{ |
ae6f8dd4d CIFS: Allow to sw... |
84 85 |
if (!tcon) return 0; |
7fb8986e7 CIFS: Add capabil... |
86 87 88 |
if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) || (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)) return 1; |
ae6f8dd4d CIFS: Allow to sw... |
89 90 91 |
if (tcon->seal && (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) return 1; |
7fb8986e7 CIFS: Add capabil... |
92 93 |
return 0; } |
ec2e4523f CIFS: Add capabil... |
94 95 |
static void |
cb200bd62 CIFS: Separate SM... |
96 |
smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd, |
ec2e4523f CIFS: Add capabil... |
97 98 |
const struct cifs_tcon *tcon) { |
31473fc4f CIFS: Separate SM... |
99 100 101 |
shdr->ProtocolId = SMB2_PROTO_NUMBER; shdr->StructureSize = cpu_to_le16(64); shdr->Command = smb2_cmd; |
7d414f396 cifs: Limit the o... |
102 103 104 105 106 |
if (tcon && tcon->ses && tcon->ses->server) { struct TCP_Server_Info *server = tcon->ses->server; spin_lock(&server->req_lock); /* Request up to 2 credits but don't go over the limit. */ |
141891f47 SMB3: Add mount p... |
107 |
if (server->credits >= server->max_credits) |
31473fc4f CIFS: Separate SM... |
108 |
shdr->CreditRequest = cpu_to_le16(0); |
7d414f396 cifs: Limit the o... |
109 |
else |
31473fc4f CIFS: Separate SM... |
110 |
shdr->CreditRequest = cpu_to_le16( |
141891f47 SMB3: Add mount p... |
111 |
min_t(int, server->max_credits - |
7d414f396 cifs: Limit the o... |
112 113 114 |
server->credits, 2)); spin_unlock(&server->req_lock); } else { |
31473fc4f CIFS: Separate SM... |
115 |
shdr->CreditRequest = cpu_to_le16(2); |
7d414f396 cifs: Limit the o... |
116 |
} |
31473fc4f CIFS: Separate SM... |
117 |
shdr->ProcessId = cpu_to_le32((__u16)current->tgid); |
ec2e4523f CIFS: Add capabil... |
118 119 120 |
if (!tcon) goto out; |
2b80d049e Charge at least o... |
121 122 |
/* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ |
1dc92c450 [cifs] fix null p... |
123 |
if ((tcon->ses) && (tcon->ses->server) && |
84ceeb962 [CIFS] fix static... |
124 |
(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) |
31473fc4f CIFS: Separate SM... |
125 |
shdr->CreditCharge = cpu_to_le16(1); |
2b80d049e Charge at least o... |
126 |
/* else CreditCharge MBZ */ |
31473fc4f CIFS: Separate SM... |
127 |
shdr->TreeId = tcon->tid; |
ec2e4523f CIFS: Add capabil... |
128 129 |
/* Uid is not converted */ if (tcon->ses) |
31473fc4f CIFS: Separate SM... |
130 |
shdr->SessionId = tcon->ses->Suid; |
f87ab88b4 [CIFS] Do not set... |
131 132 133 134 135 136 137 138 139 140 141 142 |
/* * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have * to pass the path on the Open SMB prefixed by \\server\share. * Not sure when we would need to do the augmented path (if ever) and * setting this flag breaks the SMB2 open operation since it is * illegal to send an empty path name (without \\server\share prefix) * when the DFS flag is set in the SMB open header. We could * consider setting the flag on all operations other than open * but it is safer to net set it for now. */ /* if (tcon->share_flags & SHI1005_FLAGS_DFS) |
31473fc4f CIFS: Separate SM... |
143 |
shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ |
f87ab88b4 [CIFS] Do not set... |
144 |
|
7fb8986e7 CIFS: Add capabil... |
145 |
if (tcon->ses && tcon->ses->server && tcon->ses->server->sign && |
5a77e75fe smb3: rename encr... |
146 |
!smb3_encryption_required(tcon)) |
31473fc4f CIFS: Separate SM... |
147 |
shdr->Flags |= SMB2_FLAGS_SIGNED; |
ec2e4523f CIFS: Add capabil... |
148 |
out: |
ec2e4523f CIFS: Add capabil... |
149 150 151 152 153 154 |
return; } static int smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) { |
7ffbe6557 cifs: Fix infinit... |
155 |
int rc; |
aa24d1e96 CIFS: Process rec... |
156 157 158 159 160 161 162 163 164 165 |
struct nls_table *nls_codepage; struct cifs_ses *ses; struct TCP_Server_Info *server; /* * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so * check for tcp and smb session status done differently * for those three - in the calling routine. */ if (tcon == NULL) |
7ffbe6557 cifs: Fix infinit... |
166 |
return 0; |
aa24d1e96 CIFS: Process rec... |
167 168 |
if (smb2_command == SMB2_TREE_CONNECT) |
7ffbe6557 cifs: Fix infinit... |
169 |
return 0; |
aa24d1e96 CIFS: Process rec... |
170 171 172 173 174 175 176 177 178 179 |
if (tcon->tidStatus == CifsExiting) { /* * only tree disconnect, open, and write, * (and ulogoff which does not have tcon) * are allowed as we start force umount. */ if ((smb2_command != SMB2_WRITE) && (smb2_command != SMB2_CREATE) && (smb2_command != SMB2_TREE_DISCONNECT)) { |
f96637be0 [CIFS] cifs: Rena... |
180 181 182 |
cifs_dbg(FYI, "can not send cmd %d while umounting ", smb2_command); |
aa24d1e96 CIFS: Process rec... |
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
return -ENODEV; } } if ((!tcon->ses) || (tcon->ses->status == CifsExiting) || (!tcon->ses->server)) return -EIO; ses = tcon->ses; server = ses->server; /* * Give demultiplex thread up to 10 seconds to reconnect, should be * greater than cifs socket timeout which is 7 seconds */ while (server->tcpStatus == CifsNeedReconnect) { /* * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE * here since they are implicitly done when session drops. */ switch (smb2_command) { /* * BB Should we keep oplock break and add flush to exceptions? */ case SMB2_TREE_DISCONNECT: case SMB2_CANCEL: case SMB2_CLOSE: case SMB2_OPLOCK_BREAK: return -EAGAIN; } |
7ffbe6557 cifs: Fix infinit... |
212 213 214 215 216 217 218 219 220 |
rc = wait_event_interruptible_timeout(server->response_q, (server->tcpStatus != CifsNeedReconnect), 10 * HZ); if (rc < 0) { cifs_dbg(FYI, "%s: aborting reconnect due to a received" " signal by the process ", __func__); return -ERESTARTSYS; } |
aa24d1e96 CIFS: Process rec... |
221 222 223 224 225 226 227 228 229 230 231 |
/* are we still trying to reconnect? */ if (server->tcpStatus != CifsNeedReconnect) break; /* * on "soft" mounts we wait once. Hard mounts keep * retrying until process is killed or server comes * back on-line */ if (!tcon->retry) { |
f96637be0 [CIFS] cifs: Rena... |
232 233 |
cifs_dbg(FYI, "gave up waiting on reconnect in smb_init "); |
aa24d1e96 CIFS: Process rec... |
234 235 236 237 238 |
return -EHOSTDOWN; } } if (!tcon->ses->need_reconnect && !tcon->need_reconnect) |
7ffbe6557 cifs: Fix infinit... |
239 |
return 0; |
aa24d1e96 CIFS: Process rec... |
240 241 242 243 244 245 246 247 |
nls_codepage = load_nls_default(); /* * need to prevent multiple threads trying to simultaneously reconnect * the same SMB session */ mutex_lock(&tcon->ses->session_mutex); |
76e752701 cifs: Check for t... |
248 249 250 251 252 253 254 255 256 257 258 |
/* * Recheck after acquire mutex. If another thread is negotiating * and the server never sends an answer the socket will be closed * and tcpStatus set to reconnect. */ if (server->tcpStatus == CifsNeedReconnect) { rc = -EHOSTDOWN; mutex_unlock(&tcon->ses->session_mutex); goto out; } |
aa24d1e96 CIFS: Process rec... |
259 260 261 262 263 264 265 266 267 268 |
rc = cifs_negotiate_protocol(0, tcon->ses); if (!rc && tcon->ses->need_reconnect) rc = cifs_setup_session(0, tcon->ses, nls_codepage); if (rc || !tcon->need_reconnect) { mutex_unlock(&tcon->ses->session_mutex); goto out; } cifs_mark_open_files_invalid(tcon); |
96a988ffe CIFS: Fix a possi... |
269 270 |
if (tcon->use_persistent) tcon->need_reopen_files = true; |
52ace1ef1 fs/cifs: reopen p... |
271 |
|
aa24d1e96 CIFS: Process rec... |
272 273 |
rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage); mutex_unlock(&tcon->ses->session_mutex); |
52ace1ef1 fs/cifs: reopen p... |
274 |
|
f96637be0 [CIFS] cifs: Rena... |
275 276 |
cifs_dbg(FYI, "reconnect tcon rc = %d ", rc); |
c318e6c26 SMB3: Log at leas... |
277 278 279 280 |
if (rc) { /* If sess reconnected but tcon didn't, something strange ... */ printk_once(KERN_WARNING "reconnect tcon failed rc = %d ", rc); |
aa24d1e96 CIFS: Process rec... |
281 |
goto out; |
c318e6c26 SMB3: Log at leas... |
282 |
} |
96a988ffe CIFS: Fix a possi... |
283 284 285 |
if (smb2_command != SMB2_INTERNAL_CMD) queue_delayed_work(cifsiod_wq, &server->reconnect, 0); |
aa24d1e96 CIFS: Process rec... |
286 |
atomic_inc(&tconInfoReconnectCount); |
aa24d1e96 CIFS: Process rec... |
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
out: /* * Check if handle based operation so we know whether we can continue * or not without returning to caller to reset file handle. */ /* * BB Is flush done by server on drop of tcp session? Should we special * case it and skip above? */ switch (smb2_command) { case SMB2_FLUSH: case SMB2_READ: case SMB2_WRITE: case SMB2_LOCK: case SMB2_IOCTL: case SMB2_QUERY_DIRECTORY: case SMB2_CHANGE_NOTIFY: case SMB2_QUERY_INFO: case SMB2_SET_INFO: |
4772c7959 CIFS: Fix missing... |
306 |
rc = -EAGAIN; |
aa24d1e96 CIFS: Process rec... |
307 308 |
} unload_nls(nls_codepage); |
ec2e4523f CIFS: Add capabil... |
309 310 |
return rc; } |
cb200bd62 CIFS: Separate SM... |
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
static void fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf, unsigned int *total_len) { struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf; /* lookup word count ie StructureSize from table */ __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)]; /* * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of * largest operations (Create) */ memset(buf, 0, 256); smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon); spdu->StructureSize2 = cpu_to_le16(parmsize); *total_len = parmsize + sizeof(struct smb2_sync_hdr); } |
ec2e4523f CIFS: Add capabil... |
330 331 332 |
/* * Allocate and return pointer to an SMB request hdr, and set basic * SMB information in the SMB header. If the return code is zero, this |
305428acf cifs: remove smal... |
333 |
* function must have filled in request_buf pointer. |
ec2e4523f CIFS: Add capabil... |
334 335 |
*/ static int |
305428acf cifs: remove smal... |
336 337 |
smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, void **request_buf, unsigned int *total_len) |
ec2e4523f CIFS: Add capabil... |
338 |
{ |
cb200bd62 CIFS: Separate SM... |
339 |
int rc; |
ec2e4523f CIFS: Add capabil... |
340 341 342 343 344 345 |
rc = smb2_reconnect(smb2_command, tcon); if (rc) return rc; /* BB eventually switch this to SMB2 specific small buf size */ |
f46ecbd97 cifs: Fix slab-ou... |
346 347 348 349 |
if (smb2_command == SMB2_SET_INFO) *request_buf = cifs_buf_get(); else *request_buf = cifs_small_buf_get(); |
ec2e4523f CIFS: Add capabil... |
350 351 352 353 |
if (*request_buf == NULL) { /* BB should we add a retry in here if not a writepage? */ return -ENOMEM; } |
305428acf cifs: remove smal... |
354 355 356 |
fill_small_buf(smb2_command, tcon, (struct smb2_sync_hdr *)(*request_buf), total_len); |
ec2e4523f CIFS: Add capabil... |
357 358 |
if (tcon != NULL) { |
ec2e4523f CIFS: Add capabil... |
359 360 |
uint16_t com_code = le16_to_cpu(smb2_command); cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]); |
ec2e4523f CIFS: Add capabil... |
361 362 363 364 365 |
cifs_stats_inc(&tcon->num_smbs_sent); } return rc; } |
0fdfef9aa smb3: simplify co... |
366 |
|
13cacea7b cifs: remove rfc1... |
367 368 |
/* offset is sizeof smb2_negotiate_req but rounded up to 8 bytes */ #define OFFSET_OF_NEG_CONTEXT 0x68 /* sizeof(struct smb2_negotiate_req) */ |
ebb3a9d4b Update negotiate ... |
369 370 371 372 |
#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1) #define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2) |
fcef0db6d smb3: add support... |
373 |
#define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100) |
ebb3a9d4b Update negotiate ... |
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
static void build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt) { pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES; pneg_ctxt->DataLength = cpu_to_le16(38); pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1); pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE); get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE); pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512; } static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt) { pneg_ctxt->ContextType = SMB2_ENCRYPTION_CAPABILITIES; |
23657ad73 SMB3: Fix 3.11 en... |
390 391 392 393 |
pneg_ctxt->DataLength = cpu_to_le16(4); /* Cipher Count + le16 cipher */ pneg_ctxt->CipherCount = cpu_to_le16(1); /* pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_GCM;*/ /* not supported yet */ pneg_ctxt->Ciphers[0] = SMB2_ENCRYPTION_AES128_CCM; |
ebb3a9d4b Update negotiate ... |
394 395 396 |
} static void |
fcef0db6d smb3: add support... |
397 398 399 400 401 402 403 |
build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt) { pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE; pneg_ctxt->DataLength = cpu_to_le16(POSIX_CTXT_DATA_LEN); } static void |
13cacea7b cifs: remove rfc1... |
404 405 |
assemble_neg_contexts(struct smb2_negotiate_req *req, unsigned int *total_len) |
ebb3a9d4b Update negotiate ... |
406 |
{ |
13cacea7b cifs: remove rfc1... |
407 |
char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT; |
fcef0db6d smb3: add support... |
408 |
unsigned int ctxt_len; |
ebb3a9d4b Update negotiate ... |
409 |
|
fcef0db6d smb3: add support... |
410 |
*total_len += 2; /* Add 2 due to round to 8 byte boundary for 1st ctxt */ |
ebb3a9d4b Update negotiate ... |
411 |
build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); |
fcef0db6d smb3: add support... |
412 413 414 |
ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8; *total_len += ctxt_len; pneg_ctxt += ctxt_len; |
13cacea7b cifs: remove rfc1... |
415 |
|
ebb3a9d4b Update negotiate ... |
416 |
build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); |
fcef0db6d smb3: add support... |
417 418 419 420 421 422 |
ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_encryption_neg_context), 8) * 8; *total_len += ctxt_len; pneg_ctxt += ctxt_len; build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); *total_len += sizeof(struct smb2_posix_neg_context); |
13cacea7b cifs: remove rfc1... |
423 |
|
fcef0db6d smb3: add support... |
424 425 |
req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT); req->NegotiateContextCount = cpu_to_le16(3); |
ebb3a9d4b Update negotiate ... |
426 |
} |
5100d8a3f SMB311: Improve c... |
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 |
static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) { unsigned int len = le16_to_cpu(ctxt->DataLength); /* If invalid preauth context warn but use what we requested, SHA-512 */ if (len < MIN_PREAUTH_CTXT_DATA_LEN) { printk_once(KERN_WARNING "server sent bad preauth context "); return; } if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1) printk_once(KERN_WARNING "illegal SMB3 hash algorithm count "); if (ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512) printk_once(KERN_WARNING "unknown SMB3 hash algorithm "); } static int decode_encrypt_ctx(struct TCP_Server_Info *server, struct smb2_encryption_neg_context *ctxt) { unsigned int len = le16_to_cpu(ctxt->DataLength); cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d ", len); if (len < MIN_ENCRYPT_CTXT_DATA_LEN) { printk_once(KERN_WARNING "server sent bad crypto ctxt len "); return -EINVAL; } if (le16_to_cpu(ctxt->CipherCount) != 1) { printk_once(KERN_WARNING "illegal SMB3.11 cipher count "); return -EINVAL; } cifs_dbg(FYI, "SMB311 cipher type:%d ", le16_to_cpu(ctxt->Ciphers[0])); if ((ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_CCM) && (ctxt->Ciphers[0] != SMB2_ENCRYPTION_AES128_GCM)) { printk_once(KERN_WARNING "invalid SMB3.11 cipher returned "); return -EINVAL; } server->cipher_type = ctxt->Ciphers[0]; |
23657ad73 SMB3: Fix 3.11 en... |
473 |
server->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION; |
5100d8a3f SMB311: Improve c... |
474 475 476 477 |
return 0; } static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp, |
977b61704 cifs: remove rfc1... |
478 479 |
struct TCP_Server_Info *server, unsigned int len_of_smb) |
5100d8a3f SMB311: Improve c... |
480 481 482 483 |
{ struct smb2_neg_context *pctx; unsigned int offset = le32_to_cpu(rsp->NegotiateContextOffset); unsigned int ctxt_cnt = le16_to_cpu(rsp->NegotiateContextCount); |
5100d8a3f SMB311: Improve c... |
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
unsigned int len_of_ctxts, i; int rc = 0; cifs_dbg(FYI, "decoding %d negotiate contexts ", ctxt_cnt); if (len_of_smb <= offset) { cifs_dbg(VFS, "Invalid response: negotiate context offset "); return -EINVAL; } len_of_ctxts = len_of_smb - offset; for (i = 0; i < ctxt_cnt; i++) { int clen; /* check that offset is not beyond end of SMB */ if (len_of_ctxts == 0) break; if (len_of_ctxts < sizeof(struct smb2_neg_context)) break; |
1fc6ad2f1 cifs: remove head... |
505 |
pctx = (struct smb2_neg_context *)(offset + (char *)rsp); |
5100d8a3f SMB311: Improve c... |
506 507 508 509 510 511 512 513 514 515 |
clen = le16_to_cpu(pctx->DataLength); if (clen > len_of_ctxts) break; if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) decode_preauth_context( (struct smb2_preauth_neg_context *)pctx); else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) rc = decode_encrypt_ctx(server, (struct smb2_encryption_neg_context *)pctx); |
fcef0db6d smb3: add support... |
516 517 |
else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) server->posix_ext_supported = true; |
5100d8a3f SMB311: Improve c... |
518 519 520 521 522 523 524 525 526 527 528 529 530 531 |
else cifs_dbg(VFS, "unknown negcontext of type %d ignored ", le16_to_cpu(pctx->ContextType)); if (rc) break; /* offsets must be 8 byte aligned */ clen = (clen + 7) & ~0x7; offset += clen + sizeof(struct smb2_neg_context); len_of_ctxts -= clen; } return rc; } |
ce558b0e1 smb3: Add posix c... |
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
static struct create_posix * create_posix_buf(umode_t mode) { struct create_posix *buf; buf = kzalloc(sizeof(struct create_posix), GFP_KERNEL); if (!buf) return NULL; buf->ccontext.DataOffset = cpu_to_le16(offsetof(struct create_posix, Mode)); buf->ccontext.DataLength = cpu_to_le32(4); buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct create_posix, Name)); buf->ccontext.NameLength = cpu_to_le16(16); /* SMB2_CREATE_TAG_POSIX is "0x93AD25509CB411E7B42383DE968BCD7C" */ buf->Name[0] = 0x93; buf->Name[1] = 0xAD; buf->Name[2] = 0x25; buf->Name[3] = 0x50; buf->Name[4] = 0x9C; buf->Name[5] = 0xB4; buf->Name[6] = 0x11; buf->Name[7] = 0xE7; buf->Name[8] = 0xB4; buf->Name[9] = 0x23; buf->Name[10] = 0x83; buf->Name[11] = 0xDE; buf->Name[12] = 0x96; buf->Name[13] = 0x8B; buf->Name[14] = 0xCD; buf->Name[15] = 0x7C; buf->Mode = cpu_to_le32(mode); cifs_dbg(FYI, "mode on posix create 0%o", mode); return buf; } static int add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) { struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; iov[num].iov_base = create_posix_buf(mode); if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = sizeof(struct create_posix); if (!req->CreateContextsOffset) req->CreateContextsOffset = cpu_to_le32( sizeof(struct smb2_create_req) + iov[num - 1].iov_len); le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_posix)); *num_iovec = num + 1; return 0; } |
ebb3a9d4b Update negotiate ... |
589 |
|
ec2e4523f CIFS: Add capabil... |
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 |
/* * * SMB2 Worker functions follow: * * The general structure of the worker functions is: * 1) Call smb2_init (assembles SMB2 header) * 2) Initialize SMB2 command specific fields in fixed length area of SMB * 3) Call smb_sendrcv2 (sends request on socket and waits for response) * 4) Decode SMB2 command specific fields in the fixed length area * 5) Decode variable length data area (if any for this SMB2 command type) * 6) Call free smb buffer * 7) return * */ int SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) { |
40eff45b5 cifs: remove smb2... |
608 |
struct smb_rqst rqst; |
ec2e4523f CIFS: Add capabil... |
609 610 611 |
struct smb2_negotiate_req *req; struct smb2_negotiate_rsp *rsp; struct kvec iov[1]; |
da502f7df CIFS: Make SendRe... |
612 |
struct kvec rsp_iov; |
ec2e4523f CIFS: Add capabil... |
613 614 |
int rc = 0; int resp_buftype; |
3534b8508 cifs: throw a war... |
615 |
struct TCP_Server_Info *server = ses->server; |
ec2e4523f CIFS: Add capabil... |
616 617 618 |
int blob_offset, blob_length; char *security_blob; int flags = CIFS_NEG_OP; |
13cacea7b cifs: remove rfc1... |
619 |
unsigned int total_len; |
ec2e4523f CIFS: Add capabil... |
620 |
|
f96637be0 [CIFS] cifs: Rena... |
621 622 |
cifs_dbg(FYI, "Negotiate protocol "); |
ec2e4523f CIFS: Add capabil... |
623 |
|
3534b8508 cifs: throw a war... |
624 625 626 627 |
if (!server) { WARN(1, "%s: server is NULL! ", __func__); return -EIO; |
ec2e4523f CIFS: Add capabil... |
628 |
} |
13cacea7b cifs: remove rfc1... |
629 |
rc = smb2_plain_req_init(SMB2_NEGOTIATE, NULL, (void **) &req, &total_len); |
ec2e4523f CIFS: Add capabil... |
630 631 |
if (rc) return rc; |
13cacea7b cifs: remove rfc1... |
632 |
req->sync_hdr.SessionId = 0; |
0fdfef9aa smb3: simplify co... |
633 |
|
8bd68c6e4 CIFS: implement v... |
634 635 |
memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE); |
ec2e4523f CIFS: Add capabil... |
636 |
|
9764c02fc SMB3: Add support... |
637 638 639 640 641 |
if (strcmp(ses->server->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { req->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); req->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); req->DialectCount = cpu_to_le16(2); |
13cacea7b cifs: remove rfc1... |
642 |
total_len += 4; |
9764c02fc SMB3: Add support... |
643 644 645 646 647 648 |
} else if (strcmp(ses->server->vals->version_string, SMBDEFAULT_VERSION_STRING) == 0) { req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); req->DialectCount = cpu_to_le16(3); |
13cacea7b cifs: remove rfc1... |
649 |
total_len += 6; |
9764c02fc SMB3: Add support... |
650 651 652 653 |
} else { /* otherwise send specific dialect */ req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); req->DialectCount = cpu_to_le16(1); |
13cacea7b cifs: remove rfc1... |
654 |
total_len += 2; |
9764c02fc SMB3: Add support... |
655 |
} |
ec2e4523f CIFS: Add capabil... |
656 657 |
/* only one of SMB2 signing flags may be set in SMB2 request */ |
38d77c50b cifs: track the e... |
658 |
if (ses->sign) |
9cd2e62c4 Fix endian error ... |
659 |
req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED); |
38d77c50b cifs: track the e... |
660 |
else if (global_secflags & CIFSSEC_MAY_SIGN) |
9cd2e62c4 Fix endian error ... |
661 |
req->SecurityMode = cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED); |
38d77c50b cifs: track the e... |
662 663 |
else req->SecurityMode = 0; |
ec2e4523f CIFS: Add capabil... |
664 |
|
e4aa25e78 [CIFS] Fix SMB2 n... |
665 |
req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); |
ec2e4523f CIFS: Add capabil... |
666 |
|
3c5f9be10 Do not send Clien... |
667 668 669 |
/* ClientGUID must be zero for SMB2.02 dialect */ if (ses->server->vals->protocol_id == SMB20_PROT_ID) memset(req->ClientGUID, 0, SMB2_CLIENT_GUID_SIZE); |
ebb3a9d4b Update negotiate ... |
670 |
else { |
3c5f9be10 Do not send Clien... |
671 672 |
memcpy(req->ClientGUID, server->client_guid, SMB2_CLIENT_GUID_SIZE); |
ebb3a9d4b Update negotiate ... |
673 |
if (ses->server->vals->protocol_id == SMB311_PROT_ID) |
13cacea7b cifs: remove rfc1... |
674 |
assemble_neg_contexts(req, &total_len); |
ebb3a9d4b Update negotiate ... |
675 |
} |
ec2e4523f CIFS: Add capabil... |
676 |
iov[0].iov_base = (char *)req; |
13cacea7b cifs: remove rfc1... |
677 |
iov[0].iov_len = total_len; |
ec2e4523f CIFS: Add capabil... |
678 |
|
40eff45b5 cifs: remove smb2... |
679 680 681 682 683 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
684 685 |
cifs_small_buf_release(req); rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base; |
ec2e4523f CIFS: Add capabil... |
686 687 688 689 |
/* * No tcon so can't do * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); */ |
7e682f766 Fix warning messa... |
690 691 |
if (rc == -EOPNOTSUPP) { cifs_dbg(VFS, "Dialect not supported by server. Consider " |
9764c02fc SMB3: Add support... |
692 |
"specifying vers=1.0 or vers=2.0 on mount for accessing" |
7e682f766 Fix warning messa... |
693 694 695 696 |
" older servers "); goto neg_exit; } else if (rc != 0) |
ec2e4523f CIFS: Add capabil... |
697 |
goto neg_exit; |
9764c02fc SMB3: Add support... |
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 |
if (strcmp(ses->server->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { cifs_dbg(VFS, "SMB2 dialect returned but not requested "); return -EIO; } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { cifs_dbg(VFS, "SMB2.1 dialect returned but not requested "); return -EIO; } } else if (strcmp(ses->server->vals->version_string, SMBDEFAULT_VERSION_STRING) == 0) { if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) { cifs_dbg(VFS, "SMB2 dialect returned but not requested "); return -EIO; } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { /* ops set to 3.0 by default for default so update */ ses->server->ops = &smb21_operations; } |
590d08d3d SMB3: Fix endian ... |
722 723 |
} else if (le16_to_cpu(rsp->DialectRevision) != ses->server->vals->protocol_id) { |
9764c02fc SMB3: Add support... |
724 725 726 |
/* if requested single dialect ensure returned dialect matched */ cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested ", |
590d08d3d SMB3: Fix endian ... |
727 |
le16_to_cpu(rsp->DialectRevision)); |
9764c02fc SMB3: Add support... |
728 729 |
return -EIO; } |
f96637be0 [CIFS] cifs: Rena... |
730 731 |
cifs_dbg(FYI, "mode 0x%x ", rsp->SecurityMode); |
ec2e4523f CIFS: Add capabil... |
732 |
|
e4aa25e78 [CIFS] Fix SMB2 n... |
733 |
if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) |
f96637be0 [CIFS] cifs: Rena... |
734 735 |
cifs_dbg(FYI, "negotiated smb2.0 dialect "); |
e4aa25e78 [CIFS] Fix SMB2 n... |
736 |
else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) |
f96637be0 [CIFS] cifs: Rena... |
737 738 |
cifs_dbg(FYI, "negotiated smb2.1 dialect "); |
e4aa25e78 [CIFS] Fix SMB2 n... |
739 |
else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID)) |
f96637be0 [CIFS] cifs: Rena... |
740 741 |
cifs_dbg(FYI, "negotiated smb3.0 dialect "); |
20b6d8b42 Add SMB3.02 diale... |
742 743 744 |
else if (rsp->DialectRevision == cpu_to_le16(SMB302_PROT_ID)) cifs_dbg(FYI, "negotiated smb3.02 dialect "); |
5f7fbf733 Allow parsing ver... |
745 746 747 |
else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) cifs_dbg(FYI, "negotiated smb3.1.1 dialect "); |
ec2e4523f CIFS: Add capabil... |
748 |
else { |
f799d6234 Make dialect nego... |
749 750 |
cifs_dbg(VFS, "Illegal dialect returned by server 0x%x ", |
f96637be0 [CIFS] cifs: Rena... |
751 |
le16_to_cpu(rsp->DialectRevision)); |
ec2e4523f CIFS: Add capabil... |
752 753 754 755 |
rc = -EIO; goto neg_exit; } server->dialect = le16_to_cpu(rsp->DialectRevision); |
8bd68c6e4 CIFS: implement v... |
756 757 758 759 760 761 762 |
/* * Keep a copy of the hash after negprot. This hash will be * the starting hash value for all sessions made from this * server. */ memcpy(server->preauth_sha_hash, ses->preauth_sha_hash, SMB2_PREAUTH_HASH_SIZE); |
0fdfef9aa smb3: simplify co... |
763 |
|
e598d1d8f cifs: track the f... |
764 765 |
/* SMB2 only has an extended negflavor */ server->negflavor = CIFS_NEGFLAVOR_EXTENDED; |
2365c4eaf CIFS: Fix too big... |
766 767 768 |
/* set it to the maximum buffer size value we can send with 1 credit */ server->maxBuf = min_t(unsigned int, le32_to_cpu(rsp->MaxTransactSize), SMB2_MAX_BUFFER_SIZE); |
ec2e4523f CIFS: Add capabil... |
769 770 |
server->max_read = le32_to_cpu(rsp->MaxReadSize); server->max_write = le32_to_cpu(rsp->MaxWriteSize); |
ec2e4523f CIFS: Add capabil... |
771 |
server->sec_mode = le16_to_cpu(rsp->SecurityMode); |
07108d0e7 cifs: Add minor d... |
772 773 774 775 |
if ((server->sec_mode & SMB2_SEC_MODE_FLAGS_ALL) != server->sec_mode) cifs_dbg(FYI, "Server returned unexpected security mode 0x%x ", server->sec_mode); |
ec2e4523f CIFS: Add capabil... |
776 |
server->capabilities = le32_to_cpu(rsp->Capabilities); |
29e20f9c6 CIFS: Make CAP_* ... |
777 778 |
/* Internal types */ server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES; |
ec2e4523f CIFS: Add capabil... |
779 780 |
security_blob = smb2_get_data_area_len(&blob_offset, &blob_length, |
49f466bdb cifs: remove stru... |
781 |
(struct smb2_sync_hdr *)rsp); |
5d875cc92 When server doesn... |
782 783 784 785 786 787 788 |
/* * See MS-SMB2 section 2.2.4: if no blob, client picks default which * for us will be * ses->sectype = RawNTLMSSP; * but for time being this is our only auth choice so doesn't matter. * We just found a server which sets blob length to zero expecting raw. */ |
67dbea2ce CIFS: Fix SMB3 mo... |
789 |
if (blob_length == 0) { |
5d875cc92 When server doesn... |
790 791 |
cifs_dbg(FYI, "missing security blob on negprot "); |
67dbea2ce CIFS: Fix SMB3 mo... |
792 793 |
server->sec_ntlmssp = true; } |
3c1bf7e48 CIFS: Enable sign... |
794 |
|
38d77c50b cifs: track the e... |
795 |
rc = cifs_enable_signing(server, ses->sign); |
9ddec5613 cifs: move handli... |
796 797 |
if (rc) goto neg_exit; |
ceb1b0b9b [SMB3] Fix sec=kr... |
798 |
if (blob_length) { |
ebdd207e2 decode_negTokenIn... |
799 |
rc = decode_negTokenInit(security_blob, blob_length, server); |
ceb1b0b9b [SMB3] Fix sec=kr... |
800 801 802 803 |
if (rc == 1) rc = 0; else if (rc == 0) rc = -EIO; |
ec2e4523f CIFS: Add capabil... |
804 |
} |
5100d8a3f SMB311: Improve c... |
805 |
|
5100d8a3f SMB311: Improve c... |
806 807 |
if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) { if (rsp->NegotiateContextCount) |
977b61704 cifs: remove rfc1... |
808 809 |
rc = smb311_decode_neg_context(rsp, server, rsp_iov.iov_len); |
5100d8a3f SMB311: Improve c... |
810 811 812 813 |
else cifs_dbg(VFS, "Missing expected negotiate contexts "); } |
ec2e4523f CIFS: Add capabil... |
814 815 816 817 |
neg_exit: free_rsp_buf(resp_buftype, rsp); return rc; } |
5478f9ba9 CIFS: Add session... |
818 |
|
ff1c038ad Check SMB3 dialec... |
819 820 |
int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) { |
2796d303e cifs: Allocate va... |
821 822 |
int rc; struct validate_negotiate_info_req *pneg_inbuf; |
fe83bebc0 SMB: fix leak of ... |
823 |
struct validate_negotiate_info_rsp *pneg_rsp = NULL; |
ff1c038ad Check SMB3 dialec... |
824 |
u32 rsplen; |
9764c02fc SMB3: Add support... |
825 |
u32 inbuflen; /* max of 4 dialects */ |
ff1c038ad Check SMB3 dialec... |
826 827 828 |
cifs_dbg(FYI, "validate negotiate "); |
8bd68c6e4 CIFS: implement v... |
829 830 831 |
/* In SMB3.11 preauth integrity supersedes validate negotiate */ if (tcon->ses->server->dialect == SMB311_PROT_ID) return 0; |
ff1c038ad Check SMB3 dialec... |
832 833 |
/* * validation ioctl must be signed, so no point sending this if we |
0603c96f3 SMB: Validate neg... |
834 835 |
* can not sign it (ie are not known user). Even if signing is not * required (enabled but not negotiated), in those cases we selectively |
ff1c038ad Check SMB3 dialec... |
836 |
* sign just this, the first and only signed request on a connection. |
0603c96f3 SMB: Validate neg... |
837 |
* Having validation of negotiate info helps reduce attack vectors. |
ff1c038ad Check SMB3 dialec... |
838 |
*/ |
0603c96f3 SMB: Validate neg... |
839 |
if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) |
ff1c038ad Check SMB3 dialec... |
840 |
return 0; /* validation requires signing */ |
0603c96f3 SMB: Validate neg... |
841 842 843 844 845 846 847 848 849 |
if (tcon->ses->user_name == NULL) { cifs_dbg(FYI, "Can't validate negotiate: null user mount "); return 0; /* validation requires signing */ } if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server "); |
2796d303e cifs: Allocate va... |
850 851 852 853 854 |
pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); if (!pneg_inbuf) return -ENOMEM; pneg_inbuf->Capabilities = |
ff1c038ad Check SMB3 dialec... |
855 |
cpu_to_le32(tcon->ses->server->vals->req_capabilities); |
2796d303e cifs: Allocate va... |
856 |
memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid, |
39552ea81 cifs: Set client ... |
857 |
SMB2_CLIENT_GUID_SIZE); |
ff1c038ad Check SMB3 dialec... |
858 859 |
if (tcon->ses->sign) |
2796d303e cifs: Allocate va... |
860 |
pneg_inbuf->SecurityMode = |
ff1c038ad Check SMB3 dialec... |
861 862 |
cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED); else if (global_secflags & CIFSSEC_MAY_SIGN) |
2796d303e cifs: Allocate va... |
863 |
pneg_inbuf->SecurityMode = |
ff1c038ad Check SMB3 dialec... |
864 865 |
cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED); else |
2796d303e cifs: Allocate va... |
866 |
pneg_inbuf->SecurityMode = 0; |
ff1c038ad Check SMB3 dialec... |
867 |
|
9764c02fc SMB3: Add support... |
868 869 870 |
if (strcmp(tcon->ses->server->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { |
2796d303e cifs: Allocate va... |
871 872 873 |
pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID); pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID); pneg_inbuf->DialectCount = cpu_to_le16(2); |
9764c02fc SMB3: Add support... |
874 |
/* structure is big enough for 3 dialects, sending only 2 */ |
2796d303e cifs: Allocate va... |
875 876 |
inbuflen = sizeof(*pneg_inbuf) - sizeof(pneg_inbuf->Dialects[0]); |
9764c02fc SMB3: Add support... |
877 878 |
} else if (strcmp(tcon->ses->server->vals->version_string, SMBDEFAULT_VERSION_STRING) == 0) { |
2796d303e cifs: Allocate va... |
879 880 881 882 |
pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); pneg_inbuf->DialectCount = cpu_to_le16(3); |
9764c02fc SMB3: Add support... |
883 |
/* structure is big enough for 3 dialects */ |
2796d303e cifs: Allocate va... |
884 |
inbuflen = sizeof(*pneg_inbuf); |
9764c02fc SMB3: Add support... |
885 886 |
} else { /* otherwise specific dialect was requested */ |
2796d303e cifs: Allocate va... |
887 |
pneg_inbuf->Dialects[0] = |
9764c02fc SMB3: Add support... |
888 |
cpu_to_le16(tcon->ses->server->vals->protocol_id); |
2796d303e cifs: Allocate va... |
889 |
pneg_inbuf->DialectCount = cpu_to_le16(1); |
9764c02fc SMB3: Add support... |
890 |
/* structure is big enough for 3 dialects, sending only 1 */ |
2796d303e cifs: Allocate va... |
891 892 |
inbuflen = sizeof(*pneg_inbuf) - sizeof(pneg_inbuf->Dialects[0]) * 2; |
9764c02fc SMB3: Add support... |
893 |
} |
ff1c038ad Check SMB3 dialec... |
894 895 896 |
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, |
2796d303e cifs: Allocate va... |
897 |
(char *)pneg_inbuf, inbuflen, (char **)&pneg_rsp, &rsplen); |
d579b4eae cifs: Accept vali... |
898 899 900 901 902 903 904 905 906 |
if (rc == -EOPNOTSUPP) { /* * Old Windows versions or Netapp SMB server can return * not supported error. Client should accept it. */ cifs_dbg(VFS, "Server does not support validate negotiate "); return 0; } else if (rc != 0) { |
ff1c038ad Check SMB3 dialec... |
907 908 |
cifs_dbg(VFS, "validate protocol negotiate failed: %d ", rc); |
2796d303e cifs: Allocate va... |
909 910 |
rc = -EIO; goto out_free_inbuf; |
ff1c038ad Check SMB3 dialec... |
911 |
} |
2796d303e cifs: Allocate va... |
912 913 |
rc = -EIO; if (rsplen != sizeof(*pneg_rsp)) { |
7db0a6efd SMB3: Work around... |
914 915 916 917 918 |
cifs_dbg(VFS, "invalid protocol negotiate response size: %d ", rsplen); /* relax check since Mac returns max bufsize allowed on ioctl */ |
2796d303e cifs: Allocate va... |
919 920 |
if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp)) goto out_free_rsp; |
ff1c038ad Check SMB3 dialec... |
921 922 923 |
} /* check validate negotiate info response matches what we got earlier */ |
9aca7e454 cifs: Fix autoneg... |
924 |
if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect)) |
ff1c038ad Check SMB3 dialec... |
925 926 927 928 929 930 931 932 933 934 935 936 |
goto vneg_out; if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode)) goto vneg_out; /* do not validate server guid because not saved at negprot time yet */ if ((le32_to_cpu(pneg_rsp->Capabilities) | SMB2_NT_FIND | SMB2_LARGE_FILES) != tcon->ses->server->capabilities) goto vneg_out; /* validate negotiate successful */ |
2796d303e cifs: Allocate va... |
937 |
rc = 0; |
ff1c038ad Check SMB3 dialec... |
938 939 |
cifs_dbg(FYI, "validate negotiate info successful "); |
2796d303e cifs: Allocate va... |
940 |
goto out_free_rsp; |
ff1c038ad Check SMB3 dialec... |
941 942 943 944 |
vneg_out: cifs_dbg(VFS, "protocol revalidation - security settings mismatch "); |
2796d303e cifs: Allocate va... |
945 |
out_free_rsp: |
fe83bebc0 SMB: fix leak of ... |
946 |
kfree(pneg_rsp); |
2796d303e cifs: Allocate va... |
947 948 949 |
out_free_inbuf: kfree(pneg_inbuf); return rc; |
ff1c038ad Check SMB3 dialec... |
950 |
} |
ef65aaede smb2: Enforce sec... |
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
enum securityEnum smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) { switch (requested) { case Kerberos: case RawNTLMSSP: return requested; case NTLMv2: return RawNTLMSSP; case Unspecified: if (server->sec_ntlmssp && (global_secflags & CIFSSEC_MAY_NTLMSSP)) return RawNTLMSSP; if ((server->sec_kerberos || server->sec_mskerberos) && (global_secflags & CIFSSEC_MAY_KRB5)) return Kerberos; /* Fallthrough */ default: return Unspecified; } } |
3baf1a7b9 SMB2: Separate Ke... |
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 |
struct SMB2_sess_data { unsigned int xid; struct cifs_ses *ses; struct nls_table *nls_cp; void (*func)(struct SMB2_sess_data *); int result; u64 previous_session; /* we will send the SMB in three pieces: * a fixed length beginning part, an optional * SPNEGO blob (which can be zero length), and a * last part which will include the strings * and rest of bcc area. This allows us to avoid * a large buffer 17K allocation */ int buf0_type; struct kvec iov[2]; }; static int SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data) { int rc; struct cifs_ses *ses = sess_data->ses; struct smb2_sess_setup_req *req; struct TCP_Server_Info *server = ses->server; |
88ea5cb7d cifs: remove rfc1... |
998 |
unsigned int total_len; |
3baf1a7b9 SMB2: Separate Ke... |
999 |
|
88ea5cb7d cifs: remove rfc1... |
1000 1001 |
rc = smb2_plain_req_init(SMB2_SESSION_SETUP, NULL, (void **) &req, &total_len); |
3baf1a7b9 SMB2: Separate Ke... |
1002 1003 |
if (rc) return rc; |
31473fc4f CIFS: Separate SM... |
1004 |
/* First session, not a reauthenticate */ |
88ea5cb7d cifs: remove rfc1... |
1005 |
req->sync_hdr.SessionId = 0; |
3baf1a7b9 SMB2: Separate Ke... |
1006 1007 1008 1009 1010 |
/* if reconnect, we need to send previous sess id, otherwise it is 0 */ req->PreviousSessionId = sess_data->previous_session; req->Flags = 0; /* MBZ */ |
d409014e4 smb3: increase in... |
1011 1012 1013 |
/* enough to enable echos and oplocks and one max size write */ req->sync_hdr.CreditRequest = cpu_to_le16(130); |
3baf1a7b9 SMB2: Separate Ke... |
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 |
/* only one of SMB2 signing flags may be set in SMB2 request */ if (server->sign) req->SecurityMode = SMB2_NEGOTIATE_SIGNING_REQUIRED; else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag unlike MUST_ */ req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED; else req->SecurityMode = 0; req->Capabilities = 0; req->Channel = 0; /* MBZ */ sess_data->iov[0].iov_base = (char *)req; |
88ea5cb7d cifs: remove rfc1... |
1027 1028 |
/* 1 for pad */ sess_data->iov[0].iov_len = total_len - 1; |
3baf1a7b9 SMB2: Separate Ke... |
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 |
/* * This variable will be used to clear the buffer * allocated above in case of any error in the calling function. */ sess_data->buf0_type = CIFS_SMALL_BUFFER; return 0; } static void SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data) { free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base); sess_data->buf0_type = CIFS_NO_BUFFER; } static int SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data) { int rc; |
40eff45b5 cifs: remove smb2... |
1049 |
struct smb_rqst rqst; |
3baf1a7b9 SMB2: Separate Ke... |
1050 |
struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base; |
da502f7df CIFS: Make SendRe... |
1051 |
struct kvec rsp_iov = { NULL, 0 }; |
3baf1a7b9 SMB2: Separate Ke... |
1052 1053 1054 |
/* Testing shows that buffer offset must be at location of Buffer[0] */ req->SecurityBufferOffset = |
88ea5cb7d cifs: remove rfc1... |
1055 |
cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */); |
3baf1a7b9 SMB2: Separate Ke... |
1056 |
req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len); |
40eff45b5 cifs: remove smb2... |
1057 1058 1059 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = sess_data->iov; rqst.rq_nvec = 2; |
3baf1a7b9 SMB2: Separate Ke... |
1060 |
|
40eff45b5 cifs: remove smb2... |
1061 1062 1063 |
/* BB add code to build os and lm fields */ rc = cifs_send_recv(sess_data->xid, sess_data->ses, &rqst, |
88ea5cb7d cifs: remove rfc1... |
1064 1065 |
&sess_data->buf0_type, CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
1066 1067 |
cifs_small_buf_release(sess_data->iov[0].iov_base); memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec)); |
3baf1a7b9 SMB2: Separate Ke... |
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 |
return rc; } static int SMB2_sess_establish_session(struct SMB2_sess_data *sess_data) { int rc = 0; struct cifs_ses *ses = sess_data->ses; mutex_lock(&ses->server->srv_mutex); |
cabfb3680 CIFS: Enable encr... |
1079 |
if (ses->server->ops->generate_signingkey) { |
3baf1a7b9 SMB2: Separate Ke... |
1080 |
rc = ses->server->ops->generate_signingkey(ses); |
3baf1a7b9 SMB2: Separate Ke... |
1081 1082 1083 1084 1085 |
if (rc) { cifs_dbg(FYI, "SMB3 session key generation failed "); mutex_unlock(&ses->server->srv_mutex); |
cabfb3680 CIFS: Enable encr... |
1086 |
return rc; |
3baf1a7b9 SMB2: Separate Ke... |
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
} } if (!ses->server->session_estab) { ses->server->sequence_number = 0x2; ses->server->session_estab = true; } mutex_unlock(&ses->server->srv_mutex); cifs_dbg(FYI, "SMB2/3 session established successfully "); spin_lock(&GlobalMid_Lock); ses->status = CifsGood; ses->need_reconnect = false; spin_unlock(&GlobalMid_Lock); |
3baf1a7b9 SMB2: Separate Ke... |
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 |
return rc; } #ifdef CONFIG_CIFS_UPCALL static void SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) { int rc; struct cifs_ses *ses = sess_data->ses; struct cifs_spnego_msg *msg; struct key *spnego_key = NULL; struct smb2_sess_setup_rsp *rsp = NULL; rc = SMB2_sess_alloc_buffer(sess_data); if (rc) goto out; spnego_key = cifs_get_spnego_key(ses); if (IS_ERR(spnego_key)) { rc = PTR_ERR(spnego_key); spnego_key = NULL; goto out; } msg = spnego_key->payload.data[0]; /* * check version field to make sure that cifs.upcall is * sending us a response in an expected form */ if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { cifs_dbg(VFS, "bad cifs.upcall version. Expected %d got %d", CIFS_SPNEGO_UPCALL_VERSION, msg->version); rc = -EKEYREJECTED; goto out_put_spnego_key; } ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len, GFP_KERNEL); if (!ses->auth_key.response) { cifs_dbg(VFS, "Kerberos can't allocate (%u bytes) memory", msg->sesskey_len); rc = -ENOMEM; goto out_put_spnego_key; } ses->auth_key.len = msg->sesskey_len; sess_data->iov[1].iov_base = msg->data + msg->sesskey_len; sess_data->iov[1].iov_len = msg->secblob_len; rc = SMB2_sess_sendreceive(sess_data); if (rc) goto out_put_spnego_key; rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
49f466bdb cifs: remove stru... |
1157 |
ses->Suid = rsp->sync_hdr.SessionId; |
3baf1a7b9 SMB2: Separate Ke... |
1158 1159 |
ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
3baf1a7b9 SMB2: Separate Ke... |
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 |
rc = SMB2_sess_establish_session(sess_data); out_put_spnego_key: key_invalidate(spnego_key); key_put(spnego_key); out: sess_data->result = rc; sess_data->func = NULL; SMB2_sess_free_buffer(sess_data); } #else static void SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) { cifs_dbg(VFS, "Kerberos negotiated but upcall support disabled! "); sess_data->result = -EOPNOTSUPP; sess_data->func = NULL; } #endif |
166cea4dc SMB2: Separate Ra... |
1180 1181 1182 1183 1184 |
static void SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data); static void SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) |
5478f9ba9 CIFS: Add session... |
1185 |
{ |
166cea4dc SMB2: Separate Ra... |
1186 1187 |
int rc; struct cifs_ses *ses = sess_data->ses; |
5478f9ba9 CIFS: Add session... |
1188 |
struct smb2_sess_setup_rsp *rsp = NULL; |
166cea4dc SMB2: Separate Ra... |
1189 |
char *ntlmssp_blob = NULL; |
5478f9ba9 CIFS: Add session... |
1190 |
bool use_spnego = false; /* else use raw ntlmssp */ |
166cea4dc SMB2: Separate Ra... |
1191 |
u16 blob_length = 0; |
d4e63bd6e cifs: Process pos... |
1192 1193 |
/* |
5478f9ba9 CIFS: Add session... |
1194 1195 1196 1197 |
* If memory allocation is successful, caller of this function * frees it. */ ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL); |
166cea4dc SMB2: Separate Ra... |
1198 1199 1200 1201 |
if (!ses->ntlmssp) { rc = -ENOMEM; goto out_err; } |
5c234aa5e cifs: Add a varia... |
1202 |
ses->ntlmssp->sesskey_per_smbsess = true; |
5478f9ba9 CIFS: Add session... |
1203 |
|
166cea4dc SMB2: Separate Ra... |
1204 |
rc = SMB2_sess_alloc_buffer(sess_data); |
5478f9ba9 CIFS: Add session... |
1205 |
if (rc) |
166cea4dc SMB2: Separate Ra... |
1206 |
goto out_err; |
5478f9ba9 CIFS: Add session... |
1207 |
|
166cea4dc SMB2: Separate Ra... |
1208 1209 1210 1211 1212 1213 |
ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE), GFP_KERNEL); if (ntlmssp_blob == NULL) { rc = -ENOMEM; goto out; } |
c2afb8147 Set previous sess... |
1214 |
|
166cea4dc SMB2: Separate Ra... |
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 |
build_ntlmssp_negotiate_blob(ntlmssp_blob, ses); if (use_spnego) { /* BB eventually need to add this */ cifs_dbg(VFS, "spnego not supported for SMB2 yet "); rc = -EOPNOTSUPP; goto out; } else { blob_length = sizeof(struct _NEGOTIATE_MESSAGE); /* with raw NTLMSSP we don't encapsulate in SPNEGO */ } sess_data->iov[1].iov_base = ntlmssp_blob; sess_data->iov[1].iov_len = blob_length; |
c2afb8147 Set previous sess... |
1228 |
|
166cea4dc SMB2: Separate Ra... |
1229 1230 |
rc = SMB2_sess_sendreceive(sess_data); rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
5478f9ba9 CIFS: Add session... |
1231 |
|
166cea4dc SMB2: Separate Ra... |
1232 1233 |
/* If true, rc here is expected and not an error */ if (sess_data->buf0_type != CIFS_NO_BUFFER && |
49f466bdb cifs: remove stru... |
1234 |
rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) |
166cea4dc SMB2: Separate Ra... |
1235 |
rc = 0; |
38d77c50b cifs: track the e... |
1236 |
|
166cea4dc SMB2: Separate Ra... |
1237 1238 |
if (rc) goto out; |
5478f9ba9 CIFS: Add session... |
1239 |
|
1fc6ad2f1 cifs: remove head... |
1240 |
if (offsetof(struct smb2_sess_setup_rsp, Buffer) != |
166cea4dc SMB2: Separate Ra... |
1241 1242 1243 1244 |
le16_to_cpu(rsp->SecurityBufferOffset)) { cifs_dbg(VFS, "Invalid security buffer offset %d ", le16_to_cpu(rsp->SecurityBufferOffset)); |
5478f9ba9 CIFS: Add session... |
1245 |
rc = -EIO; |
166cea4dc SMB2: Separate Ra... |
1246 |
goto out; |
5478f9ba9 CIFS: Add session... |
1247 |
} |
166cea4dc SMB2: Separate Ra... |
1248 1249 1250 1251 |
rc = decode_ntlmssp_challenge(rsp->Buffer, le16_to_cpu(rsp->SecurityBufferLength), ses); if (rc) goto out; |
5478f9ba9 CIFS: Add session... |
1252 |
|
166cea4dc SMB2: Separate Ra... |
1253 1254 |
cifs_dbg(FYI, "rawntlmssp session setup challenge phase "); |
5478f9ba9 CIFS: Add session... |
1255 |
|
5478f9ba9 CIFS: Add session... |
1256 |
|
49f466bdb cifs: remove stru... |
1257 |
ses->Suid = rsp->sync_hdr.SessionId; |
166cea4dc SMB2: Separate Ra... |
1258 |
ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
166cea4dc SMB2: Separate Ra... |
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 |
out: kfree(ntlmssp_blob); SMB2_sess_free_buffer(sess_data); if (!rc) { sess_data->result = 0; sess_data->func = SMB2_sess_auth_rawntlmssp_authenticate; return; } out_err: kfree(ses->ntlmssp); ses->ntlmssp = NULL; sess_data->result = rc; sess_data->func = NULL; } |
5478f9ba9 CIFS: Add session... |
1274 |
|
166cea4dc SMB2: Separate Ra... |
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 |
static void SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) { int rc; struct cifs_ses *ses = sess_data->ses; struct smb2_sess_setup_req *req; struct smb2_sess_setup_rsp *rsp = NULL; unsigned char *ntlmssp_blob = NULL; bool use_spnego = false; /* else use raw ntlmssp */ u16 blob_length = 0; |
5478f9ba9 CIFS: Add session... |
1285 |
|
166cea4dc SMB2: Separate Ra... |
1286 1287 1288 |
rc = SMB2_sess_alloc_buffer(sess_data); if (rc) goto out; |
5478f9ba9 CIFS: Add session... |
1289 |
|
166cea4dc SMB2: Separate Ra... |
1290 |
req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base; |
88ea5cb7d cifs: remove rfc1... |
1291 |
req->sync_hdr.SessionId = ses->Suid; |
166cea4dc SMB2: Separate Ra... |
1292 1293 1294 1295 1296 1297 1298 |
rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses, sess_data->nls_cp); if (rc) { cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d ", rc); goto out; |
5478f9ba9 CIFS: Add session... |
1299 |
} |
166cea4dc SMB2: Separate Ra... |
1300 1301 1302 1303 1304 1305 1306 1307 1308 |
if (use_spnego) { /* BB eventually need to add this */ cifs_dbg(VFS, "spnego not supported for SMB2 yet "); rc = -EOPNOTSUPP; goto out; } sess_data->iov[1].iov_base = ntlmssp_blob; sess_data->iov[1].iov_len = blob_length; |
5478f9ba9 CIFS: Add session... |
1309 |
|
166cea4dc SMB2: Separate Ra... |
1310 1311 1312 1313 1314 |
rc = SMB2_sess_sendreceive(sess_data); if (rc) goto out; rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; |
49f466bdb cifs: remove stru... |
1315 |
ses->Suid = rsp->sync_hdr.SessionId; |
5478f9ba9 CIFS: Add session... |
1316 |
ses->session_flags = le16_to_cpu(rsp->SessionFlags); |
5478f9ba9 CIFS: Add session... |
1317 |
|
166cea4dc SMB2: Separate Ra... |
1318 1319 1320 1321 1322 1323 1324 1325 1326 |
rc = SMB2_sess_establish_session(sess_data); out: kfree(ntlmssp_blob); SMB2_sess_free_buffer(sess_data); kfree(ses->ntlmssp); ses->ntlmssp = NULL; sess_data->result = rc; sess_data->func = NULL; } |
d4e63bd6e cifs: Process pos... |
1327 |
|
166cea4dc SMB2: Separate Ra... |
1328 1329 1330 |
static int SMB2_select_sec(struct cifs_ses *ses, struct SMB2_sess_data *sess_data) { |
ef65aaede smb2: Enforce sec... |
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 |
int type; type = smb2_select_sectype(ses->server, ses->sectype); cifs_dbg(FYI, "sess setup type %d ", type); if (type == Unspecified) { cifs_dbg(VFS, "Unable to select appropriate authentication method!"); return -EINVAL; } |
d4e63bd6e cifs: Process pos... |
1341 |
|
ef65aaede smb2: Enforce sec... |
1342 |
switch (type) { |
166cea4dc SMB2: Separate Ra... |
1343 1344 1345 1346 1347 1348 1349 |
case Kerberos: sess_data->func = SMB2_auth_kerberos; break; case RawNTLMSSP: sess_data->func = SMB2_sess_auth_rawntlmssp_negotiate; break; default: |
ef65aaede smb2: Enforce sec... |
1350 1351 |
cifs_dbg(VFS, "secType %d not supported! ", type); |
166cea4dc SMB2: Separate Ra... |
1352 |
return -EOPNOTSUPP; |
d4e63bd6e cifs: Process pos... |
1353 |
} |
166cea4dc SMB2: Separate Ra... |
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 |
return 0; } int SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *nls_cp) { int rc = 0; struct TCP_Server_Info *server = ses->server; struct SMB2_sess_data *sess_data; cifs_dbg(FYI, "Session Setup "); if (!server) { WARN(1, "%s: server is NULL! ", __func__); return -EIO; |
d4e63bd6e cifs: Process pos... |
1372 |
} |
d4e63bd6e cifs: Process pos... |
1373 |
|
166cea4dc SMB2: Separate Ra... |
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 |
sess_data = kzalloc(sizeof(struct SMB2_sess_data), GFP_KERNEL); if (!sess_data) return -ENOMEM; rc = SMB2_select_sec(ses, sess_data); if (rc) goto out; sess_data->xid = xid; sess_data->ses = ses; sess_data->buf0_type = CIFS_NO_BUFFER; sess_data->nls_cp = (struct nls_table *) nls_cp; |
b2adf22fd smb3: on reconnec... |
1385 |
sess_data->previous_session = ses->Suid; |
166cea4dc SMB2: Separate Ra... |
1386 |
|
8bd68c6e4 CIFS: implement v... |
1387 1388 1389 1390 1391 |
/* * Initialize the session hash with the server one. */ memcpy(ses->preauth_sha_hash, ses->server->preauth_sha_hash, SMB2_PREAUTH_HASH_SIZE); |
8bd68c6e4 CIFS: implement v... |
1392 |
|
166cea4dc SMB2: Separate Ra... |
1393 1394 |
while (sess_data->func) sess_data->func(sess_data); |
c721c3895 SMB3: Warn user i... |
1395 1396 1397 |
if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign)) cifs_dbg(VFS, "signing requested but authenticated as guest "); |
3baf1a7b9 SMB2: Separate Ke... |
1398 |
rc = sess_data->result; |
166cea4dc SMB2: Separate Ra... |
1399 |
out: |
3baf1a7b9 SMB2: Separate Ke... |
1400 1401 |
kfree(sess_data); return rc; |
5478f9ba9 CIFS: Add session... |
1402 1403 1404 1405 1406 |
} int SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) { |
40eff45b5 cifs: remove smb2... |
1407 |
struct smb_rqst rqst; |
5478f9ba9 CIFS: Add session... |
1408 1409 1410 |
struct smb2_logoff_req *req; /* response is also trivial struct */ int rc = 0; struct TCP_Server_Info *server; |
7fb8986e7 CIFS: Add capabil... |
1411 |
int flags = 0; |
45305eda6 cifs: remove rfc1... |
1412 1413 1414 1415 |
unsigned int total_len; struct kvec iov[1]; struct kvec rsp_iov; int resp_buf_type; |
5478f9ba9 CIFS: Add session... |
1416 |
|
f96637be0 [CIFS] cifs: Rena... |
1417 1418 |
cifs_dbg(FYI, "disconnect session %p ", ses); |
5478f9ba9 CIFS: Add session... |
1419 1420 1421 1422 1423 |
if (ses && (ses->server)) server = ses->server; else return -EIO; |
eb4c7df6c cifs: Avoid umoun... |
1424 1425 1426 |
/* no need to send SMB logoff if uid already closed due to reconnect */ if (ses->need_reconnect) goto smb2_session_already_dead; |
45305eda6 cifs: remove rfc1... |
1427 |
rc = smb2_plain_req_init(SMB2_LOGOFF, NULL, (void **) &req, &total_len); |
5478f9ba9 CIFS: Add session... |
1428 1429 1430 1431 |
if (rc) return rc; /* since no tcon, smb2_init can not do this, so do here */ |
45305eda6 cifs: remove rfc1... |
1432 |
req->sync_hdr.SessionId = ses->Suid; |
7fb8986e7 CIFS: Add capabil... |
1433 1434 1435 1436 |
if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) flags |= CIFS_TRANSFORM_REQ; else if (server->sign) |
45305eda6 cifs: remove rfc1... |
1437 1438 1439 1440 1441 1442 |
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; flags |= CIFS_NO_RESP; iov[0].iov_base = (char *)req; iov[0].iov_len = total_len; |
5478f9ba9 CIFS: Add session... |
1443 |
|
40eff45b5 cifs: remove smb2... |
1444 1445 1446 1447 1448 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
1449 |
cifs_small_buf_release(req); |
5478f9ba9 CIFS: Add session... |
1450 1451 1452 1453 |
/* * No tcon so can't do * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); */ |
eb4c7df6c cifs: Avoid umoun... |
1454 1455 |
smb2_session_already_dead: |
5478f9ba9 CIFS: Add session... |
1456 1457 |
return rc; } |
faaf946a7 CIFS: Add tree co... |
1458 1459 1460 |
static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code) { |
d60622eb5 CIFS: Allow SMB2 ... |
1461 |
cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_failed[code]); |
faaf946a7 CIFS: Add tree co... |
1462 1463 1464 |
} #define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */) |
de9f68df6 [CIFS] Set copych... |
1465 1466 1467 1468 1469 1470 1471 |
/* These are similar values to what Windows uses */ static inline void init_copy_chunk_defaults(struct cifs_tcon *tcon) { tcon->max_chunks = 256; tcon->max_bytes_chunk = 1048576; tcon->max_bytes_copy = 16777216; } |
faaf946a7 CIFS: Add tree co... |
1472 1473 1474 1475 |
int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, struct cifs_tcon *tcon, const struct nls_table *cp) { |
40eff45b5 cifs: remove smb2... |
1476 |
struct smb_rqst rqst; |
faaf946a7 CIFS: Add tree co... |
1477 1478 1479 |
struct smb2_tree_connect_req *req; struct smb2_tree_connect_rsp *rsp = NULL; struct kvec iov[2]; |
db3b5474f CIFS: Fix NULL po... |
1480 |
struct kvec rsp_iov = { NULL, 0 }; |
faaf946a7 CIFS: Add tree co... |
1481 1482 1483 |
int rc = 0; int resp_buftype; int unc_path_len; |
faaf946a7 CIFS: Add tree co... |
1484 |
__le16 *unc_path = NULL; |
7fb8986e7 CIFS: Add capabil... |
1485 |
int flags = 0; |
661bb943a cifs: remove rfc1... |
1486 |
unsigned int total_len; |
faaf946a7 CIFS: Add tree co... |
1487 |
|
f96637be0 [CIFS] cifs: Rena... |
1488 1489 |
cifs_dbg(FYI, "TCON "); |
faaf946a7 CIFS: Add tree co... |
1490 |
|
68a6afa7f cifs: Clean up un... |
1491 |
if (!(ses->server) || !tree) |
faaf946a7 CIFS: Add tree co... |
1492 |
return -EIO; |
faaf946a7 CIFS: Add tree co... |
1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 |
unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL); if (unc_path == NULL) return -ENOMEM; unc_path_len = cifs_strtoUTF16(unc_path, tree, strlen(tree), cp) + 1; unc_path_len *= 2; if (unc_path_len < 2) { kfree(unc_path); return -EINVAL; } |
806a28efe Reset TreeId to z... |
1503 |
/* SMB2 TREE_CONNECT request must be called with TreeId == 0 */ |
b327a717e CIFS: make IPC a ... |
1504 |
tcon->tid = 0; |
806a28efe Reset TreeId to z... |
1505 |
|
661bb943a cifs: remove rfc1... |
1506 1507 |
rc = smb2_plain_req_init(SMB2_TREE_CONNECT, tcon, (void **) &req, &total_len); |
faaf946a7 CIFS: Add tree co... |
1508 1509 1510 1511 |
if (rc) { kfree(unc_path); return rc; } |
5a77e75fe smb3: rename encr... |
1512 |
if (smb3_encryption_required(tcon)) |
ae6f8dd4d CIFS: Allow to sw... |
1513 |
flags |= CIFS_TRANSFORM_REQ; |
faaf946a7 CIFS: Add tree co... |
1514 1515 |
iov[0].iov_base = (char *)req; |
661bb943a cifs: remove rfc1... |
1516 1517 |
/* 1 for pad */ iov[0].iov_len = total_len - 1; |
faaf946a7 CIFS: Add tree co... |
1518 1519 1520 |
/* Testing shows that buffer offset must be at location of Buffer[0] */ req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req) |
661bb943a cifs: remove rfc1... |
1521 |
- 1 /* pad */); |
faaf946a7 CIFS: Add tree co... |
1522 1523 1524 |
req->PathLength = cpu_to_le16(unc_path_len - 2); iov[1].iov_base = unc_path; iov[1].iov_len = unc_path_len; |
14c52acaa cifs: allow guest... |
1525 1526 1527 |
/* * 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 * unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1 |
38bd575b9 SMB3: Fix SMB3.1.... |
1528 |
* (Samba servers don't always set the flag so also check if null user) |
14c52acaa cifs: allow guest... |
1529 |
*/ |
6188f28bf Tree connect for ... |
1530 |
if ((ses->server->dialect == SMB311_PROT_ID) && |
14c52acaa cifs: allow guest... |
1531 |
!smb3_encryption_required(tcon) && |
38bd575b9 SMB3: Fix SMB3.1.... |
1532 1533 1534 |
!(ses->session_flags & (SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) && ((ses->user_name != NULL) || (ses->sectype == Kerberos))) |
6188f28bf Tree connect for ... |
1535 |
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; |
40eff45b5 cifs: remove smb2... |
1536 1537 1538 1539 1540 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 2; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
1541 1542 |
cifs_small_buf_release(req); rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; |
faaf946a7 CIFS: Add tree co... |
1543 1544 1545 1546 1547 1548 1549 1550 |
if (rc != 0) { if (tcon) { cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); tcon->need_reconnect = true; } goto tcon_error_exit; } |
cd1230070 SMB2: Fix share t... |
1551 1552 |
switch (rsp->ShareType) { case SMB2_SHARE_TYPE_DISK: |
f96637be0 [CIFS] cifs: Rena... |
1553 1554 |
cifs_dbg(FYI, "connection to disk share "); |
cd1230070 SMB2: Fix share t... |
1555 1556 |
break; case SMB2_SHARE_TYPE_PIPE: |
b327a717e CIFS: make IPC a ... |
1557 |
tcon->pipe = true; |
f96637be0 [CIFS] cifs: Rena... |
1558 1559 |
cifs_dbg(FYI, "connection to pipe share "); |
cd1230070 SMB2: Fix share t... |
1560 1561 |
break; case SMB2_SHARE_TYPE_PRINT: |
b327a717e CIFS: make IPC a ... |
1562 |
tcon->print = true; |
f96637be0 [CIFS] cifs: Rena... |
1563 1564 |
cifs_dbg(FYI, "connection to printer "); |
cd1230070 SMB2: Fix share t... |
1565 1566 |
break; default: |
f96637be0 [CIFS] cifs: Rena... |
1567 1568 |
cifs_dbg(VFS, "unknown share type %d ", rsp->ShareType); |
faaf946a7 CIFS: Add tree co... |
1569 1570 1571 1572 1573 |
rc = -EOPNOTSUPP; goto tcon_error_exit; } tcon->share_flags = le32_to_cpu(rsp->ShareFlags); |
769ee6a40 Add ability to di... |
1574 |
tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */ |
faaf946a7 CIFS: Add tree co... |
1575 1576 1577 |
tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); tcon->tidStatus = CifsGood; tcon->need_reconnect = false; |
49f466bdb cifs: remove stru... |
1578 |
tcon->tid = rsp->sync_hdr.TreeId; |
46b51d083 cifs: using strlc... |
1579 |
strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); |
faaf946a7 CIFS: Add tree co... |
1580 1581 1582 |
if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0)) |
f96637be0 [CIFS] cifs: Rena... |
1583 1584 |
cifs_dbg(VFS, "DFS capability contradicts DFS flag "); |
ae6f8dd4d CIFS: Allow to sw... |
1585 1586 1587 1588 1589 |
if (tcon->seal && !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) cifs_dbg(VFS, "Encryption is requested but not supported "); |
de9f68df6 [CIFS] Set copych... |
1590 |
init_copy_chunk_defaults(tcon); |
ff1c038ad Check SMB3 dialec... |
1591 1592 |
if (tcon->ses->server->ops->validate_negotiate) rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); |
faaf946a7 CIFS: Add tree co... |
1593 1594 1595 1596 1597 1598 |
tcon_exit: free_rsp_buf(resp_buftype, rsp); kfree(unc_path); return rc; tcon_error_exit: |
49f466bdb cifs: remove stru... |
1599 |
if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { |
f96637be0 [CIFS] cifs: Rena... |
1600 1601 |
cifs_dbg(VFS, "BAD_NETWORK_NAME: %s ", tree); |
faaf946a7 CIFS: Add tree co... |
1602 1603 1604 1605 1606 1607 1608 |
} goto tcon_exit; } int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) { |
40eff45b5 cifs: remove smb2... |
1609 |
struct smb_rqst rqst; |
faaf946a7 CIFS: Add tree co... |
1610 1611 |
struct smb2_tree_disconnect_req *req; /* response is trivial */ int rc = 0; |
faaf946a7 CIFS: Add tree co... |
1612 |
struct cifs_ses *ses = tcon->ses; |
7fb8986e7 CIFS: Add capabil... |
1613 |
int flags = 0; |
4eecf4cfe cifs: remove rfc1... |
1614 1615 1616 1617 |
unsigned int total_len; struct kvec iov[1]; struct kvec rsp_iov; int resp_buf_type; |
faaf946a7 CIFS: Add tree co... |
1618 |
|
f96637be0 [CIFS] cifs: Rena... |
1619 1620 |
cifs_dbg(FYI, "Tree Disconnect "); |
faaf946a7 CIFS: Add tree co... |
1621 |
|
68a6afa7f cifs: Clean up un... |
1622 |
if (!ses || !(ses->server)) |
faaf946a7 CIFS: Add tree co... |
1623 1624 1625 1626 |
return -EIO; if ((tcon->need_reconnect) || (tcon->ses->need_reconnect)) return 0; |
4eecf4cfe cifs: remove rfc1... |
1627 1628 |
rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req, &total_len); |
faaf946a7 CIFS: Add tree co... |
1629 1630 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
1631 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
1632 |
flags |= CIFS_TRANSFORM_REQ; |
4eecf4cfe cifs: remove rfc1... |
1633 1634 1635 1636 |
flags |= CIFS_NO_RESP; iov[0].iov_base = (char *)req; iov[0].iov_len = total_len; |
40eff45b5 cifs: remove smb2... |
1637 1638 1639 1640 1641 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
1642 |
cifs_small_buf_release(req); |
faaf946a7 CIFS: Add tree co... |
1643 1644 1645 1646 1647 |
if (rc) cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE); return rc; } |
2503a0dba CIFS: Add SMB2 su... |
1648 |
|
b8c32dbb0 CIFS: Request SMB... |
1649 |
|
63eb3def3 CIFS: Request dur... |
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 |
static struct create_durable * create_durable_buf(void) { struct create_durable *buf; buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL); if (!buf) return NULL; buf->ccontext.DataOffset = cpu_to_le16(offsetof |
9cbc0b733 CIFS: Reconnect d... |
1660 |
(struct create_durable, Data)); |
63eb3def3 CIFS: Request dur... |
1661 1662 1663 1664 |
buf->ccontext.DataLength = cpu_to_le32(16); buf->ccontext.NameOffset = cpu_to_le16(offsetof (struct create_durable, Name)); buf->ccontext.NameLength = cpu_to_le16(4); |
12197a7fd Clarify SMB2/SMB3... |
1665 |
/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */ |
63eb3def3 CIFS: Request dur... |
1666 1667 1668 1669 1670 1671 |
buf->Name[0] = 'D'; buf->Name[1] = 'H'; buf->Name[2] = 'n'; buf->Name[3] = 'Q'; return buf; } |
9cbc0b733 CIFS: Reconnect d... |
1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 |
static struct create_durable * create_reconnect_durable_buf(struct cifs_fid *fid) { struct create_durable *buf; buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL); if (!buf) return NULL; buf->ccontext.DataOffset = cpu_to_le16(offsetof (struct create_durable, Data)); buf->ccontext.DataLength = cpu_to_le32(16); buf->ccontext.NameOffset = cpu_to_le16(offsetof (struct create_durable, Name)); buf->ccontext.NameLength = cpu_to_le16(4); buf->Data.Fid.PersistentFileId = fid->persistent_fid; buf->Data.Fid.VolatileFileId = fid->volatile_fid; |
12197a7fd Clarify SMB2/SMB3... |
1689 |
/* SMB2_CREATE_DURABLE_HANDLE_RECONNECT is "DHnC" */ |
9cbc0b733 CIFS: Reconnect d... |
1690 1691 1692 1693 1694 1695 |
buf->Name[0] = 'D'; buf->Name[1] = 'H'; buf->Name[2] = 'n'; buf->Name[3] = 'C'; return buf; } |
b8c32dbb0 CIFS: Request SMB... |
1696 |
static __u8 |
42873b0a2 CIFS: Respect epo... |
1697 |
parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, |
96164ab2d cifs: store the l... |
1698 |
unsigned int *epoch, char *lease_key) |
b8c32dbb0 CIFS: Request SMB... |
1699 1700 |
{ char *data_offset; |
b5c7cde3f CIFS: Move parsin... |
1701 |
struct create_context *cc; |
deb7deff2 cifs: fix out-of-... |
1702 1703 |
unsigned int next; unsigned int remaining; |
fd5543963 CIFS: Fix lease c... |
1704 |
char *name; |
b8c32dbb0 CIFS: Request SMB... |
1705 |
|
1fc6ad2f1 cifs: remove head... |
1706 |
data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); |
deb7deff2 cifs: fix out-of-... |
1707 |
remaining = le32_to_cpu(rsp->CreateContextsLength); |
b5c7cde3f CIFS: Move parsin... |
1708 |
cc = (struct create_context *)data_offset; |
deb7deff2 cifs: fix out-of-... |
1709 |
while (remaining >= sizeof(struct create_context)) { |
b5c7cde3f CIFS: Move parsin... |
1710 |
name = le16_to_cpu(cc->NameOffset) + (char *)cc; |
deb7deff2 cifs: fix out-of-... |
1711 1712 |
if (le16_to_cpu(cc->NameLength) == 4 && strncmp(name, "RqLs", 4) == 0) |
96164ab2d cifs: store the l... |
1713 1714 |
return server->ops->parse_lease_buf(cc, epoch, lease_key); |
deb7deff2 cifs: fix out-of-... |
1715 1716 1717 1718 1719 1720 1721 |
next = le32_to_cpu(cc->Next); if (!next) break; remaining -= next; cc = (struct create_context *)((char *)cc + next); } |
b8c32dbb0 CIFS: Request SMB... |
1722 |
|
b5c7cde3f CIFS: Move parsin... |
1723 |
return 0; |
b8c32dbb0 CIFS: Request SMB... |
1724 |
} |
d22cbfecb CIFS: Simplify SM... |
1725 |
static int |
a41a28bda CIFS: Move creati... |
1726 |
add_lease_context(struct TCP_Server_Info *server, struct kvec *iov, |
729c0c9dd cifs: Fix stack o... |
1727 |
unsigned int *num_iovec, u8 *lease_key, __u8 *oplock) |
d22cbfecb CIFS: Simplify SM... |
1728 1729 1730 |
{ struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; |
729c0c9dd cifs: Fix stack o... |
1731 |
iov[num].iov_base = server->ops->create_lease_buf(lease_key, *oplock); |
d22cbfecb CIFS: Simplify SM... |
1732 1733 |
if (iov[num].iov_base == NULL) return -ENOMEM; |
a41a28bda CIFS: Move creati... |
1734 |
iov[num].iov_len = server->vals->create_lease_size; |
d22cbfecb CIFS: Simplify SM... |
1735 1736 1737 |
req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE; if (!req->CreateContextsOffset) req->CreateContextsOffset = cpu_to_le32( |
4f33bc358 cifs: remove rfc1... |
1738 |
sizeof(struct smb2_create_req) + |
d22cbfecb CIFS: Simplify SM... |
1739 |
iov[num - 1].iov_len); |
a41a28bda CIFS: Move creati... |
1740 1741 |
le32_add_cpu(&req->CreateContextsLength, server->vals->create_lease_size); |
d22cbfecb CIFS: Simplify SM... |
1742 1743 1744 |
*num_iovec = num + 1; return 0; } |
b56eae4df [SMB3] Send durab... |
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 |
static struct create_durable_v2 * create_durable_v2_buf(struct cifs_fid *pfid) { struct create_durable_v2 *buf; buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL); if (!buf) return NULL; buf->ccontext.DataOffset = cpu_to_le16(offsetof (struct create_durable_v2, dcontext)); buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2)); buf->ccontext.NameOffset = cpu_to_le16(offsetof (struct create_durable_v2, Name)); buf->ccontext.NameLength = cpu_to_le16(4); buf->dcontext.Timeout = 0; /* Should this be configurable by workload */ buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); |
fa70b87cc SMB3: GUIDs shoul... |
1763 |
generate_random_uuid(buf->dcontext.CreateGuid); |
b56eae4df [SMB3] Send durab... |
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 |
memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16); /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */ buf->Name[0] = 'D'; buf->Name[1] = 'H'; buf->Name[2] = '2'; buf->Name[3] = 'Q'; return buf; } static struct create_durable_handle_reconnect_v2 * create_reconnect_durable_v2_buf(struct cifs_fid *fid) { struct create_durable_handle_reconnect_v2 *buf; buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2), GFP_KERNEL); if (!buf) return NULL; buf->ccontext.DataOffset = cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2, dcontext)); buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_reconnect_context_v2)); buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2, Name)); buf->ccontext.NameLength = cpu_to_le16(4); buf->dcontext.Fid.PersistentFileId = fid->persistent_fid; buf->dcontext.Fid.VolatileFileId = fid->volatile_fid; buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16); /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */ buf->Name[0] = 'D'; buf->Name[1] = 'H'; buf->Name[2] = '2'; buf->Name[3] = 'C'; return buf; } |
63eb3def3 CIFS: Request dur... |
1806 |
static int |
b56eae4df [SMB3] Send durab... |
1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 |
add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec, struct cifs_open_parms *oparms) { struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; iov[num].iov_base = create_durable_v2_buf(oparms->fid); if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = sizeof(struct create_durable_v2); if (!req->CreateContextsOffset) req->CreateContextsOffset = |
4f33bc358 cifs: remove rfc1... |
1819 |
cpu_to_le32(sizeof(struct smb2_create_req) + |
b56eae4df [SMB3] Send durab... |
1820 1821 |
iov[1].iov_len); le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2)); |
b56eae4df [SMB3] Send durab... |
1822 1823 1824 1825 1826 1827 |
*num_iovec = num + 1; return 0; } static int add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec, |
9cbc0b733 CIFS: Reconnect d... |
1828 |
struct cifs_open_parms *oparms) |
63eb3def3 CIFS: Request dur... |
1829 1830 1831 |
{ struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; |
b56eae4df [SMB3] Send durab... |
1832 1833 1834 1835 1836 1837 1838 1839 1840 |
/* indicate that we don't need to relock the file */ oparms->reconnect = false; iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid); if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2); if (!req->CreateContextsOffset) req->CreateContextsOffset = |
4f33bc358 cifs: remove rfc1... |
1841 |
cpu_to_le32(sizeof(struct smb2_create_req) + |
b56eae4df [SMB3] Send durab... |
1842 1843 1844 |
iov[1].iov_len); le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_handle_reconnect_v2)); |
b56eae4df [SMB3] Send durab... |
1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 |
*num_iovec = num + 1; return 0; } static int add_durable_context(struct kvec *iov, unsigned int *num_iovec, struct cifs_open_parms *oparms, bool use_persistent) { struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; if (use_persistent) { if (oparms->reconnect) return add_durable_reconnect_v2_context(iov, num_iovec, oparms); else return add_durable_v2_context(iov, num_iovec, oparms); } |
9cbc0b733 CIFS: Reconnect d... |
1863 1864 1865 1866 1867 1868 |
if (oparms->reconnect) { iov[num].iov_base = create_reconnect_durable_buf(oparms->fid); /* indicate that we don't need to relock the file */ oparms->reconnect = false; } else iov[num].iov_base = create_durable_buf(); |
63eb3def3 CIFS: Request dur... |
1869 1870 1871 1872 1873 |
if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = sizeof(struct create_durable); if (!req->CreateContextsOffset) req->CreateContextsOffset = |
4f33bc358 cifs: remove rfc1... |
1874 |
cpu_to_le32(sizeof(struct smb2_create_req) + |
63eb3def3 CIFS: Request dur... |
1875 |
iov[1].iov_len); |
31f92e9a8 CIFS: convert to ... |
1876 |
le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable)); |
63eb3def3 CIFS: Request dur... |
1877 1878 1879 |
*num_iovec = num + 1; return 0; } |
cdeaf9d04 smb3: allow previ... |
1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 |
/* See MS-SMB2 2.2.13.2.7 */ static struct crt_twarp_ctxt * create_twarp_buf(__u64 timewarp) { struct crt_twarp_ctxt *buf; buf = kzalloc(sizeof(struct crt_twarp_ctxt), GFP_KERNEL); if (!buf) return NULL; buf->ccontext.DataOffset = cpu_to_le16(offsetof (struct crt_twarp_ctxt, Timestamp)); buf->ccontext.DataLength = cpu_to_le32(8); buf->ccontext.NameOffset = cpu_to_le16(offsetof (struct crt_twarp_ctxt, Name)); buf->ccontext.NameLength = cpu_to_le16(4); /* SMB2_CREATE_TIMEWARP_TOKEN is "TWrp" */ buf->Name[0] = 'T'; buf->Name[1] = 'W'; buf->Name[2] = 'r'; buf->Name[3] = 'p'; buf->Timestamp = cpu_to_le64(timewarp); return buf; } /* See MS-SMB2 2.2.13.2.7 */ static int add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp) { struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; iov[num].iov_base = create_twarp_buf(timewarp); if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = sizeof(struct crt_twarp_ctxt); if (!req->CreateContextsOffset) req->CreateContextsOffset = cpu_to_le32( sizeof(struct smb2_create_req) + iov[num - 1].iov_len); le32_add_cpu(&req->CreateContextsLength, sizeof(struct crt_twarp_ctxt)); *num_iovec = num + 1; return 0; } |
f0712928b CIFS: use DFS pat... |
1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 |
static int alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len, const char *treename, const __le16 *path) { int treename_len, path_len; struct nls_table *cp; const __le16 sep[] = {cpu_to_le16('\\'), cpu_to_le16(0x0000)}; /* * skip leading "\\" */ treename_len = strlen(treename); if (treename_len < 2 || !(treename[0] == '\\' && treename[1] == '\\')) return -EINVAL; treename += 2; treename_len -= 2; path_len = UniStrnlen((wchar_t *)path, PATH_MAX); /* * make room for one path separator between the treename and * path */ *out_len = treename_len + 1 + path_len; /* * final path needs to be null-terminated UTF16 with a * size aligned to 8 */ *out_size = roundup((*out_len+1)*2, 8); *out_path = kzalloc(*out_size, GFP_KERNEL); if (!*out_path) return -ENOMEM; cp = load_nls_default(); cifs_strtoUTF16(*out_path, treename, treename_len, cp); UniStrcat(*out_path, sep); UniStrcat(*out_path, path); unload_nls(cp); return 0; } |
bea851b8b smb3: Fix mode on... |
1968 1969 1970 1971 1972 1973 1974 |
int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, umode_t mode, struct cifs_tcon *tcon, const char *full_path, struct cifs_sb_info *cifs_sb) { struct smb_rqst rqst; struct smb2_create_req *req; |
256b4c3f0 CIFS: fix memory ... |
1975 |
struct smb2_create_rsp *rsp = NULL; |
bea851b8b smb3: Fix mode on... |
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 |
struct TCP_Server_Info *server; struct cifs_ses *ses = tcon->ses; struct kvec iov[3]; /* make sure at least one for each open context */ struct kvec rsp_iov = {NULL, 0}; int resp_buftype; int uni_path_len; __le16 *copy_path = NULL; int copy_size; int rc = 0; unsigned int n_iov = 2; __u32 file_attributes = 0; char *pc_buf = NULL; int flags = 0; unsigned int total_len; |
256b4c3f0 CIFS: fix memory ... |
1990 |
__le16 *utf16_path = NULL; |
bea851b8b smb3: Fix mode on... |
1991 1992 1993 |
cifs_dbg(FYI, "mkdir "); |
256b4c3f0 CIFS: fix memory ... |
1994 1995 1996 1997 |
/* resource #1: path allocation */ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); if (!utf16_path) return -ENOMEM; |
bea851b8b smb3: Fix mode on... |
1998 1999 |
if (ses && (ses->server)) server = ses->server; |
256b4c3f0 CIFS: fix memory ... |
2000 2001 2002 2003 |
else { rc = -EIO; goto err_free_path; } |
bea851b8b smb3: Fix mode on... |
2004 |
|
256b4c3f0 CIFS: fix memory ... |
2005 |
/* resource #2: request */ |
bea851b8b smb3: Fix mode on... |
2006 |
rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len); |
bea851b8b smb3: Fix mode on... |
2007 |
if (rc) |
256b4c3f0 CIFS: fix memory ... |
2008 |
goto err_free_path; |
bea851b8b smb3: Fix mode on... |
2009 2010 2011 |
if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; |
bea851b8b smb3: Fix mode on... |
2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 |
req->ImpersonationLevel = IL_IMPERSONATION; req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES); /* File attributes ignored on open (used in create though) */ req->FileAttributes = cpu_to_le32(file_attributes); req->ShareAccess = FILE_SHARE_ALL_LE; req->CreateDisposition = cpu_to_le32(FILE_CREATE); req->CreateOptions = cpu_to_le32(CREATE_NOT_FILE); iov[0].iov_base = (char *)req; /* -1 since last byte is buf[0] which is sent below (path) */ iov[0].iov_len = total_len - 1; req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req)); /* [MS-SMB2] 2.2.13 NameOffset: * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of * the SMB2 header, the file name includes a prefix that will * be processed during DFS name normalization as specified in * section 3.3.5.9. Otherwise, the file name is relative to * the share that is identified by the TreeId in the SMB2 * header. */ if (tcon->share_flags & SHI1005_FLAGS_DFS) { int name_len; req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS; rc = alloc_path_with_tree_prefix(©_path, ©_size, &name_len, |
256b4c3f0 CIFS: fix memory ... |
2040 2041 2042 |
tcon->treeName, utf16_path); if (rc) goto err_free_req; |
bea851b8b smb3: Fix mode on... |
2043 2044 |
req->NameLength = cpu_to_le16(name_len * 2); uni_path_len = copy_size; |
256b4c3f0 CIFS: fix memory ... |
2045 2046 2047 |
/* free before overwriting resource */ kfree(utf16_path); utf16_path = copy_path; |
bea851b8b smb3: Fix mode on... |
2048 |
} else { |
256b4c3f0 CIFS: fix memory ... |
2049 |
uni_path_len = (2 * UniStrnlen((wchar_t *)utf16_path, PATH_MAX)) + 2; |
bea851b8b smb3: Fix mode on... |
2050 2051 2052 2053 2054 2055 |
/* MUST set path len (NameLength) to 0 opening root of share */ req->NameLength = cpu_to_le16(uni_path_len - 2); if (uni_path_len % 8 != 0) { copy_size = roundup(uni_path_len, 8); copy_path = kzalloc(copy_size, GFP_KERNEL); if (!copy_path) { |
256b4c3f0 CIFS: fix memory ... |
2056 2057 |
rc = -ENOMEM; goto err_free_req; |
bea851b8b smb3: Fix mode on... |
2058 |
} |
256b4c3f0 CIFS: fix memory ... |
2059 |
memcpy((char *)copy_path, (const char *)utf16_path, |
bea851b8b smb3: Fix mode on... |
2060 2061 |
uni_path_len); uni_path_len = copy_size; |
256b4c3f0 CIFS: fix memory ... |
2062 2063 2064 |
/* free before overwriting resource */ kfree(utf16_path); utf16_path = copy_path; |
bea851b8b smb3: Fix mode on... |
2065 2066 2067 2068 |
} } iov[1].iov_len = uni_path_len; |
256b4c3f0 CIFS: fix memory ... |
2069 |
iov[1].iov_base = utf16_path; |
bea851b8b smb3: Fix mode on... |
2070 2071 2072 |
req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE; if (tcon->posix_extensions) { |
256b4c3f0 CIFS: fix memory ... |
2073 |
/* resource #3: posix buf */ |
bea851b8b smb3: Fix mode on... |
2074 |
rc = add_posix_context(iov, &n_iov, mode); |
256b4c3f0 CIFS: fix memory ... |
2075 2076 |
if (rc) goto err_free_req; |
bea851b8b smb3: Fix mode on... |
2077 2078 2079 2080 2081 2082 2083 |
pc_buf = iov[n_iov-1].iov_base; } memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = n_iov; |
256b4c3f0 CIFS: fix memory ... |
2084 2085 2086 |
/* resource #4: response buffer */ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); if (rc) { |
bea851b8b smb3: Fix mode on... |
2087 2088 |
cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid, |
256b4c3f0 CIFS: fix memory ... |
2089 2090 2091 2092 2093 2094 2095 2096 2097 |
CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES, rc); goto err_free_rsp_buf; } rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid, CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES); |
bea851b8b smb3: Fix mode on... |
2098 2099 2100 2101 |
SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId); /* Eventually save off posix specific response info and timestaps */ |
256b4c3f0 CIFS: fix memory ... |
2102 |
err_free_rsp_buf: |
bea851b8b smb3: Fix mode on... |
2103 |
free_rsp_buf(resp_buftype, rsp); |
256b4c3f0 CIFS: fix memory ... |
2104 2105 2106 2107 2108 |
kfree(pc_buf); err_free_req: cifs_small_buf_release(req); err_free_path: kfree(utf16_path); |
bea851b8b smb3: Fix mode on... |
2109 |
return rc; |
bea851b8b smb3: Fix mode on... |
2110 |
} |
bea851b8b smb3: Fix mode on... |
2111 |
|
2503a0dba CIFS: Add SMB2 su... |
2112 |
int |
1eb9fb520 cifs: create SMB2... |
2113 2114 |
SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock, struct cifs_open_parms *oparms, __le16 *path) |
2503a0dba CIFS: Add SMB2 su... |
2115 |
{ |
1eb9fb520 cifs: create SMB2... |
2116 |
struct TCP_Server_Info *server = tcon->ses->server; |
2503a0dba CIFS: Add SMB2 su... |
2117 |
struct smb2_create_req *req; |
da502f7df CIFS: Make SendRe... |
2118 |
unsigned int n_iov = 2; |
ca81983fe CIFS: Respect cre... |
2119 |
__u32 file_attributes = 0; |
1eb9fb520 cifs: create SMB2... |
2120 2121 |
int copy_size; int uni_path_len; |
4f33bc358 cifs: remove rfc1... |
2122 |
unsigned int total_len; |
1eb9fb520 cifs: create SMB2... |
2123 2124 2125 |
struct kvec *iov = rqst->rq_iov; __le16 *copy_path; int rc; |
2503a0dba CIFS: Add SMB2 su... |
2126 |
|
4f33bc358 cifs: remove rfc1... |
2127 |
rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len); |
2503a0dba CIFS: Add SMB2 su... |
2128 2129 |
if (rc) return rc; |
1eb9fb520 cifs: create SMB2... |
2130 2131 2132 |
iov[0].iov_base = (char *)req; /* -1 since last byte is buf[0] which is sent below (path) */ iov[0].iov_len = total_len - 1; |
7fb8986e7 CIFS: Add capabil... |
2133 |
|
064f6047a CIFS: Make SMB2_o... |
2134 |
if (oparms->create_options & CREATE_OPTION_READONLY) |
ca81983fe CIFS: Respect cre... |
2135 |
file_attributes |= ATTR_READONLY; |
db8b631d4 Allow mknod and m... |
2136 2137 |
if (oparms->create_options & CREATE_OPTION_SPECIAL) file_attributes |= ATTR_SYSTEM; |
ca81983fe CIFS: Respect cre... |
2138 |
|
2503a0dba CIFS: Add SMB2 su... |
2139 |
req->ImpersonationLevel = IL_IMPERSONATION; |
064f6047a CIFS: Make SMB2_o... |
2140 |
req->DesiredAccess = cpu_to_le32(oparms->desired_access); |
2503a0dba CIFS: Add SMB2 su... |
2141 2142 2143 |
/* File attributes ignored on open (used in create though) */ req->FileAttributes = cpu_to_le32(file_attributes); req->ShareAccess = FILE_SHARE_ALL_LE; |
064f6047a CIFS: Make SMB2_o... |
2144 2145 |
req->CreateDisposition = cpu_to_le32(oparms->disposition); req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK); |
4f33bc358 cifs: remove rfc1... |
2146 |
req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req)); |
f0712928b CIFS: use DFS pat... |
2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 |
/* [MS-SMB2] 2.2.13 NameOffset: * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of * the SMB2 header, the file name includes a prefix that will * be processed during DFS name normalization as specified in * section 3.3.5.9. Otherwise, the file name is relative to * the share that is identified by the TreeId in the SMB2 * header. */ if (tcon->share_flags & SHI1005_FLAGS_DFS) { int name_len; |
4f33bc358 cifs: remove rfc1... |
2158 |
req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS; |
f0712928b CIFS: use DFS pat... |
2159 2160 2161 |
rc = alloc_path_with_tree_prefix(©_path, ©_size, &name_len, tcon->treeName, path); |
1eb9fb520 cifs: create SMB2... |
2162 |
if (rc) |
f0712928b CIFS: use DFS pat... |
2163 2164 |
return rc; req->NameLength = cpu_to_le16(name_len * 2); |
59aa37184 CIFS: Simplify SM... |
2165 2166 |
uni_path_len = copy_size; path = copy_path; |
f0712928b CIFS: use DFS pat... |
2167 2168 2169 2170 |
} else { uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; /* MUST set path len (NameLength) to 0 opening root of share */ req->NameLength = cpu_to_le16(uni_path_len - 2); |
1eb9fb520 cifs: create SMB2... |
2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 |
copy_size = uni_path_len; if (copy_size % 8 != 0) copy_size = roundup(copy_size, 8); copy_path = kzalloc(copy_size, GFP_KERNEL); if (!copy_path) return -ENOMEM; memcpy((char *)copy_path, (const char *)path, uni_path_len); uni_path_len = copy_size; path = copy_path; |
2503a0dba CIFS: Add SMB2 su... |
2181 |
} |
59aa37184 CIFS: Simplify SM... |
2182 2183 |
iov[1].iov_len = uni_path_len; iov[1].iov_base = path; |
59aa37184 CIFS: Simplify SM... |
2184 |
|
b8c32dbb0 CIFS: Request SMB... |
2185 2186 |
if (!server->oplocks) *oplock = SMB2_OPLOCK_LEVEL_NONE; |
a41a28bda CIFS: Move creati... |
2187 |
if (!(server->capabilities & SMB2_GLOBAL_CAP_LEASING) || |
b8c32dbb0 CIFS: Request SMB... |
2188 2189 |
*oplock == SMB2_OPLOCK_LEVEL_NONE) req->RequestedOplockLevel = *oplock; |
f80156833 smb3: check for a... |
2190 2191 2192 |
else if (!(server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) && (oparms->create_options & CREATE_NOT_FILE)) req->RequestedOplockLevel = *oplock; /* no srv lease support */ |
b8c32dbb0 CIFS: Request SMB... |
2193 |
else { |
729c0c9dd cifs: Fix stack o... |
2194 2195 |
rc = add_lease_context(server, iov, &n_iov, oparms->fid->lease_key, oplock); |
1eb9fb520 cifs: create SMB2... |
2196 |
if (rc) |
d22cbfecb CIFS: Simplify SM... |
2197 |
return rc; |
b8c32dbb0 CIFS: Request SMB... |
2198 |
} |
63eb3def3 CIFS: Request dur... |
2199 2200 |
if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) { /* need to set Next field of lease context if we request it */ |
a41a28bda CIFS: Move creati... |
2201 |
if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) { |
63eb3def3 CIFS: Request dur... |
2202 |
struct create_context *ccontext = |
da502f7df CIFS: Make SendRe... |
2203 |
(struct create_context *)iov[n_iov-1].iov_base; |
1c46943f8 [CIFS] Fix minor ... |
2204 |
ccontext->Next = |
a41a28bda CIFS: Move creati... |
2205 |
cpu_to_le32(server->vals->create_lease_size); |
63eb3def3 CIFS: Request dur... |
2206 |
} |
b56eae4df [SMB3] Send durab... |
2207 |
|
da502f7df CIFS: Make SendRe... |
2208 |
rc = add_durable_context(iov, &n_iov, oparms, |
b56eae4df [SMB3] Send durab... |
2209 |
tcon->use_persistent); |
1eb9fb520 cifs: create SMB2... |
2210 |
if (rc) |
63eb3def3 CIFS: Request dur... |
2211 |
return rc; |
63eb3def3 CIFS: Request dur... |
2212 |
} |
ce558b0e1 smb3: Add posix c... |
2213 2214 2215 2216 2217 2218 2219 2220 2221 |
if (tcon->posix_extensions) { if (n_iov > 2) { struct create_context *ccontext = (struct create_context *)iov[n_iov-1].iov_base; ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len); } rc = add_posix_context(iov, &n_iov, oparms->mode); |
1eb9fb520 cifs: create SMB2... |
2222 |
if (rc) |
ce558b0e1 smb3: Add posix c... |
2223 |
return rc; |
ce558b0e1 smb3: Add posix c... |
2224 |
} |
ce558b0e1 smb3: Add posix c... |
2225 |
|
cdeaf9d04 smb3: allow previ... |
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 |
if (tcon->snapshot_time) { cifs_dbg(FYI, "adding snapshot context "); if (n_iov > 2) { struct create_context *ccontext = (struct create_context *)iov[n_iov-1].iov_base; ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len); } rc = add_twarp_context(iov, &n_iov, tcon->snapshot_time); if (rc) return rc; } |
1eb9fb520 cifs: create SMB2... |
2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 |
rqst->rq_nvec = n_iov; return 0; } /* rq_iov[0] is the request and is released by cifs_small_buf_release(). * All other vectors are freed by kfree(). */ void SMB2_open_free(struct smb_rqst *rqst) { int i; |
b4d965a37 cifs: allow calli... |
2251 2252 2253 2254 2255 2256 |
if (rqst && rqst->rq_iov) { cifs_small_buf_release(rqst->rq_iov[0].iov_base); for (i = 1; i < rqst->rq_nvec; i++) if (rqst->rq_iov[i].iov_base != smb2_padding) kfree(rqst->rq_iov[i].iov_base); } |
1eb9fb520 cifs: create SMB2... |
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 |
} int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, __u8 *oplock, struct smb2_file_all_info *buf, struct kvec *err_iov, int *buftype) { struct smb_rqst rqst; struct smb2_create_rsp *rsp = NULL; struct TCP_Server_Info *server; struct cifs_tcon *tcon = oparms->tcon; struct cifs_ses *ses = tcon->ses; |
4d8dfafc5 cifs: create a de... |
2269 |
struct kvec iov[SMB2_CREATE_IOV_SIZE]; |
1eb9fb520 cifs: create SMB2... |
2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 |
struct kvec rsp_iov = {NULL, 0}; int resp_buftype; int rc = 0; int flags = 0; cifs_dbg(FYI, "create/open "); if (ses && (ses->server)) server = ses->server; else return -EIO; if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; |
40eff45b5 cifs: remove smb2... |
2284 |
memset(&rqst, 0, sizeof(struct smb_rqst)); |
1eb9fb520 cifs: create SMB2... |
2285 |
memset(&iov, 0, sizeof(iov)); |
40eff45b5 cifs: remove smb2... |
2286 |
rqst.rq_iov = iov; |
4d8dfafc5 cifs: create a de... |
2287 |
rqst.rq_nvec = SMB2_CREATE_IOV_SIZE; |
1eb9fb520 cifs: create SMB2... |
2288 2289 2290 2291 |
rc = SMB2_open_init(tcon, &rqst, oplock, oparms, path); if (rc) goto creat_exit; |
40eff45b5 cifs: remove smb2... |
2292 2293 |
rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, |
4f33bc358 cifs: remove rfc1... |
2294 |
&rsp_iov); |
da502f7df CIFS: Make SendRe... |
2295 |
rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; |
2503a0dba CIFS: Add SMB2 su... |
2296 2297 2298 |
if (rc != 0) { cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); |
91cb74f51 cifs: Change SMB2... |
2299 2300 |
if (err_iov && rsp) { *err_iov = rsp_iov; |
9d874c365 cifs: fix a buffe... |
2301 |
*buftype = resp_buftype; |
91cb74f51 cifs: Change SMB2... |
2302 2303 2304 |
resp_buftype = CIFS_NO_BUFFER; rsp = NULL; } |
28d59363a smb3: add tracepo... |
2305 2306 |
trace_smb3_open_err(xid, tcon->tid, ses->Suid, oparms->create_options, oparms->desired_access, rc); |
2503a0dba CIFS: Add SMB2 su... |
2307 |
goto creat_exit; |
28d59363a smb3: add tracepo... |
2308 2309 2310 2311 |
} else trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid, ses->Suid, oparms->create_options, oparms->desired_access); |
2503a0dba CIFS: Add SMB2 su... |
2312 |
|
064f6047a CIFS: Make SMB2_o... |
2313 2314 |
oparms->fid->persistent_fid = rsp->PersistentFileId; oparms->fid->volatile_fid = rsp->VolatileFileId; |
f0df737ee CIFS: Add open/cl... |
2315 2316 2317 2318 2319 2320 2321 2322 2323 |
if (buf) { memcpy(buf, &rsp->CreationTime, 32); buf->AllocationSize = rsp->AllocationSize; buf->EndOfFile = rsp->EndofFile; buf->Attributes = rsp->FileAttributes; buf->NumberOfLinks = cpu_to_le32(1); buf->DeletePending = 0; } |
2e44b2887 CIFS: Process opl... |
2324 |
|
b8c32dbb0 CIFS: Request SMB... |
2325 |
if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) |
96164ab2d cifs: store the l... |
2326 2327 |
*oplock = parse_lease_state(server, rsp, &oparms->fid->epoch, oparms->fid->lease_key); |
b8c32dbb0 CIFS: Request SMB... |
2328 2329 |
else *oplock = rsp->OplockLevel; |
2503a0dba CIFS: Add SMB2 su... |
2330 |
creat_exit: |
1eb9fb520 cifs: create SMB2... |
2331 |
SMB2_open_free(&rqst); |
2503a0dba CIFS: Add SMB2 su... |
2332 2333 2334 |
free_rsp_buf(resp_buftype, rsp); return rc; } |
4a72dafa1 SMB2 FSCTL and IO... |
2335 2336 2337 2338 2339 |
/* * SMB2 IOCTL is used for both IOCTLs and FSCTLs */ int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, |
63a83b861 CIFS: use tcon_ip... |
2340 |
u64 volatile_fid, u32 opcode, bool is_fsctl, |
51146625f CIFS: add use_ipc... |
2341 2342 |
char *in_data, u32 indatalen, char **out_data, u32 *plen /* returned data len */) |
4a72dafa1 SMB2 FSCTL and IO... |
2343 |
{ |
40eff45b5 cifs: remove smb2... |
2344 |
struct smb_rqst rqst; |
4a72dafa1 SMB2 FSCTL and IO... |
2345 2346 |
struct smb2_ioctl_req *req; struct smb2_ioctl_rsp *rsp; |
8e3531060 Fix dereference b... |
2347 |
struct cifs_ses *ses; |
4a72dafa1 SMB2 FSCTL and IO... |
2348 |
struct kvec iov[2]; |
da502f7df CIFS: Make SendRe... |
2349 |
struct kvec rsp_iov; |
4a72dafa1 SMB2 FSCTL and IO... |
2350 |
int resp_buftype; |
da502f7df CIFS: Make SendRe... |
2351 |
int n_iov; |
4a72dafa1 SMB2 FSCTL and IO... |
2352 |
int rc = 0; |
7fb8986e7 CIFS: Add capabil... |
2353 |
int flags = 0; |
977546802 cifs: remove rfc1... |
2354 |
unsigned int total_len; |
4a72dafa1 SMB2 FSCTL and IO... |
2355 2356 2357 |
cifs_dbg(FYI, "SMB2 IOCTL "); |
3d1a3745d Add sparse file s... |
2358 2359 |
if (out_data != NULL) *out_data = NULL; |
4a72dafa1 SMB2 FSCTL and IO... |
2360 2361 2362 |
/* zero out returned data len, in case of error */ if (plen) *plen = 0; |
8e3531060 Fix dereference b... |
2363 2364 2365 2366 |
if (tcon) ses = tcon->ses; else return -EIO; |
68a6afa7f cifs: Clean up un... |
2367 |
if (!ses || !(ses->server)) |
4a72dafa1 SMB2 FSCTL and IO... |
2368 |
return -EIO; |
977546802 cifs: remove rfc1... |
2369 |
rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); |
4a72dafa1 SMB2 FSCTL and IO... |
2370 2371 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
2372 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
2373 |
flags |= CIFS_TRANSFORM_REQ; |
4a72dafa1 SMB2 FSCTL and IO... |
2374 2375 2376 2377 2378 2379 2380 2381 |
req->CtlCode = cpu_to_le32(opcode); req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; if (indatalen) { req->InputCount = cpu_to_le32(indatalen); /* do not set InputOffset if no input data */ req->InputOffset = |
977546802 cifs: remove rfc1... |
2382 |
cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); |
4a72dafa1 SMB2 FSCTL and IO... |
2383 2384 |
iov[1].iov_base = in_data; iov[1].iov_len = indatalen; |
da502f7df CIFS: Make SendRe... |
2385 |
n_iov = 2; |
4a72dafa1 SMB2 FSCTL and IO... |
2386 |
} else |
da502f7df CIFS: Make SendRe... |
2387 |
n_iov = 1; |
4a72dafa1 SMB2 FSCTL and IO... |
2388 2389 2390 2391 2392 2393 2394 2395 2396 |
req->OutputOffset = 0; req->OutputCount = 0; /* MBZ */ /* * Could increase MaxOutputResponse, but that would require more * than one credit. Windows typically sets this smaller, but for some * ioctls it may be useful to allow server to send more. No point * limiting what the server can send as long as fits in one credit |
7db0a6efd SMB3: Work around... |
2397 2398 2399 2400 |
* Unfortunately - we can not handle more than CIFS_MAX_MSG_SIZE * (by default, note that it can be overridden to make max larger) * in responses (except for read responses which can be bigger. * We may want to bump this limit up |
4a72dafa1 SMB2 FSCTL and IO... |
2401 |
*/ |
7db0a6efd SMB3: Work around... |
2402 |
req->MaxOutputResponse = cpu_to_le32(CIFSMaxBufSize); |
4a72dafa1 SMB2 FSCTL and IO... |
2403 2404 2405 2406 2407 2408 2409 |
if (is_fsctl) req->Flags = cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL); else req->Flags = 0; iov[0].iov_base = (char *)req; |
4a72dafa1 SMB2 FSCTL and IO... |
2410 |
|
7ff8d45c9 Fix corrupt SMB2 ... |
2411 2412 2413 2414 2415 2416 |
/* * If no input data, the size of ioctl struct in * protocol spec still includes a 1 byte data buffer, * but if input data passed to ioctl, we do not * want to double count this, so we do not send * the dummy one byte of data in iovec[0] if sending |
977546802 cifs: remove rfc1... |
2417 |
* input data (in iovec[1]). |
7ff8d45c9 Fix corrupt SMB2 ... |
2418 2419 2420 |
*/ if (indatalen) { |
977546802 cifs: remove rfc1... |
2421 |
iov[0].iov_len = total_len - 1; |
7ff8d45c9 Fix corrupt SMB2 ... |
2422 |
} else |
977546802 cifs: remove rfc1... |
2423 |
iov[0].iov_len = total_len; |
7ff8d45c9 Fix corrupt SMB2 ... |
2424 |
|
4587eee04 SMB3: Validate ne... |
2425 2426 |
/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) |
977546802 cifs: remove rfc1... |
2427 |
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; |
4a72dafa1 SMB2 FSCTL and IO... |
2428 |
|
40eff45b5 cifs: remove smb2... |
2429 2430 2431 2432 2433 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = n_iov; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, |
977546802 cifs: remove rfc1... |
2434 |
&rsp_iov); |
da502f7df CIFS: Make SendRe... |
2435 2436 |
cifs_small_buf_release(req); rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; |
4a72dafa1 SMB2 FSCTL and IO... |
2437 |
|
eccb4422c smb3: Add ftrace ... |
2438 2439 2440 |
if (rc != 0) trace_smb3_fsctl_err(xid, persistent_fid, tcon->tid, ses->Suid, 0, opcode, rc); |
9bf0c9cd4 CIFS: Fix SMB2/SM... |
2441 |
if ((rc != 0) && (rc != -EINVAL)) { |
8e3531060 Fix dereference b... |
2442 |
cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); |
4a72dafa1 SMB2 FSCTL and IO... |
2443 |
goto ioctl_exit; |
9bf0c9cd4 CIFS: Fix SMB2/SM... |
2444 2445 2446 |
} else if (rc == -EINVAL) { if ((opcode != FSCTL_SRV_COPYCHUNK_WRITE) && (opcode != FSCTL_SRV_COPYCHUNK)) { |
8e3531060 Fix dereference b... |
2447 |
cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE); |
9bf0c9cd4 CIFS: Fix SMB2/SM... |
2448 2449 |
goto ioctl_exit; } |
4a72dafa1 SMB2 FSCTL and IO... |
2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 |
} /* check if caller wants to look at return data or just return rc */ if ((plen == NULL) || (out_data == NULL)) goto ioctl_exit; *plen = le32_to_cpu(rsp->OutputCount); /* We check for obvious errors in the output buffer length and offset */ if (*plen == 0) goto ioctl_exit; /* server returned no data */ |
2d204ee9d cifs: integer ove... |
2461 |
else if (*plen > rsp_iov.iov_len || *plen > 0xFF00) { |
4a72dafa1 SMB2 FSCTL and IO... |
2462 2463 2464 2465 2466 2467 |
cifs_dbg(VFS, "srv returned invalid ioctl length: %d ", *plen); *plen = 0; rc = -EIO; goto ioctl_exit; } |
2d204ee9d cifs: integer ove... |
2468 |
if (rsp_iov.iov_len - *plen < le32_to_cpu(rsp->OutputOffset)) { |
4a72dafa1 SMB2 FSCTL and IO... |
2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 |
cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d ", *plen, le32_to_cpu(rsp->OutputOffset)); *plen = 0; rc = -EIO; goto ioctl_exit; } *out_data = kmalloc(*plen, GFP_KERNEL); if (*out_data == NULL) { rc = -ENOMEM; goto ioctl_exit; } |
977b61704 cifs: remove rfc1... |
2482 |
memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen); |
4a72dafa1 SMB2 FSCTL and IO... |
2483 2484 2485 2486 |
ioctl_exit: free_rsp_buf(resp_buftype, rsp); return rc; } |
64a5cfa6d Allow setting per... |
2487 2488 2489 2490 2491 2492 2493 2494 2495 |
/* * Individual callers to ioctl worker function follow */ int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) { int rc; |
64a5cfa6d Allow setting per... |
2496 2497 2498 2499 |
struct compress_ioctl fsctl_input; char *ret_data = NULL; fsctl_input.CompressionState = |
bc09d141e fs/cifs: remove o... |
2500 |
cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); |
64a5cfa6d Allow setting per... |
2501 2502 2503 2504 2505 2506 2507 2508 |
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, FSCTL_SET_COMPRESSION, true /* is_fsctl */, (char *)&fsctl_input /* data input */, 2 /* in data len */, &ret_data /* out data */, NULL); cifs_dbg(FYI, "set compression rc %d ", rc); |
64a5cfa6d Allow setting per... |
2509 2510 2511 |
return rc; } |
2503a0dba CIFS: Add SMB2 su... |
2512 |
int |
8eb4ecfab cifs: add SMB2_cl... |
2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 |
SMB2_close_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid) { struct smb2_close_req *req; struct kvec *iov = rqst->rq_iov; unsigned int total_len; int rc; rc = smb2_plain_req_init(SMB2_CLOSE, tcon, (void **) &req, &total_len); if (rc) return rc; req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; iov[0].iov_base = (char *)req; iov[0].iov_len = total_len; return 0; } void SMB2_close_free(struct smb_rqst *rqst) { |
b4d965a37 cifs: allow calli... |
2536 2537 |
if (rqst && rqst->rq_iov) cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
8eb4ecfab cifs: add SMB2_cl... |
2538 2539 2540 |
} int |
97ca17622 cifs: add a new S... |
2541 2542 |
SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, int flags) |
2503a0dba CIFS: Add SMB2 su... |
2543 |
{ |
40eff45b5 cifs: remove smb2... |
2544 |
struct smb_rqst rqst; |
8eb4ecfab cifs: add SMB2_cl... |
2545 |
struct smb2_close_rsp *rsp = NULL; |
2503a0dba CIFS: Add SMB2 su... |
2546 2547 |
struct cifs_ses *ses = tcon->ses; struct kvec iov[1]; |
da502f7df CIFS: Make SendRe... |
2548 |
struct kvec rsp_iov; |
2503a0dba CIFS: Add SMB2 su... |
2549 2550 |
int resp_buftype; int rc = 0; |
f96637be0 [CIFS] cifs: Rena... |
2551 2552 |
cifs_dbg(FYI, "Close "); |
2503a0dba CIFS: Add SMB2 su... |
2553 |
|
68a6afa7f cifs: Clean up un... |
2554 |
if (!ses || !(ses->server)) |
2503a0dba CIFS: Add SMB2 su... |
2555 |
return -EIO; |
5a77e75fe smb3: rename encr... |
2556 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
2557 |
flags |= CIFS_TRANSFORM_REQ; |
40eff45b5 cifs: remove smb2... |
2558 |
memset(&rqst, 0, sizeof(struct smb_rqst)); |
8eb4ecfab cifs: add SMB2_cl... |
2559 |
memset(&iov, 0, sizeof(iov)); |
40eff45b5 cifs: remove smb2... |
2560 2561 |
rqst.rq_iov = iov; rqst.rq_nvec = 1; |
8eb4ecfab cifs: add SMB2_cl... |
2562 2563 2564 |
rc = SMB2_close_init(tcon, &rqst, persistent_fid, volatile_fid); if (rc) goto close_exit; |
40eff45b5 cifs: remove smb2... |
2565 |
rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
2566 |
rsp = (struct smb2_close_rsp *)rsp_iov.iov_base; |
2503a0dba CIFS: Add SMB2 su... |
2567 2568 |
if (rc != 0) { |
d4a029d21 cifs: remove unne... |
2569 |
cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE); |
eccb4422c smb3: Add ftrace ... |
2570 2571 |
trace_smb3_close_err(xid, persistent_fid, tcon->tid, ses->Suid, rc); |
2503a0dba CIFS: Add SMB2 su... |
2572 2573 |
goto close_exit; } |
2503a0dba CIFS: Add SMB2 su... |
2574 2575 2576 |
/* BB FIXME - decode close response, update inode for caching */ close_exit: |
8eb4ecfab cifs: add SMB2_cl... |
2577 |
SMB2_close_free(&rqst); |
2503a0dba CIFS: Add SMB2 su... |
2578 2579 2580 |
free_rsp_buf(resp_buftype, rsp); return rc; } |
be4cb9e3d CIFS: Query SMB2 ... |
2581 |
|
97ca17622 cifs: add a new S... |
2582 2583 2584 2585 2586 2587 |
int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) { return SMB2_close_flags(xid, tcon, persistent_fid, volatile_fid, 0); } |
730928c8f cifs: update smb2... |
2588 2589 2590 |
int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, struct kvec *iov, unsigned int min_buf_size) |
be4cb9e3d CIFS: Query SMB2 ... |
2591 |
{ |
c1596ff52 cifs: change vali... |
2592 |
unsigned int smb_len = iov->iov_len; |
1fc6ad2f1 cifs: remove head... |
2593 2594 |
char *end_of_smb = smb_len + (char *)iov->iov_base; char *begin_of_buf = offset + (char *)iov->iov_base; |
be4cb9e3d CIFS: Query SMB2 ... |
2595 2596 2597 2598 |
char *end_of_buf = begin_of_buf + buffer_length; if (buffer_length < min_buf_size) { |
f96637be0 [CIFS] cifs: Rena... |
2599 2600 2601 |
cifs_dbg(VFS, "buffer length %d smaller than minimum size %d ", buffer_length, min_buf_size); |
be4cb9e3d CIFS: Query SMB2 ... |
2602 2603 2604 2605 2606 |
return -EINVAL; } /* check if beyond RFC1001 maximum length */ if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) { |
f96637be0 [CIFS] cifs: Rena... |
2607 2608 2609 |
cifs_dbg(VFS, "buffer length %d or smb length %d too large ", buffer_length, smb_len); |
be4cb9e3d CIFS: Query SMB2 ... |
2610 2611 2612 2613 |
return -EINVAL; } if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) { |
f96637be0 [CIFS] cifs: Rena... |
2614 2615 |
cifs_dbg(VFS, "illegal server response, bad offset to data "); |
be4cb9e3d CIFS: Query SMB2 ... |
2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 |
return -EINVAL; } return 0; } /* * If SMB buffer fields are valid, copy into temporary buffer to hold result. * Caller must free buffer. */ static int |
1fc6ad2f1 cifs: remove head... |
2627 |
validate_and_copy_iov(unsigned int offset, unsigned int buffer_length, |
c1596ff52 cifs: change vali... |
2628 |
struct kvec *iov, unsigned int minbufsize, |
be4cb9e3d CIFS: Query SMB2 ... |
2629 |
char *data) |
be4cb9e3d CIFS: Query SMB2 ... |
2630 |
{ |
1fc6ad2f1 cifs: remove head... |
2631 |
char *begin_of_buf = offset + (char *)iov->iov_base; |
be4cb9e3d CIFS: Query SMB2 ... |
2632 2633 2634 2635 |
int rc; if (!data) return -EINVAL; |
730928c8f cifs: update smb2... |
2636 |
rc = smb2_validate_iov(offset, buffer_length, iov, minbufsize); |
be4cb9e3d CIFS: Query SMB2 ... |
2637 2638 2639 2640 2641 2642 2643 |
if (rc) return rc; memcpy(data, begin_of_buf, buffer_length); return 0; } |
296ecbae7 cifs: add SMB2_qu... |
2644 2645 2646 2647 2648 |
int SMB2_query_info_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, u64 persistent_fid, u64 volatile_fid, u8 info_class, u8 info_type, u32 additional_info, size_t output_len) |
be4cb9e3d CIFS: Query SMB2 ... |
2649 2650 |
{ struct smb2_query_info_req *req; |
296ecbae7 cifs: add SMB2_qu... |
2651 |
struct kvec *iov = rqst->rq_iov; |
b2fb7fecc cifs: remove rfc1... |
2652 |
unsigned int total_len; |
296ecbae7 cifs: add SMB2_qu... |
2653 |
int rc; |
be4cb9e3d CIFS: Query SMB2 ... |
2654 |
|
b2fb7fecc cifs: remove rfc1... |
2655 2656 |
rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req, &total_len); |
be4cb9e3d CIFS: Query SMB2 ... |
2657 2658 |
if (rc) return rc; |
42c493c16 cifs: prototype d... |
2659 |
req->InfoType = info_type; |
f0df737ee CIFS: Add open/cl... |
2660 |
req->FileInfoClass = info_class; |
be4cb9e3d CIFS: Query SMB2 ... |
2661 2662 |
req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; |
42c493c16 cifs: prototype d... |
2663 |
req->AdditionalInformation = cpu_to_le32(additional_info); |
48923d2a9 CIFS: do not send... |
2664 2665 2666 2667 2668 |
/* * We do not use the input buffer (do not send extra byte) */ req->InputBufferOffset = 0; |
48923d2a9 CIFS: do not send... |
2669 |
|
f0df737ee CIFS: Add open/cl... |
2670 |
req->OutputBufferLength = cpu_to_le32(output_len); |
be4cb9e3d CIFS: Query SMB2 ... |
2671 2672 |
iov[0].iov_base = (char *)req; |
b2fb7fecc cifs: remove rfc1... |
2673 2674 |
/* 1 for Buffer */ iov[0].iov_len = total_len - 1; |
296ecbae7 cifs: add SMB2_qu... |
2675 2676 2677 2678 2679 2680 |
return 0; } void SMB2_query_info_free(struct smb_rqst *rqst) { |
b4d965a37 cifs: allow calli... |
2681 2682 |
if (rqst && rqst->rq_iov) cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ |
296ecbae7 cifs: add SMB2_qu... |
2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 |
} static int query_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u8 info_class, u8 info_type, u32 additional_info, size_t output_len, size_t min_len, void **data, u32 *dlen) { struct smb_rqst rqst; struct smb2_query_info_rsp *rsp = NULL; struct kvec iov[1]; struct kvec rsp_iov; int rc = 0; int resp_buftype; struct cifs_ses *ses = tcon->ses; int flags = 0; cifs_dbg(FYI, "Query Info "); if (!ses || !(ses->server)) return -EIO; if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; |
be4cb9e3d CIFS: Query SMB2 ... |
2708 |
|
40eff45b5 cifs: remove smb2... |
2709 |
memset(&rqst, 0, sizeof(struct smb_rqst)); |
296ecbae7 cifs: add SMB2_qu... |
2710 |
memset(&iov, 0, sizeof(iov)); |
40eff45b5 cifs: remove smb2... |
2711 2712 |
rqst.rq_iov = iov; rqst.rq_nvec = 1; |
296ecbae7 cifs: add SMB2_qu... |
2713 2714 2715 2716 2717 |
rc = SMB2_query_info_init(tcon, &rqst, persistent_fid, volatile_fid, info_class, info_type, additional_info, output_len); if (rc) goto qinf_exit; |
40eff45b5 cifs: remove smb2... |
2718 |
rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
2719 |
rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; |
e5d048871 CIFS: Fix possibl... |
2720 |
|
be4cb9e3d CIFS: Query SMB2 ... |
2721 2722 |
if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
eccb4422c smb3: Add ftrace ... |
2723 2724 |
trace_smb3_query_info_err(xid, persistent_fid, tcon->tid, ses->Suid, info_class, (__u32)info_type, rc); |
be4cb9e3d CIFS: Query SMB2 ... |
2725 2726 |
goto qinf_exit; } |
42c493c16 cifs: prototype d... |
2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 |
if (dlen) { *dlen = le32_to_cpu(rsp->OutputBufferLength); if (!*data) { *data = kmalloc(*dlen, GFP_KERNEL); if (!*data) { cifs_dbg(VFS, "Error %d allocating memory for acl ", rc); *dlen = 0; goto qinf_exit; } } } |
1fc6ad2f1 cifs: remove head... |
2741 |
rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset), |
be4cb9e3d CIFS: Query SMB2 ... |
2742 |
le32_to_cpu(rsp->OutputBufferLength), |
c1596ff52 cifs: change vali... |
2743 |
&rsp_iov, min_len, *data); |
be4cb9e3d CIFS: Query SMB2 ... |
2744 2745 |
qinf_exit: |
296ecbae7 cifs: add SMB2_qu... |
2746 |
SMB2_query_info_free(&rqst); |
be4cb9e3d CIFS: Query SMB2 ... |
2747 2748 2749 |
free_rsp_buf(resp_buftype, rsp); return rc; } |
9094fad1e CIFS: Add echo re... |
2750 |
|
95907fea4 cifs: Add support... |
2751 |
int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, |
7cb3def44 cifs: handle larg... |
2752 2753 |
u64 persistent_fid, u64 volatile_fid, int ea_buf_size, struct smb2_file_full_ea_info *data) |
95907fea4 cifs: Add support... |
2754 2755 2756 |
{ return query_info(xid, tcon, persistent_fid, volatile_fid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, |
7cb3def44 cifs: handle larg... |
2757 |
ea_buf_size, |
95907fea4 cifs: Add support... |
2758 2759 2760 2761 |
sizeof(struct smb2_file_full_ea_info), (void **)&data, NULL); } |
42c493c16 cifs: prototype d... |
2762 2763 2764 2765 2766 2767 2768 2769 2770 |
int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data) { return query_info(xid, tcon, persistent_fid, volatile_fid, FILE_ALL_INFORMATION, SMB2_O_INFO_FILE, 0, sizeof(struct smb2_file_all_info) + PATH_MAX * 2, sizeof(struct smb2_file_all_info), (void **)&data, NULL); } |
f0df737ee CIFS: Add open/cl... |
2771 |
int |
42c493c16 cifs: prototype d... |
2772 |
SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon, |
f0df737ee CIFS: Add open/cl... |
2773 |
u64 persistent_fid, u64 volatile_fid, |
42c493c16 cifs: prototype d... |
2774 |
void **data, u32 *plen) |
f0df737ee CIFS: Add open/cl... |
2775 |
{ |
42c493c16 cifs: prototype d... |
2776 2777 |
__u32 additional_info = OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO; *plen = 0; |
f0df737ee CIFS: Add open/cl... |
2778 |
return query_info(xid, tcon, persistent_fid, volatile_fid, |
42c493c16 cifs: prototype d... |
2779 |
0, SMB2_O_INFO_SECURITY, additional_info, |
ee25c6dd7 cifs: For SMB2 se... |
2780 |
SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen); |
f0df737ee CIFS: Add open/cl... |
2781 2782 2783 2784 2785 2786 2787 |
} int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, __le64 *uniqueid) { return query_info(xid, tcon, persistent_fid, volatile_fid, |
42c493c16 cifs: prototype d... |
2788 2789 |
FILE_INTERNAL_INFORMATION, SMB2_O_INFO_FILE, 0, sizeof(struct smb2_file_internal_info), |
f0df737ee CIFS: Add open/cl... |
2790 |
sizeof(struct smb2_file_internal_info), |
42c493c16 cifs: prototype d... |
2791 |
(void **)&uniqueid, NULL); |
f0df737ee CIFS: Add open/cl... |
2792 |
} |
9094fad1e CIFS: Add echo re... |
2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 |
/* * This is a no-op for now. We're not really interested in the reply, but * rather in the fact that the server sent one and that server->lstrp * gets updated. * * FIXME: maybe we should consider checking that the reply matches request? */ static void smb2_echo_callback(struct mid_q_entry *mid) { struct TCP_Server_Info *server = mid->callback_data; |
31473fc4f CIFS: Separate SM... |
2804 |
struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf; |
b1765ebd9 CIFS: Do not assu... |
2805 |
unsigned int credits_received = 0; |
9094fad1e CIFS: Add echo re... |
2806 |
|
b1765ebd9 CIFS: Do not assu... |
2807 2808 |
if (mid->mid_state == MID_RESPONSE_RECEIVED || mid->mid_state == MID_RESPONSE_MALFORMED) |
49f466bdb cifs: remove stru... |
2809 |
credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
9094fad1e CIFS: Add echo re... |
2810 2811 2812 2813 |
DeleteMidQEntry(mid); add_credits(server, credits_received, CIFS_ECHO_OP); } |
53e0e11ef CIFS: Fix a possi... |
2814 2815 2816 2817 2818 2819 2820 2821 |
void smb2_reconnect_server(struct work_struct *work) { struct TCP_Server_Info *server = container_of(work, struct TCP_Server_Info, reconnect.work); struct cifs_ses *ses; struct cifs_tcon *tcon, *tcon2; struct list_head tmp_list; int tcon_exist = false; |
18ea43113 CIFS: reconnect t... |
2822 2823 |
int rc; int resched = false; |
53e0e11ef CIFS: Fix a possi... |
2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 |
/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ mutex_lock(&server->reconnect_mutex); INIT_LIST_HEAD(&tmp_list); cifs_dbg(FYI, "Need negotiate, reconnecting tcons "); spin_lock(&cifs_tcp_ses_lock); list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { |
96a988ffe CIFS: Fix a possi... |
2835 |
if (tcon->need_reconnect || tcon->need_reopen_files) { |
53e0e11ef CIFS: Fix a possi... |
2836 2837 2838 2839 2840 |
tcon->tc_count++; list_add_tail(&tcon->rlist, &tmp_list); tcon_exist = true; } } |
b327a717e CIFS: make IPC a ... |
2841 2842 2843 2844 |
if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); tcon_exist = true; } |
53e0e11ef CIFS: Fix a possi... |
2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 |
} /* * Get the reference to server struct to be sure that the last call of * cifs_put_tcon() in the loop below won't release the server pointer. */ if (tcon_exist) server->srv_count++; spin_unlock(&cifs_tcp_ses_lock); list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { |
18ea43113 CIFS: reconnect t... |
2856 2857 |
rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon); if (!rc) |
96a988ffe CIFS: Fix a possi... |
2858 |
cifs_reopen_persistent_handles(tcon); |
18ea43113 CIFS: reconnect t... |
2859 2860 |
else resched = true; |
53e0e11ef CIFS: Fix a possi... |
2861 2862 2863 2864 2865 2866 |
list_del_init(&tcon->rlist); cifs_put_tcon(tcon); } cifs_dbg(FYI, "Reconnecting tcons finished "); |
18ea43113 CIFS: reconnect t... |
2867 2868 |
if (resched) queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ); |
53e0e11ef CIFS: Fix a possi... |
2869 2870 2871 2872 2873 2874 |
mutex_unlock(&server->reconnect_mutex); /* now we can safely release srv struct */ if (tcon_exist) cifs_put_tcp_session(server, 1); } |
9094fad1e CIFS: Add echo re... |
2875 2876 2877 2878 2879 |
int SMB2_echo(struct TCP_Server_Info *server) { struct smb2_echo_req *req; int rc = 0; |
c713c8770 cifs: push rfc100... |
2880 |
struct kvec iov[1]; |
738f9de5c CIFS: Send RFC100... |
2881 |
struct smb_rqst rqst = { .rq_iov = iov, |
c713c8770 cifs: push rfc100... |
2882 |
.rq_nvec = 1 }; |
7f7ae759f cifs: remove rfc1... |
2883 |
unsigned int total_len; |
9094fad1e CIFS: Add echo re... |
2884 |
|
f96637be0 [CIFS] cifs: Rena... |
2885 2886 |
cifs_dbg(FYI, "In echo request "); |
9094fad1e CIFS: Add echo re... |
2887 |
|
4fcd1813e Fix reconnect to ... |
2888 |
if (server->tcpStatus == CifsNeedNegotiate) { |
53e0e11ef CIFS: Fix a possi... |
2889 2890 2891 |
/* No need to send echo on newly established connections */ queue_delayed_work(cifsiod_wq, &server->reconnect, 0); return rc; |
4fcd1813e Fix reconnect to ... |
2892 |
} |
7f7ae759f cifs: remove rfc1... |
2893 |
rc = smb2_plain_req_init(SMB2_ECHO, NULL, (void **)&req, &total_len); |
9094fad1e CIFS: Add echo re... |
2894 2895 |
if (rc) return rc; |
7f7ae759f cifs: remove rfc1... |
2896 |
req->sync_hdr.CreditRequest = cpu_to_le16(1); |
9094fad1e CIFS: Add echo re... |
2897 |
|
c713c8770 cifs: push rfc100... |
2898 2899 |
iov[0].iov_len = total_len; iov[0].iov_base = (char *)req; |
9094fad1e CIFS: Add echo re... |
2900 |
|
9b7c18a2d CIFS: Add mid han... |
2901 2902 |
rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL, server, CIFS_ECHO_OP); |
9094fad1e CIFS: Add echo re... |
2903 |
if (rc) |
f96637be0 [CIFS] cifs: Rena... |
2904 2905 |
cifs_dbg(FYI, "Echo request failed: %d ", rc); |
9094fad1e CIFS: Add echo re... |
2906 2907 2908 2909 |
cifs_small_buf_release(req); return rc; } |
7a5cfb196 CIFS: Add SMB2 su... |
2910 2911 2912 2913 2914 |
int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) { |
40eff45b5 cifs: remove smb2... |
2915 |
struct smb_rqst rqst; |
7a5cfb196 CIFS: Add SMB2 su... |
2916 |
struct smb2_flush_req *req; |
7a5cfb196 CIFS: Add SMB2 su... |
2917 2918 |
struct cifs_ses *ses = tcon->ses; struct kvec iov[1]; |
da502f7df CIFS: Make SendRe... |
2919 |
struct kvec rsp_iov; |
7a5cfb196 CIFS: Add SMB2 su... |
2920 2921 |
int resp_buftype; int rc = 0; |
7fb8986e7 CIFS: Add capabil... |
2922 |
int flags = 0; |
1f444e4c0 cifs: remove rfc1... |
2923 |
unsigned int total_len; |
7a5cfb196 CIFS: Add SMB2 su... |
2924 |
|
f96637be0 [CIFS] cifs: Rena... |
2925 2926 |
cifs_dbg(FYI, "Flush "); |
7a5cfb196 CIFS: Add SMB2 su... |
2927 |
|
68a6afa7f cifs: Clean up un... |
2928 |
if (!ses || !(ses->server)) |
7a5cfb196 CIFS: Add SMB2 su... |
2929 |
return -EIO; |
1f444e4c0 cifs: remove rfc1... |
2930 |
rc = smb2_plain_req_init(SMB2_FLUSH, tcon, (void **) &req, &total_len); |
7a5cfb196 CIFS: Add SMB2 su... |
2931 2932 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
2933 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
2934 |
flags |= CIFS_TRANSFORM_REQ; |
7a5cfb196 CIFS: Add SMB2 su... |
2935 2936 2937 2938 |
req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; iov[0].iov_base = (char *)req; |
1f444e4c0 cifs: remove rfc1... |
2939 |
iov[0].iov_len = total_len; |
7a5cfb196 CIFS: Add SMB2 su... |
2940 |
|
40eff45b5 cifs: remove smb2... |
2941 2942 2943 2944 2945 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
2946 |
cifs_small_buf_release(req); |
7a5cfb196 CIFS: Add SMB2 su... |
2947 |
|
eccb4422c smb3: Add ftrace ... |
2948 |
if (rc != 0) { |
7a5cfb196 CIFS: Add SMB2 su... |
2949 |
cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE); |
eccb4422c smb3: Add ftrace ... |
2950 2951 2952 |
trace_smb3_flush_err(xid, persistent_fid, tcon->tid, ses->Suid, rc); } |
7a5cfb196 CIFS: Add SMB2 su... |
2953 |
|
da502f7df CIFS: Make SendRe... |
2954 |
free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
7a5cfb196 CIFS: Add SMB2 su... |
2955 2956 |
return rc; } |
09a4707e7 CIFS: Add SMB2 su... |
2957 2958 2959 2960 2961 2962 |
/* * To form a chain of read requests, any read requests after the first should * have the end_of_chain boolean set to true. */ static int |
738f9de5c CIFS: Send RFC100... |
2963 |
smb2_new_read_req(void **buf, unsigned int *total_len, |
2dabfd5ba CIFS: SMBD: Add p... |
2964 2965 |
struct cifs_io_parms *io_parms, struct cifs_readdata *rdata, unsigned int remaining_bytes, int request_type) |
09a4707e7 CIFS: Add SMB2 su... |
2966 2967 |
{ int rc = -EACCES; |
b8f57ee8a CIFS: Separate RF... |
2968 |
struct smb2_read_plain_req *req = NULL; |
31473fc4f CIFS: Separate SM... |
2969 |
struct smb2_sync_hdr *shdr; |
2dabfd5ba CIFS: SMBD: Add p... |
2970 |
struct TCP_Server_Info *server; |
09a4707e7 CIFS: Add SMB2 su... |
2971 |
|
b8f57ee8a CIFS: Separate RF... |
2972 2973 |
rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req, total_len); |
09a4707e7 CIFS: Add SMB2 su... |
2974 2975 |
if (rc) return rc; |
2dabfd5ba CIFS: SMBD: Add p... |
2976 2977 2978 |
server = io_parms->tcon->ses->server; if (server == NULL) |
09a4707e7 CIFS: Add SMB2 su... |
2979 |
return -ECONNABORTED; |
b8f57ee8a CIFS: Separate RF... |
2980 |
shdr = &req->sync_hdr; |
31473fc4f CIFS: Separate SM... |
2981 |
shdr->ProcessId = cpu_to_le32(io_parms->pid); |
09a4707e7 CIFS: Add SMB2 su... |
2982 2983 2984 2985 2986 2987 2988 2989 2990 |
req->PersistentFileId = io_parms->persistent_fid; req->VolatileFileId = io_parms->volatile_fid; req->ReadChannelInfoOffset = 0; /* reserved */ req->ReadChannelInfoLength = 0; /* reserved */ req->Channel = 0; /* reserved */ req->MinimumCount = 0; req->Length = cpu_to_le32(io_parms->length); req->Offset = cpu_to_le64(io_parms->offset); |
bd3dcc6a2 CIFS: SMBD: Upper... |
2991 2992 2993 2994 2995 |
#ifdef CONFIG_CIFS_SMB_DIRECT /* * If we want to do a RDMA write, fill in and append * smbd_buffer_descriptor_v1 to the end of read request */ |
bb4c04194 cifs: smbd: Don't... |
2996 |
if (server->rdma && rdata && !server->sign && |
bd3dcc6a2 CIFS: SMBD: Upper... |
2997 2998 2999 3000 3001 3002 3003 3004 |
rdata->bytes >= server->smbd_conn->rdma_readwrite_threshold) { struct smbd_buffer_descriptor_v1 *v1; bool need_invalidate = io_parms->tcon->ses->server->dialect == SMB30_PROT_ID; rdata->mr = smbd_register_mr( server->smbd_conn, rdata->pages, |
7cf20bce7 CIFS: SMBD: Suppo... |
3005 3006 |
rdata->nr_pages, rdata->page_offset, rdata->tailsz, true, need_invalidate); |
bd3dcc6a2 CIFS: SMBD: Upper... |
3007 3008 3009 3010 3011 3012 3013 |
if (!rdata->mr) return -ENOBUFS; req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE; if (need_invalidate) req->Channel = SMB2_CHANNEL_RDMA_V1; req->ReadChannelInfoOffset = |
2026b06e9 Cleanup some mino... |
3014 |
cpu_to_le16(offsetof(struct smb2_read_plain_req, Buffer)); |
bd3dcc6a2 CIFS: SMBD: Upper... |
3015 |
req->ReadChannelInfoLength = |
2026b06e9 Cleanup some mino... |
3016 |
cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1)); |
bd3dcc6a2 CIFS: SMBD: Upper... |
3017 |
v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0]; |
2026b06e9 Cleanup some mino... |
3018 3019 3020 |
v1->offset = cpu_to_le64(rdata->mr->mr->iova); v1->token = cpu_to_le32(rdata->mr->mr->rkey); v1->length = cpu_to_le32(rdata->mr->mr->length); |
bd3dcc6a2 CIFS: SMBD: Upper... |
3021 3022 3023 3024 |
*total_len += sizeof(*v1) - 1; } #endif |
09a4707e7 CIFS: Add SMB2 su... |
3025 3026 |
if (request_type & CHAINED_REQUEST) { if (!(request_type & END_OF_CHAIN)) { |
b8f57ee8a CIFS: Separate RF... |
3027 3028 3029 |
/* next 8-byte aligned request */ *total_len = DIV_ROUND_UP(*total_len, 8) * 8; shdr->NextCommand = cpu_to_le32(*total_len); |
09a4707e7 CIFS: Add SMB2 su... |
3030 |
} else /* END_OF_CHAIN */ |
31473fc4f CIFS: Separate SM... |
3031 |
shdr->NextCommand = 0; |
09a4707e7 CIFS: Add SMB2 su... |
3032 |
if (request_type & RELATED_REQUEST) { |
31473fc4f CIFS: Separate SM... |
3033 |
shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS; |
09a4707e7 CIFS: Add SMB2 su... |
3034 3035 3036 3037 |
/* * Related requests use info from previous read request * in chain. */ |
31473fc4f CIFS: Separate SM... |
3038 3039 |
shdr->SessionId = 0xFFFFFFFF; shdr->TreeId = 0xFFFFFFFF; |
09a4707e7 CIFS: Add SMB2 su... |
3040 3041 3042 3043 3044 3045 3046 3047 |
req->PersistentFileId = 0xFFFFFFFF; req->VolatileFileId = 0xFFFFFFFF; } } if (remaining_bytes > io_parms->length) req->RemainingBytes = cpu_to_le32(remaining_bytes); else req->RemainingBytes = 0; |
738f9de5c CIFS: Send RFC100... |
3048 |
*buf = req; |
09a4707e7 CIFS: Add SMB2 su... |
3049 3050 3051 3052 3053 3054 3055 3056 3057 |
return rc; } static void smb2_readv_callback(struct mid_q_entry *mid) { struct cifs_readdata *rdata = mid->callback_data; struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; |
738f9de5c CIFS: Send RFC100... |
3058 |
struct smb2_sync_hdr *shdr = |
977b61704 cifs: remove rfc1... |
3059 |
(struct smb2_sync_hdr *)rdata->iov[0].iov_base; |
b1765ebd9 CIFS: Do not assu... |
3060 |
unsigned int credits_received = 0; |
738f9de5c CIFS: Send RFC100... |
3061 3062 |
struct smb_rqst rqst = { .rq_iov = rdata->iov, .rq_nvec = 2, |
8321fec43 cifs: convert asy... |
3063 |
.rq_pages = rdata->pages, |
1dbe3466b CIFS: Use offset ... |
3064 |
.rq_offset = rdata->page_offset, |
8321fec43 cifs: convert asy... |
3065 3066 3067 |
.rq_npages = rdata->nr_pages, .rq_pagesz = rdata->pagesz, .rq_tailsz = rdata->tailsz }; |
09a4707e7 CIFS: Add SMB2 su... |
3068 |
|
f96637be0 [CIFS] cifs: Rena... |
3069 3070 3071 3072 |
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u ", __func__, mid->mid, mid->mid_state, rdata->result, rdata->bytes); |
09a4707e7 CIFS: Add SMB2 su... |
3073 3074 3075 |
switch (mid->mid_state) { case MID_RESPONSE_RECEIVED: |
31473fc4f CIFS: Separate SM... |
3076 |
credits_received = le16_to_cpu(shdr->CreditRequest); |
09a4707e7 CIFS: Add SMB2 su... |
3077 |
/* result already set, check signature */ |
4326ed2f6 CIFS: Decrypt and... |
3078 |
if (server->sign && !mid->decrypted) { |
3c1bf7e48 CIFS: Enable sign... |
3079 |
int rc; |
0b688cfc8 cifs: change smb2... |
3080 |
rc = smb2_verify_signature(&rqst, server); |
3c1bf7e48 CIFS: Enable sign... |
3081 |
if (rc) |
f96637be0 [CIFS] cifs: Rena... |
3082 3083 3084 |
cifs_dbg(VFS, "SMB signature verification returned error = %d ", rc); |
3c1bf7e48 CIFS: Enable sign... |
3085 |
} |
09a4707e7 CIFS: Add SMB2 su... |
3086 |
/* FIXME: should this be counted toward the initiating task? */ |
34a54d617 CIFS: Use separat... |
3087 3088 |
task_io_account_read(rdata->got_bytes); cifs_stats_bytes_read(tcon, rdata->got_bytes); |
09a4707e7 CIFS: Add SMB2 su... |
3089 3090 3091 3092 |
break; case MID_REQUEST_SUBMITTED: case MID_RETRY_NEEDED: rdata->result = -EAGAIN; |
d913ed17f CIFS: Optimize ci... |
3093 3094 3095 3096 3097 3098 |
if (server->sign && rdata->got_bytes) /* reset bytes number since we can not check a sign */ rdata->got_bytes = 0; /* FIXME: should this be counted toward the initiating task? */ task_io_account_read(rdata->got_bytes); cifs_stats_bytes_read(tcon, rdata->got_bytes); |
09a4707e7 CIFS: Add SMB2 su... |
3099 |
break; |
b1765ebd9 CIFS: Do not assu... |
3100 3101 3102 |
case MID_RESPONSE_MALFORMED: credits_received = le16_to_cpu(shdr->CreditRequest); /* fall through */ |
09a4707e7 CIFS: Add SMB2 su... |
3103 3104 3105 3106 |
default: if (rdata->result != -ENODATA) rdata->result = -EIO; } |
bd3dcc6a2 CIFS: SMBD: Upper... |
3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 |
#ifdef CONFIG_CIFS_SMB_DIRECT /* * If this rdata has a memmory registered, the MR can be freed * MR needs to be freed as soon as I/O finishes to prevent deadlock * because they have limited number and are used for future I/Os */ if (rdata->mr) { smbd_deregister_mr(rdata->mr); rdata->mr = NULL; } #endif |
e9d56f920 CIFS: Do not cons... |
3118 |
if (rdata->result && rdata->result != -ENODATA) { |
09a4707e7 CIFS: Add SMB2 su... |
3119 |
cifs_stats_fail_inc(tcon, SMB2_READ_HE); |
6e7045ec3 CIFS: Fix trace c... |
3120 3121 3122 3123 3124 3125 3126 3127 3128 |
trace_smb3_read_err(0 /* xid */, rdata->cfile->fid.persistent_fid, tcon->tid, tcon->ses->Suid, rdata->offset, rdata->bytes, rdata->result); } else trace_smb3_read_done(0 /* xid */, rdata->cfile->fid.persistent_fid, tcon->tid, tcon->ses->Suid, rdata->offset, rdata->got_bytes); |
09a4707e7 CIFS: Add SMB2 su... |
3129 3130 3131 3132 3133 |
queue_work(cifsiod_wq, &rdata->work); DeleteMidQEntry(mid); add_credits(server, credits_received, 0); } |
738f9de5c CIFS: Send RFC100... |
3134 |
/* smb2_async_readv - send an async read, and set up mid to handle result */ |
09a4707e7 CIFS: Add SMB2 su... |
3135 3136 3137 |
int smb2_async_readv(struct cifs_readdata *rdata) { |
bed9da021 CIFS: Use multicr... |
3138 |
int rc, flags = 0; |
31473fc4f CIFS: Separate SM... |
3139 3140 |
char *buf; struct smb2_sync_hdr *shdr; |
09a4707e7 CIFS: Add SMB2 su... |
3141 |
struct cifs_io_parms io_parms; |
738f9de5c CIFS: Send RFC100... |
3142 |
struct smb_rqst rqst = { .rq_iov = rdata->iov, |
c713c8770 cifs: push rfc100... |
3143 |
.rq_nvec = 1 }; |
bed9da021 CIFS: Use multicr... |
3144 |
struct TCP_Server_Info *server; |
738f9de5c CIFS: Send RFC100... |
3145 |
unsigned int total_len; |
09a4707e7 CIFS: Add SMB2 su... |
3146 |
|
f96637be0 [CIFS] cifs: Rena... |
3147 3148 3149 |
cifs_dbg(FYI, "%s: offset=%llu bytes=%u ", __func__, rdata->offset, rdata->bytes); |
09a4707e7 CIFS: Add SMB2 su... |
3150 3151 3152 3153 3154 3155 3156 |
io_parms.tcon = tlink_tcon(rdata->cfile->tlink); io_parms.offset = rdata->offset; io_parms.length = rdata->bytes; io_parms.persistent_fid = rdata->cfile->fid.persistent_fid; io_parms.volatile_fid = rdata->cfile->fid.volatile_fid; io_parms.pid = rdata->pid; |
bed9da021 CIFS: Use multicr... |
3157 3158 |
server = io_parms.tcon->ses->server; |
2dabfd5ba CIFS: SMBD: Add p... |
3159 3160 |
rc = smb2_new_read_req( (void **) &buf, &total_len, &io_parms, rdata, 0, 0); |
bed9da021 CIFS: Use multicr... |
3161 3162 3163 3164 3165 3166 3167 3168 3169 |
if (rc) { if (rc == -EAGAIN && rdata->credits) { /* credits was reset by reconnect */ rdata->credits = 0; /* reduce in_flight value since we won't send the req */ spin_lock(&server->req_lock); server->in_flight--; spin_unlock(&server->req_lock); } |
09a4707e7 CIFS: Add SMB2 su... |
3170 |
return rc; |
bed9da021 CIFS: Use multicr... |
3171 |
} |
09a4707e7 CIFS: Add SMB2 su... |
3172 |
|
5a77e75fe smb3: rename encr... |
3173 |
if (smb3_encryption_required(io_parms.tcon)) |
7fb8986e7 CIFS: Add capabil... |
3174 |
flags |= CIFS_TRANSFORM_REQ; |
c713c8770 cifs: push rfc100... |
3175 3176 |
rdata->iov[0].iov_base = buf; rdata->iov[0].iov_len = total_len; |
b8f57ee8a CIFS: Separate RF... |
3177 3178 |
shdr = (struct smb2_sync_hdr *)buf; |
09a4707e7 CIFS: Add SMB2 su... |
3179 |
|
bed9da021 CIFS: Use multicr... |
3180 |
if (rdata->credits) { |
31473fc4f CIFS: Separate SM... |
3181 |
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, |
bed9da021 CIFS: Use multicr... |
3182 |
SMB2_MAX_BUFFER_SIZE)); |
d1130682d CIFS: Fix adjustm... |
3183 3184 |
shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1); |
bed9da021 CIFS: Use multicr... |
3185 3186 |
spin_lock(&server->req_lock); server->credits += rdata->credits - |
31473fc4f CIFS: Separate SM... |
3187 |
le16_to_cpu(shdr->CreditCharge); |
bed9da021 CIFS: Use multicr... |
3188 3189 |
spin_unlock(&server->req_lock); wake_up(&server->request_q); |
d1130682d CIFS: Fix adjustm... |
3190 |
rdata->credits = le16_to_cpu(shdr->CreditCharge); |
7fb8986e7 CIFS: Add capabil... |
3191 |
flags |= CIFS_HAS_CREDITS; |
bed9da021 CIFS: Use multicr... |
3192 |
} |
09a4707e7 CIFS: Add SMB2 su... |
3193 |
kref_get(&rdata->refcount); |
fec344e3f cifs: change cifs... |
3194 |
rc = cifs_call_async(io_parms.tcon->ses->server, &rqst, |
09a4707e7 CIFS: Add SMB2 su... |
3195 |
cifs_readv_receive, smb2_readv_callback, |
4326ed2f6 CIFS: Decrypt and... |
3196 |
smb3_handle_read_data, rdata, flags); |
e5d048871 CIFS: Fix possibl... |
3197 |
if (rc) { |
09a4707e7 CIFS: Add SMB2 su... |
3198 |
kref_put(&rdata->refcount, cifs_readdata_release); |
e5d048871 CIFS: Fix possibl... |
3199 |
cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); |
6e7045ec3 CIFS: Fix trace c... |
3200 3201 3202 3203 3204 |
trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid, io_parms.tcon->tid, io_parms.tcon->ses->Suid, io_parms.offset, io_parms.length, rc); } |
09a4707e7 CIFS: Add SMB2 su... |
3205 3206 3207 3208 |
cifs_small_buf_release(buf); return rc; } |
333191412 CIFS: Add SMB2 su... |
3209 |
|
d8e050398 CIFS: Add readpag... |
3210 3211 3212 3213 |
int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, char **buf, int *buf_type) { |
40eff45b5 cifs: remove smb2... |
3214 |
struct smb_rqst rqst; |
d8e050398 CIFS: Add readpag... |
3215 |
int resp_buftype, rc = -EACCES; |
b8f57ee8a CIFS: Separate RF... |
3216 |
struct smb2_read_plain_req *req = NULL; |
d8e050398 CIFS: Add readpag... |
3217 |
struct smb2_read_rsp *rsp = NULL; |
f5688a6d7 cifs: remove rfc1... |
3218 |
struct kvec iov[1]; |
da502f7df CIFS: Make SendRe... |
3219 |
struct kvec rsp_iov; |
738f9de5c CIFS: Send RFC100... |
3220 |
unsigned int total_len; |
7fb8986e7 CIFS: Add capabil... |
3221 3222 |
int flags = CIFS_LOG_ERROR; struct cifs_ses *ses = io_parms->tcon->ses; |
d8e050398 CIFS: Add readpag... |
3223 3224 |
*nbytes = 0; |
2dabfd5ba CIFS: SMBD: Add p... |
3225 |
rc = smb2_new_read_req((void **)&req, &total_len, io_parms, NULL, 0, 0); |
d8e050398 CIFS: Add readpag... |
3226 3227 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
3228 |
if (smb3_encryption_required(io_parms->tcon)) |
7fb8986e7 CIFS: Add capabil... |
3229 |
flags |= CIFS_TRANSFORM_REQ; |
f5688a6d7 cifs: remove rfc1... |
3230 3231 |
iov[0].iov_base = (char *)req; iov[0].iov_len = total_len; |
b8f57ee8a CIFS: Separate RF... |
3232 |
|
40eff45b5 cifs: remove smb2... |
3233 3234 3235 3236 3237 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
b8f57ee8a CIFS: Separate RF... |
3238 |
cifs_small_buf_release(req); |
d8e050398 CIFS: Add readpag... |
3239 |
|
da502f7df CIFS: Make SendRe... |
3240 |
rsp = (struct smb2_read_rsp *)rsp_iov.iov_base; |
d8e050398 CIFS: Add readpag... |
3241 |
|
a821df3f1 cifs: fix NULL de... |
3242 3243 3244 3245 3246 |
if (rc) { if (rc != -ENODATA) { cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); cifs_dbg(VFS, "Send error in read = %d ", rc); |
6e7045ec3 CIFS: Fix trace c... |
3247 3248 3249 3250 |
trace_smb3_read_err(xid, req->PersistentFileId, io_parms->tcon->tid, ses->Suid, io_parms->offset, io_parms->length, rc); |
a821df3f1 cifs: fix NULL de... |
3251 |
} |
da502f7df CIFS: Make SendRe... |
3252 |
free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
a821df3f1 cifs: fix NULL de... |
3253 |
return rc == -ENODATA ? 0 : rc; |
eccb4422c smb3: Add ftrace ... |
3254 3255 3256 3257 |
} else trace_smb3_read_done(xid, req->PersistentFileId, io_parms->tcon->tid, ses->Suid, io_parms->offset, io_parms->length); |
d8e050398 CIFS: Add readpag... |
3258 |
|
a821df3f1 cifs: fix NULL de... |
3259 3260 3261 3262 3263 3264 3265 3266 |
*nbytes = le32_to_cpu(rsp->DataLength); if ((*nbytes > CIFS_MAX_MSGSIZE) || (*nbytes > io_parms->length)) { cifs_dbg(FYI, "bad length %d for count %d ", *nbytes, io_parms->length); rc = -EIO; *nbytes = 0; |
d8e050398 CIFS: Add readpag... |
3267 3268 3269 |
} if (*buf) { |
977b61704 cifs: remove rfc1... |
3270 |
memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes); |
da502f7df CIFS: Make SendRe... |
3271 |
free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
d8e050398 CIFS: Add readpag... |
3272 |
} else if (resp_buftype != CIFS_NO_BUFFER) { |
da502f7df CIFS: Make SendRe... |
3273 |
*buf = rsp_iov.iov_base; |
d8e050398 CIFS: Add readpag... |
3274 3275 3276 3277 3278 3279 3280 |
if (resp_buftype == CIFS_SMALL_BUFFER) *buf_type = CIFS_SMALL_BUFFER; else if (resp_buftype == CIFS_LARGE_BUFFER) *buf_type = CIFS_LARGE_BUFFER; } return rc; } |
333191412 CIFS: Add SMB2 su... |
3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 |
/* * Check the mid_state and signature on received buffer (if any), and queue the * workqueue completion task. */ static void smb2_writev_callback(struct mid_q_entry *mid) { struct cifs_writedata *wdata = mid->callback_data; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); unsigned int written; struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; |
b1765ebd9 CIFS: Do not assu... |
3292 |
unsigned int credits_received = 0; |
333191412 CIFS: Add SMB2 su... |
3293 3294 3295 |
switch (mid->mid_state) { case MID_RESPONSE_RECEIVED: |
49f466bdb cifs: remove stru... |
3296 |
credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); |
333191412 CIFS: Add SMB2 su... |
3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 |
wdata->result = smb2_check_receive(mid, tcon->ses->server, 0); if (wdata->result != 0) break; written = le32_to_cpu(rsp->DataLength); /* * Mask off high 16 bits when bytes written as returned * by the server is greater than bytes requested by the * client. OS/2 servers are known to set incorrect * CountHigh values. */ if (written > wdata->bytes) written &= 0xFFFF; if (written < wdata->bytes) wdata->result = -ENOSPC; else wdata->bytes = written; break; case MID_REQUEST_SUBMITTED: case MID_RETRY_NEEDED: wdata->result = -EAGAIN; break; |
b1765ebd9 CIFS: Do not assu... |
3320 3321 3322 |
case MID_RESPONSE_MALFORMED: credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); /* fall through */ |
333191412 CIFS: Add SMB2 su... |
3323 3324 3325 3326 |
default: wdata->result = -EIO; break; } |
db223a590 CIFS: SMBD: Upper... |
3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 |
#ifdef CONFIG_CIFS_SMB_DIRECT /* * If this wdata has a memory registered, the MR can be freed * The number of MRs available is limited, it's important to recover * used MR as soon as I/O is finished. Hold MR longer in the later * I/O process can possibly result in I/O deadlock due to lack of MR * to send request on I/O retry */ if (wdata->mr) { smbd_deregister_mr(wdata->mr); wdata->mr = NULL; } #endif |
6e7045ec3 CIFS: Fix trace c... |
3340 |
if (wdata->result) { |
333191412 CIFS: Add SMB2 su... |
3341 |
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); |
6e7045ec3 CIFS: Fix trace c... |
3342 3343 3344 3345 3346 3347 3348 3349 3350 |
trace_smb3_write_err(0 /* no xid */, wdata->cfile->fid.persistent_fid, tcon->tid, tcon->ses->Suid, wdata->offset, wdata->bytes, wdata->result); } else trace_smb3_write_done(0 /* no xid */, wdata->cfile->fid.persistent_fid, tcon->tid, tcon->ses->Suid, wdata->offset, wdata->bytes); |
333191412 CIFS: Add SMB2 su... |
3351 3352 3353 3354 3355 3356 3357 3358 |
queue_work(cifsiod_wq, &wdata->work); DeleteMidQEntry(mid); add_credits(tcon->ses->server, credits_received, 0); } /* smb2_async_writev - send an async write, and set up mid to handle result */ int |
4a5c80d7b [CIFS] clean up p... |
3359 3360 |
smb2_async_writev(struct cifs_writedata *wdata, void (*release)(struct kref *kref)) |
333191412 CIFS: Add SMB2 su... |
3361 |
{ |
cb7e9eabb CIFS: Use multicr... |
3362 |
int rc = -EACCES, flags = 0; |
333191412 CIFS: Add SMB2 su... |
3363 |
struct smb2_write_req *req = NULL; |
31473fc4f CIFS: Separate SM... |
3364 |
struct smb2_sync_hdr *shdr; |
333191412 CIFS: Add SMB2 su... |
3365 |
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); |
cb7e9eabb CIFS: Use multicr... |
3366 |
struct TCP_Server_Info *server = tcon->ses->server; |
c713c8770 cifs: push rfc100... |
3367 |
struct kvec iov[1]; |
738f9de5c CIFS: Send RFC100... |
3368 |
struct smb_rqst rqst = { }; |
f5688a6d7 cifs: remove rfc1... |
3369 |
unsigned int total_len; |
333191412 CIFS: Add SMB2 su... |
3370 |
|
f5688a6d7 cifs: remove rfc1... |
3371 |
rc = smb2_plain_req_init(SMB2_WRITE, tcon, (void **) &req, &total_len); |
cb7e9eabb CIFS: Use multicr... |
3372 3373 3374 3375 3376 3377 3378 3379 3380 |
if (rc) { if (rc == -EAGAIN && wdata->credits) { /* credits was reset by reconnect */ wdata->credits = 0; /* reduce in_flight value since we won't send the req */ spin_lock(&server->req_lock); server->in_flight--; spin_unlock(&server->req_lock); } |
333191412 CIFS: Add SMB2 su... |
3381 |
goto async_writev_out; |
cb7e9eabb CIFS: Use multicr... |
3382 |
} |
333191412 CIFS: Add SMB2 su... |
3383 |
|
5a77e75fe smb3: rename encr... |
3384 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
3385 |
flags |= CIFS_TRANSFORM_REQ; |
f5688a6d7 cifs: remove rfc1... |
3386 |
shdr = (struct smb2_sync_hdr *)req; |
31473fc4f CIFS: Separate SM... |
3387 |
shdr->ProcessId = cpu_to_le32(wdata->cfile->pid); |
333191412 CIFS: Add SMB2 su... |
3388 3389 3390 3391 3392 3393 3394 |
req->PersistentFileId = wdata->cfile->fid.persistent_fid; req->VolatileFileId = wdata->cfile->fid.volatile_fid; req->WriteChannelInfoOffset = 0; req->WriteChannelInfoLength = 0; req->Channel = 0; req->Offset = cpu_to_le64(wdata->offset); |
333191412 CIFS: Add SMB2 su... |
3395 |
req->DataOffset = cpu_to_le16( |
f5688a6d7 cifs: remove rfc1... |
3396 |
offsetof(struct smb2_write_req, Buffer)); |
333191412 CIFS: Add SMB2 su... |
3397 |
req->RemainingBytes = 0; |
db223a590 CIFS: SMBD: Upper... |
3398 3399 3400 3401 3402 |
#ifdef CONFIG_CIFS_SMB_DIRECT /* * If we want to do a server RDMA read, fill in and append * smbd_buffer_descriptor_v1 to the end of write request */ |
bb4c04194 cifs: smbd: Don't... |
3403 |
if (server->rdma && !server->sign && wdata->bytes >= |
db223a590 CIFS: SMBD: Upper... |
3404 3405 3406 3407 3408 3409 3410 |
server->smbd_conn->rdma_readwrite_threshold) { struct smbd_buffer_descriptor_v1 *v1; bool need_invalidate = server->dialect == SMB30_PROT_ID; wdata->mr = smbd_register_mr( server->smbd_conn, wdata->pages, |
7cf20bce7 CIFS: SMBD: Suppo... |
3411 3412 |
wdata->nr_pages, wdata->page_offset, wdata->tailsz, false, need_invalidate); |
db223a590 CIFS: SMBD: Upper... |
3413 3414 3415 3416 3417 3418 |
if (!wdata->mr) { rc = -ENOBUFS; goto async_writev_out; } req->Length = 0; req->DataOffset = 0; |
7cf20bce7 CIFS: SMBD: Suppo... |
3419 3420 3421 3422 3423 3424 3425 3426 |
if (wdata->nr_pages > 1) req->RemainingBytes = cpu_to_le32( (wdata->nr_pages - 1) * wdata->pagesz - wdata->page_offset + wdata->tailsz ); else req->RemainingBytes = cpu_to_le32(wdata->tailsz); |
db223a590 CIFS: SMBD: Upper... |
3427 3428 3429 3430 |
req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE; if (need_invalidate) req->Channel = SMB2_CHANNEL_RDMA_V1; req->WriteChannelInfoOffset = |
2026b06e9 Cleanup some mino... |
3431 |
cpu_to_le16(offsetof(struct smb2_write_req, Buffer)); |
db223a590 CIFS: SMBD: Upper... |
3432 |
req->WriteChannelInfoLength = |
2026b06e9 Cleanup some mino... |
3433 |
cpu_to_le16(sizeof(struct smbd_buffer_descriptor_v1)); |
db223a590 CIFS: SMBD: Upper... |
3434 |
v1 = (struct smbd_buffer_descriptor_v1 *) &req->Buffer[0]; |
2026b06e9 Cleanup some mino... |
3435 3436 3437 |
v1->offset = cpu_to_le64(wdata->mr->mr->iova); v1->token = cpu_to_le32(wdata->mr->mr->rkey); v1->length = cpu_to_le32(wdata->mr->mr->length); |
db223a590 CIFS: SMBD: Upper... |
3438 3439 |
} #endif |
c713c8770 cifs: push rfc100... |
3440 3441 |
iov[0].iov_len = total_len - 1; iov[0].iov_base = (char *)req; |
333191412 CIFS: Add SMB2 su... |
3442 |
|
738f9de5c CIFS: Send RFC100... |
3443 |
rqst.rq_iov = iov; |
c713c8770 cifs: push rfc100... |
3444 |
rqst.rq_nvec = 1; |
eddb079de cifs: convert asy... |
3445 |
rqst.rq_pages = wdata->pages; |
57a929a66 CIFS: Introduce o... |
3446 |
rqst.rq_offset = wdata->page_offset; |
eddb079de cifs: convert asy... |
3447 3448 3449 |
rqst.rq_npages = wdata->nr_pages; rqst.rq_pagesz = wdata->pagesz; rqst.rq_tailsz = wdata->tailsz; |
db223a590 CIFS: SMBD: Upper... |
3450 3451 |
#ifdef CONFIG_CIFS_SMB_DIRECT if (wdata->mr) { |
c713c8770 cifs: push rfc100... |
3452 |
iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1); |
db223a590 CIFS: SMBD: Upper... |
3453 3454 3455 |
rqst.rq_npages = 0; } #endif |
f96637be0 [CIFS] cifs: Rena... |
3456 3457 3458 |
cifs_dbg(FYI, "async write at %llu %u bytes ", wdata->offset, wdata->bytes); |
333191412 CIFS: Add SMB2 su... |
3459 |
|
db223a590 CIFS: SMBD: Upper... |
3460 3461 3462 3463 3464 |
#ifdef CONFIG_CIFS_SMB_DIRECT /* For RDMA read, I/O size is in RemainingBytes not in Length */ if (!wdata->mr) req->Length = cpu_to_le32(wdata->bytes); #else |
333191412 CIFS: Add SMB2 su... |
3465 |
req->Length = cpu_to_le32(wdata->bytes); |
db223a590 CIFS: SMBD: Upper... |
3466 |
#endif |
333191412 CIFS: Add SMB2 su... |
3467 |
|
cb7e9eabb CIFS: Use multicr... |
3468 |
if (wdata->credits) { |
31473fc4f CIFS: Separate SM... |
3469 |
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, |
cb7e9eabb CIFS: Use multicr... |
3470 |
SMB2_MAX_BUFFER_SIZE)); |
d1130682d CIFS: Fix adjustm... |
3471 3472 |
shdr->CreditRequest = cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1); |
cb7e9eabb CIFS: Use multicr... |
3473 3474 |
spin_lock(&server->req_lock); server->credits += wdata->credits - |
31473fc4f CIFS: Separate SM... |
3475 |
le16_to_cpu(shdr->CreditCharge); |
cb7e9eabb CIFS: Use multicr... |
3476 3477 |
spin_unlock(&server->req_lock); wake_up(&server->request_q); |
d1130682d CIFS: Fix adjustm... |
3478 |
wdata->credits = le16_to_cpu(shdr->CreditCharge); |
7fb8986e7 CIFS: Add capabil... |
3479 |
flags |= CIFS_HAS_CREDITS; |
cb7e9eabb CIFS: Use multicr... |
3480 |
} |
333191412 CIFS: Add SMB2 su... |
3481 |
kref_get(&wdata->refcount); |
9b7c18a2d CIFS: Add mid han... |
3482 3483 |
rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL, wdata, flags); |
333191412 CIFS: Add SMB2 su... |
3484 |
|
e5d048871 CIFS: Fix possibl... |
3485 |
if (rc) { |
eccb4422c smb3: Add ftrace ... |
3486 3487 3488 |
trace_smb3_write_err(0 /* no xid */, req->PersistentFileId, tcon->tid, tcon->ses->Suid, wdata->offset, wdata->bytes, rc); |
4a5c80d7b [CIFS] clean up p... |
3489 |
kref_put(&wdata->refcount, release); |
e5d048871 CIFS: Fix possibl... |
3490 |
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); |
6e7045ec3 CIFS: Fix trace c... |
3491 |
} |
333191412 CIFS: Add SMB2 su... |
3492 |
|
333191412 CIFS: Add SMB2 su... |
3493 3494 |
async_writev_out: cifs_small_buf_release(req); |
333191412 CIFS: Add SMB2 su... |
3495 3496 |
return rc; } |
009d34439 CIFS: Add writepa... |
3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 |
/* * SMB2_write function gets iov pointer to kvec array with n_vec as a length. * The length field from io_parms must be at least 1 and indicates a number of * elements with data to write that begins with position 1 in iov array. All * data length is specified by count. */ int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, struct kvec *iov, int n_vec) { |
40eff45b5 cifs: remove smb2... |
3508 |
struct smb_rqst rqst; |
009d34439 CIFS: Add writepa... |
3509 3510 3511 3512 |
int rc = 0; struct smb2_write_req *req = NULL; struct smb2_write_rsp *rsp = NULL; int resp_buftype; |
da502f7df CIFS: Make SendRe... |
3513 |
struct kvec rsp_iov; |
7fb8986e7 CIFS: Add capabil... |
3514 |
int flags = 0; |
f5688a6d7 cifs: remove rfc1... |
3515 |
unsigned int total_len; |
da502f7df CIFS: Make SendRe... |
3516 |
|
009d34439 CIFS: Add writepa... |
3517 3518 3519 3520 |
*nbytes = 0; if (n_vec < 1) return rc; |
f5688a6d7 cifs: remove rfc1... |
3521 3522 |
rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, (void **) &req, &total_len); |
009d34439 CIFS: Add writepa... |
3523 3524 3525 3526 3527 |
if (rc) return rc; if (io_parms->tcon->ses->server == NULL) return -ECONNABORTED; |
5a77e75fe smb3: rename encr... |
3528 |
if (smb3_encryption_required(io_parms->tcon)) |
7fb8986e7 CIFS: Add capabil... |
3529 |
flags |= CIFS_TRANSFORM_REQ; |
f5688a6d7 cifs: remove rfc1... |
3530 |
req->sync_hdr.ProcessId = cpu_to_le32(io_parms->pid); |
009d34439 CIFS: Add writepa... |
3531 3532 3533 3534 3535 3536 3537 3538 |
req->PersistentFileId = io_parms->persistent_fid; req->VolatileFileId = io_parms->volatile_fid; req->WriteChannelInfoOffset = 0; req->WriteChannelInfoLength = 0; req->Channel = 0; req->Length = cpu_to_le32(io_parms->length); req->Offset = cpu_to_le64(io_parms->offset); |
009d34439 CIFS: Add writepa... |
3539 |
req->DataOffset = cpu_to_le16( |
f5688a6d7 cifs: remove rfc1... |
3540 |
offsetof(struct smb2_write_req, Buffer)); |
009d34439 CIFS: Add writepa... |
3541 3542 3543 |
req->RemainingBytes = 0; iov[0].iov_base = (char *)req; |
f5688a6d7 cifs: remove rfc1... |
3544 3545 |
/* 1 for Buffer */ iov[0].iov_len = total_len - 1; |
009d34439 CIFS: Add writepa... |
3546 |
|
40eff45b5 cifs: remove smb2... |
3547 3548 3549 3550 3551 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = n_vec + 1; rc = cifs_send_recv(xid, io_parms->tcon->ses, &rqst, |
f5688a6d7 cifs: remove rfc1... |
3552 |
&resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
3553 3554 |
cifs_small_buf_release(req); rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; |
009d34439 CIFS: Add writepa... |
3555 3556 |
if (rc) { |
eccb4422c smb3: Add ftrace ... |
3557 3558 3559 3560 |
trace_smb3_write_err(xid, req->PersistentFileId, io_parms->tcon->tid, io_parms->tcon->ses->Suid, io_parms->offset, io_parms->length, rc); |
009d34439 CIFS: Add writepa... |
3561 |
cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE); |
f96637be0 [CIFS] cifs: Rena... |
3562 3563 |
cifs_dbg(VFS, "Send error in write = %d ", rc); |
eccb4422c smb3: Add ftrace ... |
3564 |
} else { |
009d34439 CIFS: Add writepa... |
3565 |
*nbytes = le32_to_cpu(rsp->DataLength); |
eccb4422c smb3: Add ftrace ... |
3566 3567 3568 3569 3570 |
trace_smb3_write_done(xid, req->PersistentFileId, io_parms->tcon->tid, io_parms->tcon->ses->Suid, io_parms->offset, *nbytes); } |
e5d048871 CIFS: Fix possibl... |
3571 3572 |
free_rsp_buf(resp_buftype, rsp); |
009d34439 CIFS: Add writepa... |
3573 3574 |
return rc; } |
35143eb5c CIFS: Add SMB2 su... |
3575 |
|
d324f08d6 CIFS: Add readdir... |
3576 3577 3578 3579 3580 3581 |
static unsigned int num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size) { int len; unsigned int entrycount = 0; unsigned int next_offset = 0; |
56446f218 CIFS: fix wrappin... |
3582 3583 |
char *entryptr; FILE_DIRECTORY_INFO *dir_info; |
d324f08d6 CIFS: Add readdir... |
3584 3585 3586 |
if (bufstart == NULL) return 0; |
56446f218 CIFS: fix wrappin... |
3587 |
entryptr = bufstart; |
d324f08d6 CIFS: Add readdir... |
3588 3589 |
while (1) { |
56446f218 CIFS: fix wrappin... |
3590 3591 3592 |
if (entryptr + next_offset < entryptr || entryptr + next_offset > end_of_buf || entryptr + next_offset + size > end_of_buf) { |
f96637be0 [CIFS] cifs: Rena... |
3593 3594 |
cifs_dbg(VFS, "malformed search entry would overflow "); |
d324f08d6 CIFS: Add readdir... |
3595 3596 |
break; } |
56446f218 CIFS: fix wrappin... |
3597 3598 3599 3600 3601 3602 3603 |
entryptr = entryptr + next_offset; dir_info = (FILE_DIRECTORY_INFO *)entryptr; len = le32_to_cpu(dir_info->FileNameLength); if (entryptr + len < entryptr || entryptr + len > end_of_buf || entryptr + len + size > end_of_buf) { |
f96637be0 [CIFS] cifs: Rena... |
3604 3605 3606 |
cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p ", end_of_buf); |
d324f08d6 CIFS: Add readdir... |
3607 3608 |
break; } |
56446f218 CIFS: fix wrappin... |
3609 |
*lastentry = entryptr; |
d324f08d6 CIFS: Add readdir... |
3610 |
entrycount++; |
56446f218 CIFS: fix wrappin... |
3611 |
next_offset = le32_to_cpu(dir_info->NextEntryOffset); |
d324f08d6 CIFS: Add readdir... |
3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 |
if (!next_offset) break; } return entrycount; } /* * Readdir/FindFirst */ int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, int index, struct cifs_search_info *srch_inf) { |
40eff45b5 cifs: remove smb2... |
3627 |
struct smb_rqst rqst; |
d324f08d6 CIFS: Add readdir... |
3628 3629 3630 |
struct smb2_query_directory_req *req; struct smb2_query_directory_rsp *rsp = NULL; struct kvec iov[2]; |
da502f7df CIFS: Make SendRe... |
3631 |
struct kvec rsp_iov; |
d324f08d6 CIFS: Add readdir... |
3632 3633 |
int rc = 0; int len; |
75fdfc849 Fix warning on un... |
3634 |
int resp_buftype = CIFS_NO_BUFFER; |
d324f08d6 CIFS: Add readdir... |
3635 3636 3637 3638 3639 3640 3641 |
unsigned char *bufptr; struct TCP_Server_Info *server; struct cifs_ses *ses = tcon->ses; __le16 asteriks = cpu_to_le16('*'); char *end_of_smb; unsigned int output_size = CIFSMaxBufSize; size_t info_buf_size; |
7fb8986e7 CIFS: Add capabil... |
3642 |
int flags = 0; |
7c00c3a62 cifs: remove rfc1... |
3643 |
unsigned int total_len; |
d324f08d6 CIFS: Add readdir... |
3644 3645 3646 3647 3648 |
if (ses && (ses->server)) server = ses->server; else return -EIO; |
7c00c3a62 cifs: remove rfc1... |
3649 3650 |
rc = smb2_plain_req_init(SMB2_QUERY_DIRECTORY, tcon, (void **) &req, &total_len); |
d324f08d6 CIFS: Add readdir... |
3651 3652 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
3653 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
3654 |
flags |= CIFS_TRANSFORM_REQ; |
d324f08d6 CIFS: Add readdir... |
3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 |
switch (srch_inf->info_level) { case SMB_FIND_FILE_DIRECTORY_INFO: req->FileInformationClass = FILE_DIRECTORY_INFORMATION; info_buf_size = sizeof(FILE_DIRECTORY_INFO) - 1; break; case SMB_FIND_FILE_ID_FULL_DIR_INFO: req->FileInformationClass = FILEID_FULL_DIRECTORY_INFORMATION; info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO) - 1; break; default: |
f96637be0 [CIFS] cifs: Rena... |
3665 3666 3667 |
cifs_dbg(VFS, "info level %u isn't supported ", srch_inf->info_level); |
d324f08d6 CIFS: Add readdir... |
3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 |
rc = -EINVAL; goto qdir_exit; } req->FileIndex = cpu_to_le32(index); req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; len = 0x2; bufptr = req->Buffer; memcpy(bufptr, &asteriks, len); req->FileNameOffset = |
7c00c3a62 cifs: remove rfc1... |
3681 |
cpu_to_le16(sizeof(struct smb2_query_directory_req) - 1); |
d324f08d6 CIFS: Add readdir... |
3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 |
req->FileNameLength = cpu_to_le16(len); /* * BB could be 30 bytes or so longer if we used SMB2 specific * buffer lengths, but this is safe and close enough. */ output_size = min_t(unsigned int, output_size, server->maxBuf); output_size = min_t(unsigned int, output_size, 2 << 15); req->OutputBufferLength = cpu_to_le32(output_size); iov[0].iov_base = (char *)req; |
7c00c3a62 cifs: remove rfc1... |
3692 3693 |
/* 1 for Buffer */ iov[0].iov_len = total_len - 1; |
d324f08d6 CIFS: Add readdir... |
3694 3695 3696 |
iov[1].iov_base = (char *)(req->Buffer); iov[1].iov_len = len; |
40eff45b5 cifs: remove smb2... |
3697 3698 3699 3700 3701 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 2; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
3702 3703 |
cifs_small_buf_release(req); rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; |
e5d048871 CIFS: Fix possibl... |
3704 |
|
d324f08d6 CIFS: Add readdir... |
3705 |
if (rc) { |
31473fc4f CIFS: Separate SM... |
3706 |
if (rc == -ENODATA && |
49f466bdb cifs: remove stru... |
3707 |
rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { |
52755808d CIFS: Fix SMB2 re... |
3708 3709 |
srch_inf->endOfSearch = true; rc = 0; |
c6961288a CIFS: Do not coun... |
3710 3711 |
} else cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); |
d324f08d6 CIFS: Add readdir... |
3712 3713 |
goto qdir_exit; } |
d324f08d6 CIFS: Add readdir... |
3714 |
|
730928c8f cifs: update smb2... |
3715 3716 3717 |
rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset), le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, info_buf_size); |
d324f08d6 CIFS: Add readdir... |
3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 |
if (rc) goto qdir_exit; srch_inf->unicode = true; if (srch_inf->ntwrk_buf_start) { if (srch_inf->smallBuf) cifs_small_buf_release(srch_inf->ntwrk_buf_start); else cifs_buf_release(srch_inf->ntwrk_buf_start); } srch_inf->ntwrk_buf_start = (char *)rsp; |
977b61704 cifs: remove rfc1... |
3730 3731 3732 |
srch_inf->srch_entries_start = srch_inf->last_entry = (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset); end_of_smb = rsp_iov.iov_len + (char *)rsp; |
d324f08d6 CIFS: Add readdir... |
3733 3734 3735 3736 |
srch_inf->entries_in_buffer = num_entries(srch_inf->srch_entries_start, end_of_smb, &srch_inf->last_entry, info_buf_size); srch_inf->index_of_last_entry += srch_inf->entries_in_buffer; |
f96637be0 [CIFS] cifs: Rena... |
3737 3738 3739 3740 |
cifs_dbg(FYI, "num entries %d last_index %lld srch start %p srch end %p ", srch_inf->entries_in_buffer, srch_inf->index_of_last_entry, srch_inf->srch_entries_start, srch_inf->last_entry); |
d324f08d6 CIFS: Add readdir... |
3741 3742 3743 3744 3745 |
if (resp_buftype == CIFS_LARGE_BUFFER) srch_inf->smallBuf = false; else if (resp_buftype == CIFS_SMALL_BUFFER) srch_inf->smallBuf = true; else |
f96637be0 [CIFS] cifs: Rena... |
3746 3747 |
cifs_dbg(VFS, "illegal search buffer type "); |
d324f08d6 CIFS: Add readdir... |
3748 |
|
d324f08d6 CIFS: Add readdir... |
3749 3750 3751 3752 3753 3754 |
return rc; qdir_exit: free_rsp_buf(resp_buftype, rsp); return rc; } |
35143eb5c CIFS: Add SMB2 su... |
3755 3756 |
static int send_set_info(const unsigned int xid, struct cifs_tcon *tcon, |
dac953401 cifs: prototype d... |
3757 3758 3759 |
u64 persistent_fid, u64 volatile_fid, u32 pid, u8 info_class, u8 info_type, u32 additional_info, unsigned int num, void **data, unsigned int *size) |
35143eb5c CIFS: Add SMB2 su... |
3760 |
{ |
40eff45b5 cifs: remove smb2... |
3761 |
struct smb_rqst rqst; |
35143eb5c CIFS: Add SMB2 su... |
3762 3763 3764 |
struct smb2_set_info_req *req; struct smb2_set_info_rsp *rsp = NULL; struct kvec *iov; |
da502f7df CIFS: Make SendRe... |
3765 |
struct kvec rsp_iov; |
35143eb5c CIFS: Add SMB2 su... |
3766 3767 3768 |
int rc = 0; int resp_buftype; unsigned int i; |
35143eb5c CIFS: Add SMB2 su... |
3769 |
struct cifs_ses *ses = tcon->ses; |
7fb8986e7 CIFS: Add capabil... |
3770 |
int flags = 0; |
2fc803efe cifs: remove rfc1... |
3771 |
unsigned int total_len; |
35143eb5c CIFS: Add SMB2 su... |
3772 |
|
68a6afa7f cifs: Clean up un... |
3773 |
if (!ses || !(ses->server)) |
35143eb5c CIFS: Add SMB2 su... |
3774 3775 3776 3777 |
return -EIO; if (!num) return -EINVAL; |
6da2ec560 treewide: kmalloc... |
3778 |
iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL); |
35143eb5c CIFS: Add SMB2 su... |
3779 3780 |
if (!iov) return -ENOMEM; |
2fc803efe cifs: remove rfc1... |
3781 |
rc = smb2_plain_req_init(SMB2_SET_INFO, tcon, (void **) &req, &total_len); |
35143eb5c CIFS: Add SMB2 su... |
3782 3783 3784 3785 |
if (rc) { kfree(iov); return rc; } |
5a77e75fe smb3: rename encr... |
3786 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
3787 |
flags |= CIFS_TRANSFORM_REQ; |
2fc803efe cifs: remove rfc1... |
3788 |
req->sync_hdr.ProcessId = cpu_to_le32(pid); |
c839ff244 CIFS: Add SMB2 su... |
3789 |
|
dac953401 cifs: prototype d... |
3790 |
req->InfoType = info_type; |
35143eb5c CIFS: Add SMB2 su... |
3791 3792 3793 |
req->FileInfoClass = info_class; req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; |
dac953401 cifs: prototype d... |
3794 |
req->AdditionalInformation = cpu_to_le32(additional_info); |
35143eb5c CIFS: Add SMB2 su... |
3795 |
|
35143eb5c CIFS: Add SMB2 su... |
3796 |
req->BufferOffset = |
2fc803efe cifs: remove rfc1... |
3797 |
cpu_to_le16(sizeof(struct smb2_set_info_req) - 1); |
35143eb5c CIFS: Add SMB2 su... |
3798 |
req->BufferLength = cpu_to_le32(*size); |
35143eb5c CIFS: Add SMB2 su... |
3799 |
memcpy(req->Buffer, *data, *size); |
2fc803efe cifs: remove rfc1... |
3800 |
total_len += *size; |
35143eb5c CIFS: Add SMB2 su... |
3801 3802 |
iov[0].iov_base = (char *)req; |
2fc803efe cifs: remove rfc1... |
3803 3804 |
/* 1 for Buffer */ iov[0].iov_len = total_len - 1; |
35143eb5c CIFS: Add SMB2 su... |
3805 3806 |
for (i = 1; i < num; i++) { |
35143eb5c CIFS: Add SMB2 su... |
3807 3808 3809 3810 |
le32_add_cpu(&req->BufferLength, size[i]); iov[i].iov_base = (char *)data[i]; iov[i].iov_len = size[i]; } |
40eff45b5 cifs: remove smb2... |
3811 3812 3813 3814 3815 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = num; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, |
2fc803efe cifs: remove rfc1... |
3816 |
&rsp_iov); |
f46ecbd97 cifs: Fix slab-ou... |
3817 |
cifs_buf_release(req); |
da502f7df CIFS: Make SendRe... |
3818 |
rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base; |
35143eb5c CIFS: Add SMB2 su... |
3819 |
|
eccb4422c smb3: Add ftrace ... |
3820 |
if (rc != 0) { |
35143eb5c CIFS: Add SMB2 su... |
3821 |
cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE); |
eccb4422c smb3: Add ftrace ... |
3822 3823 3824 |
trace_smb3_set_info_err(xid, persistent_fid, tcon->tid, ses->Suid, info_class, (__u32)info_type, rc); } |
7d3fb24bc Removed duplicate... |
3825 |
|
35143eb5c CIFS: Add SMB2 su... |
3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 |
free_rsp_buf(resp_buftype, rsp); kfree(iov); return rc; } int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, __le16 *target_file) { struct smb2_file_rename_info info; void **data; unsigned int size[2]; int rc; int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX)); |
6da2ec560 treewide: kmalloc... |
3840 |
data = kmalloc_array(2, sizeof(void *), GFP_KERNEL); |
35143eb5c CIFS: Add SMB2 su... |
3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 |
if (!data) return -ENOMEM; info.ReplaceIfExists = 1; /* 1 = replace existing target with new */ /* 0 = fail if target already exists */ info.RootDirectory = 0; /* MBZ for network ops (why does spec say?) */ info.FileNameLength = cpu_to_le32(len); data[0] = &info; size[0] = sizeof(struct smb2_file_rename_info); data[1] = target_file; size[1] = len + 2 /* null */; rc = send_set_info(xid, tcon, persistent_fid, volatile_fid, |
dac953401 cifs: prototype d... |
3856 3857 |
current->tgid, FILE_RENAME_INFORMATION, SMB2_O_INFO_FILE, 0, 2, data, size); |
35143eb5c CIFS: Add SMB2 su... |
3858 3859 3860 |
kfree(data); return rc; } |
568798cc6 CIFS: Add SMB2 su... |
3861 3862 |
int |
897fba117 remove directory ... |
3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 |
SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) { __u8 delete_pending = 1; void *data; unsigned int size; data = &delete_pending; size = 1; /* sizeof __u8 */ return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
dac953401 cifs: prototype d... |
3874 3875 |
current->tgid, FILE_DISPOSITION_INFORMATION, SMB2_O_INFO_FILE, 0, 1, &data, &size); |
897fba117 remove directory ... |
3876 3877 3878 |
} int |
568798cc6 CIFS: Add SMB2 su... |
3879 3880 3881 3882 3883 3884 3885 3886 |
SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, __le16 *target_file) { struct smb2_file_link_info info; void **data; unsigned int size[2]; int rc; int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX)); |
6da2ec560 treewide: kmalloc... |
3887 |
data = kmalloc_array(2, sizeof(void *), GFP_KERNEL); |
568798cc6 CIFS: Add SMB2 su... |
3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 |
if (!data) return -ENOMEM; info.ReplaceIfExists = 0; /* 1 = replace existing link with new */ /* 0 = fail if link already exists */ info.RootDirectory = 0; /* MBZ for network ops (why does spec say?) */ info.FileNameLength = cpu_to_le32(len); data[0] = &info; size[0] = sizeof(struct smb2_file_link_info); data[1] = target_file; size[1] = len + 2 /* null */; rc = send_set_info(xid, tcon, persistent_fid, volatile_fid, |
dac953401 cifs: prototype d... |
3903 3904 |
current->tgid, FILE_LINK_INFORMATION, SMB2_O_INFO_FILE, 0, 2, data, size); |
568798cc6 CIFS: Add SMB2 su... |
3905 3906 3907 |
kfree(data); return rc; } |
c839ff244 CIFS: Add SMB2 su... |
3908 3909 3910 |
int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, |
f29ebb47d Add worker functi... |
3911 |
u64 volatile_fid, u32 pid, __le64 *eof, bool is_falloc) |
c839ff244 CIFS: Add SMB2 su... |
3912 3913 3914 3915 3916 3917 3918 3919 3920 |
{ struct smb2_file_eof_info info; void *data; unsigned int size; info.EndOfFile = *eof; data = &info; size = sizeof(struct smb2_file_eof_info); |
f29ebb47d Add worker functi... |
3921 3922 |
if (is_falloc) return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
dac953401 cifs: prototype d... |
3923 3924 |
pid, FILE_ALLOCATION_INFORMATION, SMB2_O_INFO_FILE, 0, 1, &data, &size); |
f29ebb47d Add worker functi... |
3925 3926 |
else return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
dac953401 cifs: prototype d... |
3927 3928 |
pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE, 0, 1, &data, &size); |
c839ff244 CIFS: Add SMB2 su... |
3929 |
} |
1feeaac75 CIFS: Add set_fil... |
3930 3931 3932 3933 3934 3935 3936 3937 |
int SMB2_set_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, FILE_BASIC_INFO *buf) { unsigned int size; size = sizeof(FILE_BASIC_INFO); return send_set_info(xid, tcon, persistent_fid, volatile_fid, |
dac953401 cifs: prototype d... |
3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 |
current->tgid, FILE_BASIC_INFORMATION, SMB2_O_INFO_FILE, 0, 1, (void **)&buf, &size); } int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, struct cifs_ntsd *pnntsd, int pacllen, int aclflag) { return send_set_info(xid, tcon, persistent_fid, volatile_fid, current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag, 1, (void **)&pnntsd, &pacllen); |
1feeaac75 CIFS: Add set_fil... |
3950 |
} |
983c88a49 CIFS: Add oplock ... |
3951 3952 |
int |
5517554e4 cifs: Add support... |
3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 |
SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, struct smb2_file_full_ea_info *buf, int len) { return send_set_info(xid, tcon, persistent_fid, volatile_fid, current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, 1, (void **)&buf, &len); } int |
983c88a49 CIFS: Add oplock ... |
3963 3964 3965 3966 |
SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, const u64 persistent_fid, const u64 volatile_fid, __u8 oplock_level) { |
40eff45b5 cifs: remove smb2... |
3967 |
struct smb_rqst rqst; |
983c88a49 CIFS: Add oplock ... |
3968 |
int rc; |
0d5a288d2 cifs: remove stru... |
3969 |
struct smb2_oplock_break *req = NULL; |
21ad9487c cifs: remove rfc1... |
3970 |
struct cifs_ses *ses = tcon->ses; |
7fb8986e7 CIFS: Add capabil... |
3971 |
int flags = CIFS_OBREAK_OP; |
21ad9487c cifs: remove rfc1... |
3972 3973 3974 3975 |
unsigned int total_len; struct kvec iov[1]; struct kvec rsp_iov; int resp_buf_type; |
983c88a49 CIFS: Add oplock ... |
3976 |
|
f96637be0 [CIFS] cifs: Rena... |
3977 3978 |
cifs_dbg(FYI, "SMB2_oplock_break "); |
21ad9487c cifs: remove rfc1... |
3979 3980 |
rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req, &total_len); |
983c88a49 CIFS: Add oplock ... |
3981 3982 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
3983 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
3984 |
flags |= CIFS_TRANSFORM_REQ; |
983c88a49 CIFS: Add oplock ... |
3985 3986 3987 |
req->VolatileFid = volatile_fid; req->PersistentFid = persistent_fid; req->OplockLevel = oplock_level; |
21ad9487c cifs: remove rfc1... |
3988 |
req->sync_hdr.CreditRequest = cpu_to_le16(1); |
983c88a49 CIFS: Add oplock ... |
3989 |
|
21ad9487c cifs: remove rfc1... |
3990 3991 3992 3993 |
flags |= CIFS_NO_RESP; iov[0].iov_base = (char *)req; iov[0].iov_len = total_len; |
40eff45b5 cifs: remove smb2... |
3994 3995 3996 3997 3998 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
3999 |
cifs_small_buf_release(req); |
983c88a49 CIFS: Add oplock ... |
4000 4001 4002 |
if (rc) { cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); |
f96637be0 [CIFS] cifs: Rena... |
4003 4004 |
cifs_dbg(FYI, "Send error in Oplock Break = %d ", rc); |
983c88a49 CIFS: Add oplock ... |
4005 4006 4007 4008 |
} return rc; } |
6fc05c25c CIFS: Add statfs ... |
4009 |
|
730928c8f cifs: update smb2... |
4010 4011 4012 |
void smb2_copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf, struct kstatfs *kst) |
6fc05c25c CIFS: Add statfs ... |
4013 4014 4015 4016 |
{ kst->f_bsize = le32_to_cpu(pfs_inf->BytesPerSector) * le32_to_cpu(pfs_inf->SectorsPerAllocationUnit); kst->f_blocks = le64_to_cpu(pfs_inf->TotalAllocationUnits); |
42bec214d cifs: Fix df outp... |
4017 4018 |
kst->f_bfree = kst->f_bavail = le64_to_cpu(pfs_inf->CallerAvailableAllocationUnits); |
6fc05c25c CIFS: Add statfs ... |
4019 4020 |
return; } |
2d3042178 smb3: add support... |
4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 |
static void copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data, struct kstatfs *kst) { kst->f_bsize = le32_to_cpu(response_data->BlockSize); kst->f_blocks = le64_to_cpu(response_data->TotalBlocks); kst->f_bfree = le64_to_cpu(response_data->BlocksAvail); if (response_data->UserBlocksAvail == cpu_to_le64(-1)) kst->f_bavail = kst->f_bfree; else kst->f_bavail = le64_to_cpu(response_data->UserBlocksAvail); if (response_data->TotalFileNodes != cpu_to_le64(-1)) kst->f_files = le64_to_cpu(response_data->TotalFileNodes); if (response_data->FreeFileNodes != cpu_to_le64(-1)) kst->f_ffree = le64_to_cpu(response_data->FreeFileNodes); return; } |
2d3042178 smb3: add support... |
4039 |
|
6fc05c25c CIFS: Add statfs ... |
4040 4041 4042 4043 |
static int build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, int outbuf_len, u64 persistent_fid, u64 volatile_fid) { |
c0953f2ed cifs: smb2pdu: Fi... |
4044 |
struct TCP_Server_Info *server; |
6fc05c25c CIFS: Add statfs ... |
4045 4046 |
int rc; struct smb2_query_info_req *req; |
b2fb7fecc cifs: remove rfc1... |
4047 |
unsigned int total_len; |
6fc05c25c CIFS: Add statfs ... |
4048 |
|
f96637be0 [CIFS] cifs: Rena... |
4049 4050 |
cifs_dbg(FYI, "Query FSInfo level %d ", level); |
6fc05c25c CIFS: Add statfs ... |
4051 4052 4053 |
if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) return -EIO; |
c0953f2ed cifs: smb2pdu: Fi... |
4054 |
server = tcon->ses->server; |
b2fb7fecc cifs: remove rfc1... |
4055 4056 |
rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, (void **) &req, &total_len); |
6fc05c25c CIFS: Add statfs ... |
4057 4058 4059 4060 4061 4062 4063 |
if (rc) return rc; req->InfoType = SMB2_O_INFO_FILESYSTEM; req->FileInfoClass = level; req->PersistentFileId = persistent_fid; req->VolatileFileId = volatile_fid; |
b2fb7fecc cifs: remove rfc1... |
4064 |
/* 1 for pad */ |
6fc05c25c CIFS: Add statfs ... |
4065 |
req->InputBufferOffset = |
b2fb7fecc cifs: remove rfc1... |
4066 |
cpu_to_le16(sizeof(struct smb2_query_info_req) - 1); |
6fc05c25c CIFS: Add statfs ... |
4067 |
req->OutputBufferLength = cpu_to_le32( |
1fc6ad2f1 cifs: remove head... |
4068 |
outbuf_len + sizeof(struct smb2_query_info_rsp) - 1); |
6fc05c25c CIFS: Add statfs ... |
4069 4070 |
iov->iov_base = (char *)req; |
b2fb7fecc cifs: remove rfc1... |
4071 |
iov->iov_len = total_len; |
6fc05c25c CIFS: Add statfs ... |
4072 4073 |
return 0; } |
2d3042178 smb3: add support... |
4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 |
int SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata) { struct smb_rqst rqst; struct smb2_query_info_rsp *rsp = NULL; struct kvec iov; struct kvec rsp_iov; int rc = 0; int resp_buftype; struct cifs_ses *ses = tcon->ses; FILE_SYSTEM_POSIX_INFO *info = NULL; int flags = 0; rc = build_qfs_info_req(&iov, tcon, FS_POSIX_INFORMATION, sizeof(FILE_SYSTEM_POSIX_INFO), persistent_fid, volatile_fid); if (rc) return rc; if (smb3_encryption_required(tcon)) flags |= CIFS_TRANSFORM_REQ; memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = &iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); cifs_small_buf_release(iov.iov_base); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); goto posix_qfsinf_exit; } rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; info = (FILE_SYSTEM_POSIX_INFO *)( le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp); |
730928c8f cifs: update smb2... |
4111 4112 4113 |
rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset), le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, sizeof(FILE_SYSTEM_POSIX_INFO)); |
2d3042178 smb3: add support... |
4114 4115 4116 4117 4118 4119 4120 |
if (!rc) copy_posix_fs_info_to_kstatfs(info, fsdata); posix_qfsinf_exit: free_rsp_buf(resp_buftype, rsp_iov.iov_base); return rc; } |
2d3042178 smb3: add support... |
4121 |
|
6fc05c25c CIFS: Add statfs ... |
4122 4123 4124 4125 |
int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata) { |
40eff45b5 cifs: remove smb2... |
4126 |
struct smb_rqst rqst; |
6fc05c25c CIFS: Add statfs ... |
4127 4128 |
struct smb2_query_info_rsp *rsp = NULL; struct kvec iov; |
da502f7df CIFS: Make SendRe... |
4129 |
struct kvec rsp_iov; |
6fc05c25c CIFS: Add statfs ... |
4130 4131 4132 4133 |
int rc = 0; int resp_buftype; struct cifs_ses *ses = tcon->ses; struct smb2_fs_full_size_info *info = NULL; |
7fb8986e7 CIFS: Add capabil... |
4134 |
int flags = 0; |
6fc05c25c CIFS: Add statfs ... |
4135 4136 4137 4138 4139 4140 |
rc = build_qfs_info_req(&iov, tcon, FS_FULL_SIZE_INFORMATION, sizeof(struct smb2_fs_full_size_info), persistent_fid, volatile_fid); if (rc) return rc; |
5a77e75fe smb3: rename encr... |
4141 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
4142 |
flags |= CIFS_TRANSFORM_REQ; |
40eff45b5 cifs: remove smb2... |
4143 4144 4145 4146 4147 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = &iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
4148 |
cifs_small_buf_release(iov.iov_base); |
6fc05c25c CIFS: Add statfs ... |
4149 4150 |
if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); |
34f626406 Query file system... |
4151 |
goto qfsinf_exit; |
6fc05c25c CIFS: Add statfs ... |
4152 |
} |
da502f7df CIFS: Make SendRe... |
4153 |
rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; |
6fc05c25c CIFS: Add statfs ... |
4154 |
|
1fc6ad2f1 cifs: remove head... |
4155 |
info = (struct smb2_fs_full_size_info *)( |
49f466bdb cifs: remove stru... |
4156 |
le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp); |
730928c8f cifs: update smb2... |
4157 4158 4159 |
rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset), le32_to_cpu(rsp->OutputBufferLength), &rsp_iov, sizeof(struct smb2_fs_full_size_info)); |
6fc05c25c CIFS: Add statfs ... |
4160 |
if (!rc) |
730928c8f cifs: update smb2... |
4161 |
smb2_copy_fs_info_to_kstatfs(info, fsdata); |
6fc05c25c CIFS: Add statfs ... |
4162 |
|
34f626406 Query file system... |
4163 |
qfsinf_exit: |
da502f7df CIFS: Make SendRe... |
4164 |
free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
34f626406 Query file system... |
4165 4166 4167 4168 4169 |
return rc; } int SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, |
2167114c6 Query device char... |
4170 |
u64 persistent_fid, u64 volatile_fid, int level) |
34f626406 Query file system... |
4171 |
{ |
40eff45b5 cifs: remove smb2... |
4172 |
struct smb_rqst rqst; |
34f626406 Query file system... |
4173 4174 |
struct smb2_query_info_rsp *rsp = NULL; struct kvec iov; |
da502f7df CIFS: Make SendRe... |
4175 |
struct kvec rsp_iov; |
34f626406 Query file system... |
4176 |
int rc = 0; |
2167114c6 Query device char... |
4177 |
int resp_buftype, max_len, min_len; |
34f626406 Query file system... |
4178 4179 |
struct cifs_ses *ses = tcon->ses; unsigned int rsp_len, offset; |
7fb8986e7 CIFS: Add capabil... |
4180 |
int flags = 0; |
34f626406 Query file system... |
4181 |
|
2167114c6 Query device char... |
4182 4183 4184 4185 4186 4187 |
if (level == FS_DEVICE_INFORMATION) { max_len = sizeof(FILE_SYSTEM_DEVICE_INFO); min_len = sizeof(FILE_SYSTEM_DEVICE_INFO); } else if (level == FS_ATTRIBUTE_INFORMATION) { max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO); min_len = MIN_FS_ATTR_INFO_SIZE; |
af6a12ea8 Query File System... |
4188 4189 4190 |
} else if (level == FS_SECTOR_SIZE_INFORMATION) { max_len = sizeof(struct smb3_fs_ss_info); min_len = sizeof(struct smb3_fs_ss_info); |
21ba3845b smb3: fill in sta... |
4191 4192 4193 |
} else if (level == FS_VOLUME_INFORMATION) { max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN; min_len = sizeof(struct smb3_fs_vol_info); |
2167114c6 Query device char... |
4194 |
} else { |
af6a12ea8 Query File System... |
4195 4196 |
cifs_dbg(FYI, "Invalid qfsinfo level %d ", level); |
2167114c6 Query device char... |
4197 4198 4199 4200 |
return -EINVAL; } rc = build_qfs_info_req(&iov, tcon, level, max_len, |
34f626406 Query file system... |
4201 4202 4203 |
persistent_fid, volatile_fid); if (rc) return rc; |
5a77e75fe smb3: rename encr... |
4204 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
4205 |
flags |= CIFS_TRANSFORM_REQ; |
40eff45b5 cifs: remove smb2... |
4206 4207 4208 4209 4210 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = &iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
4211 |
cifs_small_buf_release(iov.iov_base); |
34f626406 Query file system... |
4212 4213 4214 4215 |
if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); goto qfsattr_exit; } |
da502f7df CIFS: Make SendRe... |
4216 |
rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; |
34f626406 Query file system... |
4217 4218 4219 |
rsp_len = le32_to_cpu(rsp->OutputBufferLength); offset = le16_to_cpu(rsp->OutputBufferOffset); |
730928c8f cifs: update smb2... |
4220 |
rc = smb2_validate_iov(offset, rsp_len, &rsp_iov, min_len); |
2167114c6 Query device char... |
4221 4222 4223 4224 |
if (rc) goto qfsattr_exit; if (level == FS_ATTRIBUTE_INFORMATION) |
1fc6ad2f1 cifs: remove head... |
4225 |
memcpy(&tcon->fsAttrInfo, offset |
49f466bdb cifs: remove stru... |
4226 |
+ (char *)rsp, min_t(unsigned int, |
2167114c6 Query device char... |
4227 4228 |
rsp_len, max_len)); else if (level == FS_DEVICE_INFORMATION) |
1fc6ad2f1 cifs: remove head... |
4229 |
memcpy(&tcon->fsDevInfo, offset |
49f466bdb cifs: remove stru... |
4230 |
+ (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO)); |
af6a12ea8 Query File System... |
4231 4232 |
else if (level == FS_SECTOR_SIZE_INFORMATION) { struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *) |
1fc6ad2f1 cifs: remove head... |
4233 |
(offset + (char *)rsp); |
af6a12ea8 Query File System... |
4234 4235 4236 |
tcon->ss_flags = le32_to_cpu(ss_info->Flags); tcon->perf_sector_size = le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf); |
21ba3845b smb3: fill in sta... |
4237 4238 4239 4240 4241 |
} else if (level == FS_VOLUME_INFORMATION) { struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *) (offset + (char *)rsp); tcon->vol_serial_number = vol_info->VolumeSerialNumber; tcon->vol_create_time = vol_info->VolumeCreationTime; |
af6a12ea8 Query File System... |
4242 |
} |
34f626406 Query file system... |
4243 4244 |
qfsattr_exit: |
da502f7df CIFS: Make SendRe... |
4245 |
free_rsp_buf(resp_buftype, rsp_iov.iov_base); |
6fc05c25c CIFS: Add statfs ... |
4246 4247 |
return rc; } |
f7ba7fe68 CIFS: Add brlock ... |
4248 4249 4250 4251 4252 4253 |
int smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid, const __u32 num_lock, struct smb2_lock_element *buf) { |
40eff45b5 cifs: remove smb2... |
4254 |
struct smb_rqst rqst; |
f7ba7fe68 CIFS: Add brlock ... |
4255 4256 4257 |
int rc = 0; struct smb2_lock_req *req = NULL; struct kvec iov[2]; |
da502f7df CIFS: Make SendRe... |
4258 |
struct kvec rsp_iov; |
f7ba7fe68 CIFS: Add brlock ... |
4259 4260 |
int resp_buf_type; unsigned int count; |
7fb8986e7 CIFS: Add capabil... |
4261 |
int flags = CIFS_NO_RESP; |
ced93679c cifs: remove rfc1... |
4262 |
unsigned int total_len; |
f7ba7fe68 CIFS: Add brlock ... |
4263 |
|
f96637be0 [CIFS] cifs: Rena... |
4264 4265 |
cifs_dbg(FYI, "smb2_lockv num lock %d ", num_lock); |
f7ba7fe68 CIFS: Add brlock ... |
4266 |
|
ced93679c cifs: remove rfc1... |
4267 |
rc = smb2_plain_req_init(SMB2_LOCK, tcon, (void **) &req, &total_len); |
f7ba7fe68 CIFS: Add brlock ... |
4268 4269 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
4270 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
4271 |
flags |= CIFS_TRANSFORM_REQ; |
ced93679c cifs: remove rfc1... |
4272 |
req->sync_hdr.ProcessId = cpu_to_le32(pid); |
f7ba7fe68 CIFS: Add brlock ... |
4273 4274 4275 4276 4277 4278 |
req->LockCount = cpu_to_le16(num_lock); req->PersistentFileId = persist_fid; req->VolatileFileId = volatile_fid; count = num_lock * sizeof(struct smb2_lock_element); |
f7ba7fe68 CIFS: Add brlock ... |
4279 4280 |
iov[0].iov_base = (char *)req; |
ced93679c cifs: remove rfc1... |
4281 |
iov[0].iov_len = total_len - sizeof(struct smb2_lock_element); |
f7ba7fe68 CIFS: Add brlock ... |
4282 4283 4284 4285 |
iov[1].iov_base = (char *)buf; iov[1].iov_len = count; cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); |
40eff45b5 cifs: remove smb2... |
4286 4287 4288 4289 4290 4291 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 2; rc = cifs_send_recv(xid, tcon->ses, &rqst, &resp_buf_type, flags, |
ced93679c cifs: remove rfc1... |
4292 |
&rsp_iov); |
da502f7df CIFS: Make SendRe... |
4293 |
cifs_small_buf_release(req); |
f7ba7fe68 CIFS: Add brlock ... |
4294 |
if (rc) { |
f96637be0 [CIFS] cifs: Rena... |
4295 4296 |
cifs_dbg(FYI, "Send error in smb2_lockv = %d ", rc); |
f7ba7fe68 CIFS: Add brlock ... |
4297 |
cifs_stats_fail_inc(tcon, SMB2_LOCK_HE); |
eccb4422c smb3: Add ftrace ... |
4298 4299 |
trace_smb3_lock_err(xid, persist_fid, tcon->tid, tcon->ses->Suid, rc); |
f7ba7fe68 CIFS: Add brlock ... |
4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 |
} return rc; } int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon, const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid, const __u64 length, const __u64 offset, const __u32 lock_flags, const bool wait) { struct smb2_lock_element lock; lock.Offset = cpu_to_le64(offset); lock.Length = cpu_to_le64(length); lock.Flags = cpu_to_le32(lock_flags); if (!wait && lock_flags != SMB2_LOCKFLAG_UNLOCK) lock.Flags |= cpu_to_le32(SMB2_LOCKFLAG_FAIL_IMMEDIATELY); return smb2_lockv(xid, tcon, persist_fid, volatile_fid, pid, 1, &lock); } |
0822f5142 CIFS: Add SMB2.1 ... |
4321 4322 4323 4324 4325 |
int SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, __u8 *lease_key, const __le32 lease_state) { |
40eff45b5 cifs: remove smb2... |
4326 |
struct smb_rqst rqst; |
0822f5142 CIFS: Add SMB2.1 ... |
4327 4328 |
int rc; struct smb2_lease_ack *req = NULL; |
8eb7998e7 cifs: remove rfc1... |
4329 |
struct cifs_ses *ses = tcon->ses; |
7fb8986e7 CIFS: Add capabil... |
4330 |
int flags = CIFS_OBREAK_OP; |
8eb7998e7 cifs: remove rfc1... |
4331 4332 4333 4334 |
unsigned int total_len; struct kvec iov[1]; struct kvec rsp_iov; int resp_buf_type; |
0822f5142 CIFS: Add SMB2.1 ... |
4335 |
|
f96637be0 [CIFS] cifs: Rena... |
4336 4337 |
cifs_dbg(FYI, "SMB2_lease_break "); |
8eb7998e7 cifs: remove rfc1... |
4338 4339 |
rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req, &total_len); |
0822f5142 CIFS: Add SMB2.1 ... |
4340 4341 |
if (rc) return rc; |
5a77e75fe smb3: rename encr... |
4342 |
if (smb3_encryption_required(tcon)) |
7fb8986e7 CIFS: Add capabil... |
4343 |
flags |= CIFS_TRANSFORM_REQ; |
8eb7998e7 cifs: remove rfc1... |
4344 |
req->sync_hdr.CreditRequest = cpu_to_le16(1); |
0822f5142 CIFS: Add SMB2.1 ... |
4345 |
req->StructureSize = cpu_to_le16(36); |
8eb7998e7 cifs: remove rfc1... |
4346 |
total_len += 12; |
0822f5142 CIFS: Add SMB2.1 ... |
4347 4348 4349 |
memcpy(req->LeaseKey, lease_key, 16); req->LeaseState = lease_state; |
8eb7998e7 cifs: remove rfc1... |
4350 4351 4352 4353 |
flags |= CIFS_NO_RESP; iov[0].iov_base = (char *)req; iov[0].iov_len = total_len; |
40eff45b5 cifs: remove smb2... |
4354 4355 4356 4357 4358 |
memset(&rqst, 0, sizeof(struct smb_rqst)); rqst.rq_iov = iov; rqst.rq_nvec = 1; rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); |
da502f7df CIFS: Make SendRe... |
4359 |
cifs_small_buf_release(req); |
0822f5142 CIFS: Add SMB2.1 ... |
4360 4361 4362 |
if (rc) { cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); |
f96637be0 [CIFS] cifs: Rena... |
4363 4364 |
cifs_dbg(FYI, "Send error in Lease Break = %d ", rc); |
0822f5142 CIFS: Add SMB2.1 ... |
4365 4366 4367 4368 |
} return rc; } |