blob: dad6dc7632004ceafc4034f133e4caf9595ea482 [file] [log] [blame]
Steve French1080ef72011-02-24 18:07:19 +00001/*
2 * SMB2 version specific operations
3 *
4 * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License v2 as published
8 * by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
Pavel Shilovsky3a3bab52012-09-18 16:20:28 -070020#include <linux/pagemap.h>
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -070021#include <linux/vfs.h>
Steve Frenchf29ebb42014-07-19 21:44:58 -050022#include <linux/falloc.h>
Pavel Shilovsky026e93d2016-11-03 16:47:37 -070023#include <linux/scatterlist.h>
Tobias Regnery4fa8e502017-03-30 12:34:14 +020024#include <linux/uuid.h>
Pavel Shilovsky026e93d2016-11-03 16:47:37 -070025#include <crypto/aead.h>
Steve French1080ef72011-02-24 18:07:19 +000026#include "cifsglob.h"
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +040027#include "smb2pdu.h"
28#include "smb2proto.h"
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040029#include "cifsproto.h"
30#include "cifs_debug.h"
Pavel Shilovskyb42bf882013-08-14 19:25:21 +040031#include "cifs_unicode.h"
Pavel Shilovsky2e44b282012-09-18 16:20:33 -070032#include "smb2status.h"
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -070033#include "smb2glob.h"
Steve French834170c2016-09-30 21:14:26 -050034#include "cifs_ioctl.h"
Long Li09902f82017-11-22 17:38:39 -070035#include "smbdirect.h"
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040036
37static int
38change_conf(struct TCP_Server_Info *server)
39{
40 server->credits += server->echo_credits + server->oplock_credits;
41 server->oplock_credits = server->echo_credits = 0;
42 switch (server->credits) {
43 case 0:
44 return -1;
45 case 1:
46 server->echoes = false;
47 server->oplocks = false;
Joe Perchesf96637b2013-05-04 22:12:25 -050048 cifs_dbg(VFS, "disabling echoes and oplocks\n");
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040049 break;
50 case 2:
51 server->echoes = true;
52 server->oplocks = false;
53 server->echo_credits = 1;
Joe Perchesf96637b2013-05-04 22:12:25 -050054 cifs_dbg(FYI, "disabling oplocks\n");
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040055 break;
56 default:
57 server->echoes = true;
Steve Frenche0ddde92015-09-22 09:29:38 -050058 if (enable_oplocks) {
59 server->oplocks = true;
60 server->oplock_credits = 1;
61 } else
62 server->oplocks = false;
63
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040064 server->echo_credits = 1;
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040065 }
66 server->credits -= server->echo_credits + server->oplock_credits;
67 return 0;
68}
69
70static void
71smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
72 const int optype)
73{
74 int *val, rc = 0;
75 spin_lock(&server->req_lock);
76 val = server->ops->get_credits_field(server, optype);
77 *val += add;
Steve French141891f2016-09-23 00:44:16 -050078 if (*val > 65000) {
79 *val = 65000; /* Don't get near 64K credits, avoid srv bugs */
80 printk_once(KERN_WARNING "server overflowed SMB3 credits\n");
81 }
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040082 server->in_flight--;
Pavel Shilovskyec2e4522011-12-27 16:12:43 +040083 if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040084 rc = change_conf(server);
Pavel Shilovsky983c88a2012-09-18 16:20:33 -070085 /*
86 * Sometimes server returns 0 credits on oplock break ack - we need to
87 * rebalance credits in this case.
88 */
89 else if (server->in_flight > 0 && server->oplock_credits == 0 &&
90 server->oplocks) {
91 if (server->credits > 1) {
92 server->credits--;
93 server->oplock_credits++;
94 }
95 }
Pavel Shilovsky28ea5292012-05-23 16:18:00 +040096 spin_unlock(&server->req_lock);
97 wake_up(&server->request_q);
98 if (rc)
99 cifs_reconnect(server);
100}
101
102static void
103smb2_set_credits(struct TCP_Server_Info *server, const int val)
104{
105 spin_lock(&server->req_lock);
106 server->credits = val;
107 spin_unlock(&server->req_lock);
108}
109
110static int *
111smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
112{
113 switch (optype) {
114 case CIFS_ECHO_OP:
115 return &server->echo_credits;
116 case CIFS_OBREAK_OP:
117 return &server->oplock_credits;
118 default:
119 return &server->credits;
120 }
121}
122
123static unsigned int
124smb2_get_credits(struct mid_q_entry *mid)
125{
Ronnie Sahlberg49f466b2018-06-01 10:53:06 +1000126 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf;
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700127
128 return le16_to_cpu(shdr->CreditRequest);
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400129}
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400130
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +0400131static int
132smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
133 unsigned int *num, unsigned int *credits)
134{
135 int rc = 0;
136 unsigned int scredits;
137
138 spin_lock(&server->req_lock);
139 while (1) {
140 if (server->credits <= 0) {
141 spin_unlock(&server->req_lock);
142 cifs_num_waiters_inc(server);
143 rc = wait_event_killable(server->request_q,
144 has_credits(server, &server->credits));
145 cifs_num_waiters_dec(server);
146 if (rc)
147 return rc;
148 spin_lock(&server->req_lock);
149 } else {
150 if (server->tcpStatus == CifsExiting) {
151 spin_unlock(&server->req_lock);
152 return -ENOENT;
153 }
154
155 scredits = server->credits;
156 /* can deadlock with reopen */
157 if (scredits == 1) {
158 *num = SMB2_MAX_BUFFER_SIZE;
159 *credits = 0;
160 break;
161 }
162
163 /* leave one credit for a possible reopen */
164 scredits--;
165 *num = min_t(unsigned int, size,
166 scredits * SMB2_MAX_BUFFER_SIZE);
167
168 *credits = DIV_ROUND_UP(*num, SMB2_MAX_BUFFER_SIZE);
169 server->credits -= *credits;
170 server->in_flight++;
171 break;
172 }
173 }
174 spin_unlock(&server->req_lock);
175 return rc;
176}
177
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +0400178static __u64
179smb2_get_next_mid(struct TCP_Server_Info *server)
180{
181 __u64 mid;
182 /* for SMB2 we need the current value */
183 spin_lock(&GlobalMid_Lock);
184 mid = server->CurrentMid++;
185 spin_unlock(&GlobalMid_Lock);
186 return mid;
187}
Steve French1080ef72011-02-24 18:07:19 +0000188
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400189static struct mid_q_entry *
190smb2_find_mid(struct TCP_Server_Info *server, char *buf)
191{
192 struct mid_q_entry *mid;
Ronnie Sahlberg49f466b2018-06-01 10:53:06 +1000193 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700194 __u64 wire_mid = le64_to_cpu(shdr->MessageId);
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400195
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700196 if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
Steve French373512e2015-12-18 13:05:30 -0600197 cifs_dbg(VFS, "encrypted frame parsing not supported yet");
198 return NULL;
199 }
200
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400201 spin_lock(&GlobalMid_Lock);
202 list_for_each_entry(mid, &server->pending_mid_q, qhead) {
Sachin Prabhu9235d092014-12-09 17:37:00 +0000203 if ((mid->mid == wire_mid) &&
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400204 (mid->mid_state == MID_REQUEST_SUBMITTED) &&
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700205 (mid->command == shdr->Command)) {
Lars Persson696e4202018-06-25 14:05:25 +0200206 kref_get(&mid->refcount);
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400207 spin_unlock(&GlobalMid_Lock);
208 return mid;
209 }
210 }
211 spin_unlock(&GlobalMid_Lock);
212 return NULL;
213}
214
215static void
Ronnie Sahlberg14547f72018-04-22 14:45:53 -0600216smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400217{
218#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlberg49f466b2018-06-01 10:53:06 +1000219 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400220
Joe Perchesf96637b2013-05-04 22:12:25 -0500221 cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
Pavel Shilovsky31473fc2016-10-24 15:33:04 -0700222 shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
223 shdr->ProcessId);
Ronnie Sahlberg14547f72018-04-22 14:45:53 -0600224 cifs_dbg(VFS, "smb buf %p len %u\n", buf,
Steve French71992e622018-05-06 15:58:51 -0500225 server->ops->calc_smb_size(buf, server));
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +0400226#endif
227}
228
Pavel Shilovskyec2e4522011-12-27 16:12:43 +0400229static bool
230smb2_need_neg(struct TCP_Server_Info *server)
231{
232 return server->max_read == 0;
233}
234
235static int
236smb2_negotiate(const unsigned int xid, struct cifs_ses *ses)
237{
238 int rc;
239 ses->server->CurrentMid = 0;
240 rc = SMB2_negotiate(xid, ses);
241 /* BB we probably don't need to retry with modern servers */
242 if (rc == -EAGAIN)
243 rc = -EHOSTDOWN;
244 return rc;
245}
246
Pavel Shilovsky3a3bab52012-09-18 16:20:28 -0700247static unsigned int
248smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
249{
250 struct TCP_Server_Info *server = tcon->ses->server;
251 unsigned int wsize;
252
253 /* start with specified wsize, or default */
254 wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
255 wsize = min_t(unsigned int, wsize, server->max_write);
Long Li09902f82017-11-22 17:38:39 -0700256#ifdef CONFIG_CIFS_SMB_DIRECT
Long Libb4c0412018-04-17 12:17:08 -0700257 if (server->rdma) {
258 if (server->sign)
259 wsize = min_t(unsigned int,
260 wsize, server->smbd_conn->max_fragmented_send_size);
261 else
262 wsize = min_t(unsigned int,
Long Li09902f82017-11-22 17:38:39 -0700263 wsize, server->smbd_conn->max_readwrite_size);
Long Libb4c0412018-04-17 12:17:08 -0700264 }
Long Li09902f82017-11-22 17:38:39 -0700265#endif
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +0400266 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
267 wsize = min_t(unsigned int, wsize, SMB2_MAX_BUFFER_SIZE);
Pavel Shilovsky3a3bab52012-09-18 16:20:28 -0700268
Pavel Shilovsky3a3bab52012-09-18 16:20:28 -0700269 return wsize;
270}
271
272static unsigned int
273smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
274{
275 struct TCP_Server_Info *server = tcon->ses->server;
276 unsigned int rsize;
277
278 /* start with specified rsize, or default */
279 rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
280 rsize = min_t(unsigned int, rsize, server->max_read);
Long Li09902f82017-11-22 17:38:39 -0700281#ifdef CONFIG_CIFS_SMB_DIRECT
Long Libb4c0412018-04-17 12:17:08 -0700282 if (server->rdma) {
283 if (server->sign)
284 rsize = min_t(unsigned int,
285 rsize, server->smbd_conn->max_fragmented_recv_size);
286 else
287 rsize = min_t(unsigned int,
Long Li09902f82017-11-22 17:38:39 -0700288 rsize, server->smbd_conn->max_readwrite_size);
Long Libb4c0412018-04-17 12:17:08 -0700289 }
Long Li09902f82017-11-22 17:38:39 -0700290#endif
Pavel Shilovskybed9da02014-06-25 11:28:57 +0400291
292 if (!(server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
293 rsize = min_t(unsigned int, rsize, SMB2_MAX_BUFFER_SIZE);
Pavel Shilovsky3a3bab52012-09-18 16:20:28 -0700294
Pavel Shilovsky3a3bab52012-09-18 16:20:28 -0700295 return rsize;
296}
297
Aurelien Aptelfe856be2018-06-14 17:04:51 +0200298
299static int
300parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
301 size_t buf_len,
302 struct cifs_server_iface **iface_list,
303 size_t *iface_count)
304{
305 struct network_interface_info_ioctl_rsp *p;
306 struct sockaddr_in *addr4;
307 struct sockaddr_in6 *addr6;
308 struct iface_info_ipv4 *p4;
309 struct iface_info_ipv6 *p6;
310 struct cifs_server_iface *info;
311 ssize_t bytes_left;
312 size_t next = 0;
313 int nb_iface = 0;
314 int rc = 0;
315
316 *iface_list = NULL;
317 *iface_count = 0;
318
319 /*
320 * Fist pass: count and sanity check
321 */
322
323 bytes_left = buf_len;
324 p = buf;
325 while (bytes_left >= sizeof(*p)) {
326 nb_iface++;
327 next = le32_to_cpu(p->Next);
328 if (!next) {
329 bytes_left -= sizeof(*p);
330 break;
331 }
332 p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
333 bytes_left -= next;
334 }
335
336 if (!nb_iface) {
337 cifs_dbg(VFS, "%s: malformed interface info\n", __func__);
338 rc = -EINVAL;
339 goto out;
340 }
341
342 if (bytes_left || p->Next)
343 cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
344
345
346 /*
347 * Second pass: extract info to internal structure
348 */
349
350 *iface_list = kcalloc(nb_iface, sizeof(**iface_list), GFP_KERNEL);
351 if (!*iface_list) {
352 rc = -ENOMEM;
353 goto out;
354 }
355
356 info = *iface_list;
357 bytes_left = buf_len;
358 p = buf;
359 while (bytes_left >= sizeof(*p)) {
360 info->speed = le64_to_cpu(p->LinkSpeed);
361 info->rdma_capable = le32_to_cpu(p->Capability & RDMA_CAPABLE);
362 info->rss_capable = le32_to_cpu(p->Capability & RSS_CAPABLE);
363
364 cifs_dbg(FYI, "%s: adding iface %zu\n", __func__, *iface_count);
365 cifs_dbg(FYI, "%s: speed %zu bps\n", __func__, info->speed);
366 cifs_dbg(FYI, "%s: capabilities 0x%08x\n", __func__,
367 le32_to_cpu(p->Capability));
368
369 switch (p->Family) {
370 /*
371 * The kernel and wire socket structures have the same
372 * layout and use network byte order but make the
373 * conversion explicit in case either one changes.
374 */
375 case INTERNETWORK:
376 addr4 = (struct sockaddr_in *)&info->sockaddr;
377 p4 = (struct iface_info_ipv4 *)p->Buffer;
378 addr4->sin_family = AF_INET;
379 memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
380
381 /* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */
382 addr4->sin_port = cpu_to_be16(CIFS_PORT);
383
384 cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__,
385 &addr4->sin_addr);
386 break;
387 case INTERNETWORKV6:
388 addr6 = (struct sockaddr_in6 *)&info->sockaddr;
389 p6 = (struct iface_info_ipv6 *)p->Buffer;
390 addr6->sin6_family = AF_INET6;
391 memcpy(&addr6->sin6_addr, &p6->IPv6Address, 16);
392
393 /* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */
394 addr6->sin6_flowinfo = 0;
395 addr6->sin6_scope_id = 0;
396 addr6->sin6_port = cpu_to_be16(CIFS_PORT);
397
398 cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__,
399 &addr6->sin6_addr);
400 break;
401 default:
402 cifs_dbg(VFS,
403 "%s: skipping unsupported socket family\n",
404 __func__);
405 goto next_iface;
406 }
407
408 (*iface_count)++;
409 info++;
410next_iface:
411 next = le32_to_cpu(p->Next);
412 if (!next)
413 break;
414 p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
415 bytes_left -= next;
416 }
417
418 if (!*iface_count) {
419 rc = -EINVAL;
420 goto out;
421 }
422
423out:
424 if (rc) {
425 kfree(*iface_list);
426 *iface_count = 0;
427 *iface_list = NULL;
428 }
429 return rc;
430}
431
432
Steve Frenchc481e9f2013-10-14 01:21:53 -0500433static int
434SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
435{
436 int rc;
437 unsigned int ret_data_len = 0;
Aurelien Aptelfe856be2018-06-14 17:04:51 +0200438 struct network_interface_info_ioctl_rsp *out_buf = NULL;
439 struct cifs_server_iface *iface_list;
440 size_t iface_count;
441 struct cifs_ses *ses = tcon->ses;
Steve Frenchc481e9f2013-10-14 01:21:53 -0500442
443 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
444 FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
445 NULL /* no data input */, 0 /* no data input */,
446 (char **)&out_buf, &ret_data_len);
Steve Frenchc3ed4402018-06-28 22:53:39 -0500447 if (rc == -EOPNOTSUPP) {
448 cifs_dbg(FYI,
449 "server does not support query network interfaces\n");
450 goto out;
451 } else if (rc != 0) {
Steve French9ffc5412014-10-16 15:13:14 -0500452 cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
Aurelien Aptelfe856be2018-06-14 17:04:51 +0200453 goto out;
Steve French9ffc5412014-10-16 15:13:14 -0500454 }
Aurelien Aptelfe856be2018-06-14 17:04:51 +0200455
456 rc = parse_server_interfaces(out_buf, ret_data_len,
457 &iface_list, &iface_count);
458 if (rc)
459 goto out;
460
461 spin_lock(&ses->iface_lock);
462 kfree(ses->iface_list);
463 ses->iface_list = iface_list;
464 ses->iface_count = iface_count;
465 ses->iface_last_update = jiffies;
466 spin_unlock(&ses->iface_lock);
467
468out:
Steve French24df1482016-09-29 04:20:23 -0500469 kfree(out_buf);
Steve Frenchc481e9f2013-10-14 01:21:53 -0500470 return rc;
471}
Steve Frenchc481e9f2013-10-14 01:21:53 -0500472
Ronnie Sahlberga93864d2018-06-14 06:48:35 +1000473void
474smb2_cached_lease_break(struct work_struct *work)
475{
476 struct cached_fid *cfid = container_of(work,
477 struct cached_fid, lease_break);
478 mutex_lock(&cfid->fid_mutex);
479 if (cfid->is_valid) {
480 cifs_dbg(FYI, "clear cached root file handle\n");
481 SMB2_close(0, cfid->tcon, cfid->fid->persistent_fid,
482 cfid->fid->volatile_fid);
483 cfid->is_valid = false;
484 }
485 mutex_unlock(&cfid->fid_mutex);
486}
487
Steve French3d4ef9a2018-04-25 22:19:09 -0500488/*
489 * Open the directory at the root of a share
490 */
491int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
492{
493 struct cifs_open_parms oparams;
494 int rc;
495 __le16 srch_path = 0; /* Null - since an open of top of share */
Ronnie Sahlberga93864d2018-06-14 06:48:35 +1000496 u8 oplock = SMB2_OPLOCK_LEVEL_II;
Steve French3d4ef9a2018-04-25 22:19:09 -0500497
Ronnie Sahlberga93864d2018-06-14 06:48:35 +1000498 mutex_lock(&tcon->crfid.fid_mutex);
499 if (tcon->crfid.is_valid) {
Steve French3d4ef9a2018-04-25 22:19:09 -0500500 cifs_dbg(FYI, "found a cached root file handle\n");
Ronnie Sahlberga93864d2018-06-14 06:48:35 +1000501 memcpy(pfid, tcon->crfid.fid, sizeof(struct cifs_fid));
502 mutex_unlock(&tcon->crfid.fid_mutex);
Steve French3d4ef9a2018-04-25 22:19:09 -0500503 return 0;
504 }
505
506 oparams.tcon = tcon;
507 oparams.create_options = 0;
508 oparams.desired_access = FILE_READ_ATTRIBUTES;
509 oparams.disposition = FILE_OPEN;
510 oparams.fid = pfid;
511 oparams.reconnect = false;
512
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +1000513 rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL);
Steve French3d4ef9a2018-04-25 22:19:09 -0500514 if (rc == 0) {
Ronnie Sahlberga93864d2018-06-14 06:48:35 +1000515 memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid));
516 tcon->crfid.tcon = tcon;
517 tcon->crfid.is_valid = true;
Steve French3d4ef9a2018-04-25 22:19:09 -0500518 }
Ronnie Sahlberga93864d2018-06-14 06:48:35 +1000519 mutex_unlock(&tcon->crfid.fid_mutex);
Steve French3d4ef9a2018-04-25 22:19:09 -0500520 return rc;
521}
522
Steve French34f62642013-10-09 02:07:00 -0500523static void
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500524smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
525{
526 int rc;
527 __le16 srch_path = 0; /* Null - open root of share */
528 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
529 struct cifs_open_parms oparms;
530 struct cifs_fid fid;
Steve French3d4ef9a2018-04-25 22:19:09 -0500531 bool no_cached_open = tcon->nohandlecache;
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500532
533 oparms.tcon = tcon;
534 oparms.desired_access = FILE_READ_ATTRIBUTES;
535 oparms.disposition = FILE_OPEN;
536 oparms.create_options = 0;
537 oparms.fid = &fid;
538 oparms.reconnect = false;
539
Steve French3d4ef9a2018-04-25 22:19:09 -0500540 if (no_cached_open)
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +1000541 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
542 NULL);
Steve French3d4ef9a2018-04-25 22:19:09 -0500543 else
544 rc = open_shroot(xid, tcon, &fid);
545
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500546 if (rc)
547 return;
548
Steve Frenchc481e9f2013-10-14 01:21:53 -0500549 SMB3_request_interfaces(xid, tcon);
Steve Frenchc481e9f2013-10-14 01:21:53 -0500550
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500551 SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
552 FS_ATTRIBUTE_INFORMATION);
553 SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
554 FS_DEVICE_INFORMATION);
555 SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
Steve French21ba3842018-06-24 23:18:52 -0500556 FS_VOLUME_INFORMATION);
557 SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500558 FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
Steve French3d4ef9a2018-04-25 22:19:09 -0500559 if (no_cached_open)
560 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500561 return;
562}
563
564static void
Steve French34f62642013-10-09 02:07:00 -0500565smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
566{
567 int rc;
568 __le16 srch_path = 0; /* Null - open root of share */
569 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
570 struct cifs_open_parms oparms;
571 struct cifs_fid fid;
572
573 oparms.tcon = tcon;
574 oparms.desired_access = FILE_READ_ATTRIBUTES;
575 oparms.disposition = FILE_OPEN;
576 oparms.create_options = 0;
577 oparms.fid = &fid;
578 oparms.reconnect = false;
579
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +1000580 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
Steve French34f62642013-10-09 02:07:00 -0500581 if (rc)
582 return;
583
Steven French21671142013-10-09 13:36:35 -0500584 SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
585 FS_ATTRIBUTE_INFORMATION);
586 SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
587 FS_DEVICE_INFORMATION);
Steve French34f62642013-10-09 02:07:00 -0500588 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
589 return;
590}
591
Pavel Shilovsky2503a0d2011-12-26 22:58:46 +0400592static int
593smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
594 struct cifs_sb_info *cifs_sb, const char *full_path)
595{
596 int rc;
Pavel Shilovsky2503a0d2011-12-26 22:58:46 +0400597 __le16 *utf16_path;
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700598 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
Pavel Shilovsky064f6042013-07-09 18:20:30 +0400599 struct cifs_open_parms oparms;
600 struct cifs_fid fid;
Pavel Shilovsky2503a0d2011-12-26 22:58:46 +0400601
Ronnie Sahlberga93864d2018-06-14 06:48:35 +1000602 if ((*full_path == 0) && tcon->crfid.is_valid)
Steve French3d4ef9a2018-04-25 22:19:09 -0500603 return 0;
604
Pavel Shilovsky2503a0d2011-12-26 22:58:46 +0400605 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
606 if (!utf16_path)
607 return -ENOMEM;
608
Pavel Shilovsky064f6042013-07-09 18:20:30 +0400609 oparms.tcon = tcon;
610 oparms.desired_access = FILE_READ_ATTRIBUTES;
611 oparms.disposition = FILE_OPEN;
612 oparms.create_options = 0;
613 oparms.fid = &fid;
Pavel Shilovsky9cbc0b72013-07-09 18:40:58 +0400614 oparms.reconnect = false;
Pavel Shilovsky064f6042013-07-09 18:20:30 +0400615
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +1000616 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
Pavel Shilovsky2503a0d2011-12-26 22:58:46 +0400617 if (rc) {
618 kfree(utf16_path);
619 return rc;
620 }
621
Pavel Shilovsky064f6042013-07-09 18:20:30 +0400622 rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
Pavel Shilovsky2503a0d2011-12-26 22:58:46 +0400623 kfree(utf16_path);
624 return rc;
625}
626
Pavel Shilovskybe4cb9e2011-12-29 17:06:33 +0400627static int
628smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
629 struct cifs_sb_info *cifs_sb, const char *full_path,
630 u64 *uniqueid, FILE_ALL_INFO *data)
631{
632 *uniqueid = le64_to_cpu(data->IndexNumber);
633 return 0;
634}
635
Pavel Shilovskyb7546bc2012-09-18 16:20:27 -0700636static int
637smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
638 struct cifs_fid *fid, FILE_ALL_INFO *data)
639{
640 int rc;
641 struct smb2_file_all_info *smb2_data;
642
Pavel Shilovsky1bbe4992014-08-22 13:32:11 +0400643 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
Pavel Shilovskyb7546bc2012-09-18 16:20:27 -0700644 GFP_KERNEL);
645 if (smb2_data == NULL)
646 return -ENOMEM;
647
648 rc = SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid,
649 smb2_data);
650 if (!rc)
651 move_smb2_info_to_cifs(data, smb2_data);
652 kfree(smb2_data);
653 return rc;
654}
655
Arnd Bergmann1368f152017-09-05 11:24:15 +0200656#ifdef CONFIG_CIFS_XATTR
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +1000657static ssize_t
658move_smb2_ea_to_cifs(char *dst, size_t dst_size,
659 struct smb2_file_full_ea_info *src, size_t src_size,
660 const unsigned char *ea_name)
661{
662 int rc = 0;
663 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
664 char *name, *value;
665 size_t name_len, value_len, user_name_len;
666
667 while (src_size > 0) {
668 name = &src->ea_data[0];
669 name_len = (size_t)src->ea_name_length;
670 value = &src->ea_data[src->ea_name_length + 1];
671 value_len = (size_t)le16_to_cpu(src->ea_value_length);
672
673 if (name_len == 0) {
674 break;
675 }
676
677 if (src_size < 8 + name_len + 1 + value_len) {
678 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
679 rc = -EIO;
680 goto out;
681 }
682
683 if (ea_name) {
684 if (ea_name_len == name_len &&
685 memcmp(ea_name, name, name_len) == 0) {
686 rc = value_len;
687 if (dst_size == 0)
688 goto out;
689 if (dst_size < value_len) {
690 rc = -ERANGE;
691 goto out;
692 }
693 memcpy(dst, value, value_len);
694 goto out;
695 }
696 } else {
697 /* 'user.' plus a terminating null */
698 user_name_len = 5 + 1 + name_len;
699
700 rc += user_name_len;
701
702 if (dst_size >= user_name_len) {
703 dst_size -= user_name_len;
704 memcpy(dst, "user.", 5);
705 dst += 5;
706 memcpy(dst, src->ea_data, name_len);
707 dst += name_len;
708 *dst = 0;
709 ++dst;
710 } else if (dst_size == 0) {
711 /* skip copy - calc size only */
712 } else {
713 /* stop before overrun buffer */
714 rc = -ERANGE;
715 break;
716 }
717 }
718
719 if (!src->next_entry_offset)
720 break;
721
722 if (src_size < le32_to_cpu(src->next_entry_offset)) {
723 /* stop before overrun buffer */
724 rc = -ERANGE;
725 break;
726 }
727 src_size -= le32_to_cpu(src->next_entry_offset);
728 src = (void *)((char *)src +
729 le32_to_cpu(src->next_entry_offset));
730 }
731
732 /* didn't find the named attribute */
733 if (ea_name)
734 rc = -ENODATA;
735
736out:
737 return (ssize_t)rc;
738}
739
740static ssize_t
741smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
742 const unsigned char *path, const unsigned char *ea_name,
743 char *ea_data, size_t buf_size,
744 struct cifs_sb_info *cifs_sb)
745{
746 int rc;
747 __le16 *utf16_path;
748 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
749 struct cifs_open_parms oparms;
750 struct cifs_fid fid;
751 struct smb2_file_full_ea_info *smb2_data;
Ronnie Sahlberg7cb3def2017-09-28 09:39:58 +1000752 int ea_buf_size = SMB2_MIN_EA_BUF;
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +1000753
754 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
755 if (!utf16_path)
756 return -ENOMEM;
757
758 oparms.tcon = tcon;
759 oparms.desired_access = FILE_READ_EA;
760 oparms.disposition = FILE_OPEN;
761 oparms.create_options = 0;
762 oparms.fid = &fid;
763 oparms.reconnect = false;
764
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +1000765 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +1000766 kfree(utf16_path);
767 if (rc) {
768 cifs_dbg(FYI, "open failed rc=%d\n", rc);
769 return rc;
770 }
771
Ronnie Sahlberg7cb3def2017-09-28 09:39:58 +1000772 while (1) {
773 smb2_data = kzalloc(ea_buf_size, GFP_KERNEL);
774 if (smb2_data == NULL) {
775 SMB2_close(xid, tcon, fid.persistent_fid,
776 fid.volatile_fid);
777 return -ENOMEM;
778 }
779
780 rc = SMB2_query_eas(xid, tcon, fid.persistent_fid,
781 fid.volatile_fid,
782 ea_buf_size, smb2_data);
783
784 if (rc != -E2BIG)
785 break;
786
787 kfree(smb2_data);
788 ea_buf_size <<= 1;
789
790 if (ea_buf_size > SMB2_MAX_EA_BUF) {
791 cifs_dbg(VFS, "EA size is too large\n");
792 SMB2_close(xid, tcon, fid.persistent_fid,
793 fid.volatile_fid);
794 return -ENOMEM;
795 }
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +1000796 }
797
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +1000798 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
799
Paulo Alcantaraae2cd7f2018-05-04 11:25:26 -0300800 /*
801 * If ea_name is NULL (listxattr) and there are no EAs, return 0 as it's
802 * not an error. Otherwise, the specified ea_name was not found.
803 */
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +1000804 if (!rc)
805 rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data,
806 SMB2_MAX_EA_BUF, ea_name);
Paulo Alcantaraae2cd7f2018-05-04 11:25:26 -0300807 else if (!ea_name && rc == -ENODATA)
808 rc = 0;
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +1000809
810 kfree(smb2_data);
811 return rc;
812}
813
Ronnie Sahlberg55175542017-08-24 11:24:56 +1000814
815static int
816smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
817 const char *path, const char *ea_name, const void *ea_value,
818 const __u16 ea_value_len, const struct nls_table *nls_codepage,
819 struct cifs_sb_info *cifs_sb)
820{
821 int rc;
822 __le16 *utf16_path;
823 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
824 struct cifs_open_parms oparms;
825 struct cifs_fid fid;
826 struct smb2_file_full_ea_info *ea;
827 int ea_name_len = strlen(ea_name);
828 int len;
829
830 if (ea_name_len > 255)
831 return -EINVAL;
832
833 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
834 if (!utf16_path)
835 return -ENOMEM;
836
837 oparms.tcon = tcon;
838 oparms.desired_access = FILE_WRITE_EA;
839 oparms.disposition = FILE_OPEN;
840 oparms.create_options = 0;
841 oparms.fid = &fid;
842 oparms.reconnect = false;
843
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +1000844 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
Ronnie Sahlberg55175542017-08-24 11:24:56 +1000845 kfree(utf16_path);
846 if (rc) {
847 cifs_dbg(FYI, "open failed rc=%d\n", rc);
848 return rc;
849 }
850
851 len = sizeof(ea) + ea_name_len + ea_value_len + 1;
852 ea = kzalloc(len, GFP_KERNEL);
853 if (ea == NULL) {
854 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
855 return -ENOMEM;
856 }
857
858 ea->ea_name_length = ea_name_len;
859 ea->ea_value_length = cpu_to_le16(ea_value_len);
860 memcpy(ea->ea_data, ea_name, ea_name_len + 1);
861 memcpy(ea->ea_data + ea_name_len + 1, ea_value, ea_value_len);
862
863 rc = SMB2_set_ea(xid, tcon, fid.persistent_fid, fid.volatile_fid, ea,
864 len);
Paulo Alcantara6aa0c112018-07-04 14:16:16 -0300865 kfree(ea);
866
Ronnie Sahlberg55175542017-08-24 11:24:56 +1000867 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
868
869 return rc;
870}
Arnd Bergmann1368f152017-09-05 11:24:15 +0200871#endif
Ronnie Sahlberg55175542017-08-24 11:24:56 +1000872
Pavel Shilovsky9094fad2012-07-12 18:30:44 +0400873static bool
874smb2_can_echo(struct TCP_Server_Info *server)
875{
876 return server->echoes;
877}
878
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400879static void
880smb2_clear_stats(struct cifs_tcon *tcon)
881{
882#ifdef CONFIG_CIFS_STATS
883 int i;
884 for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
885 atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0);
886 atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0);
887 }
888#endif
889}
890
891static void
Steve French769ee6a2013-06-19 14:15:30 -0500892smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
893{
894 seq_puts(m, "\n\tShare Capabilities:");
895 if (tcon->capabilities & SMB2_SHARE_CAP_DFS)
896 seq_puts(m, " DFS,");
897 if (tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
898 seq_puts(m, " CONTINUOUS AVAILABILITY,");
899 if (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT)
900 seq_puts(m, " SCALEOUT,");
901 if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER)
902 seq_puts(m, " CLUSTER,");
903 if (tcon->capabilities & SMB2_SHARE_CAP_ASYMMETRIC)
904 seq_puts(m, " ASYMMETRIC,");
905 if (tcon->capabilities == 0)
906 seq_puts(m, " None");
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500907 if (tcon->ss_flags & SSINFO_FLAGS_ALIGNED_DEVICE)
908 seq_puts(m, " Aligned,");
909 if (tcon->ss_flags & SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE)
910 seq_puts(m, " Partition Aligned,");
911 if (tcon->ss_flags & SSINFO_FLAGS_NO_SEEK_PENALTY)
912 seq_puts(m, " SSD,");
913 if (tcon->ss_flags & SSINFO_FLAGS_TRIM_ENABLED)
914 seq_puts(m, " TRIM-support,");
915
Steve French769ee6a2013-06-19 14:15:30 -0500916 seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags);
Steve Frenche0386e42018-05-20 01:27:03 -0500917 seq_printf(m, "\n\ttid: 0x%x", tcon->tid);
Steven Frenchaf6a12e2013-10-09 20:55:53 -0500918 if (tcon->perf_sector_size)
919 seq_printf(m, "\tOptimal sector size: 0x%x",
920 tcon->perf_sector_size);
Steve Frenche0386e42018-05-20 01:27:03 -0500921 seq_printf(m, "\tMaximal Access: 0x%x", tcon->maximal_access);
Steve French769ee6a2013-06-19 14:15:30 -0500922}
923
924static void
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400925smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
926{
927#ifdef CONFIG_CIFS_STATS
928 atomic_t *sent = tcon->stats.smb2_stats.smb2_com_sent;
929 atomic_t *failed = tcon->stats.smb2_stats.smb2_com_failed;
Steve French1995d282018-07-27 15:14:04 -0500930
931 /*
932 * Can't display SMB2_NEGOTIATE, SESSION_SETUP, LOGOFF, CANCEL and ECHO
933 * totals (requests sent) since those SMBs are per-session not per tcon
934 */
935 seq_printf(m, "\nTreeConnects: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400936 atomic_read(&sent[SMB2_TREE_CONNECT_HE]),
937 atomic_read(&failed[SMB2_TREE_CONNECT_HE]));
Steve French1995d282018-07-27 15:14:04 -0500938 seq_printf(m, "\nTreeDisconnects: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400939 atomic_read(&sent[SMB2_TREE_DISCONNECT_HE]),
940 atomic_read(&failed[SMB2_TREE_DISCONNECT_HE]));
Steve French1995d282018-07-27 15:14:04 -0500941 seq_printf(m, "\nCreates: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400942 atomic_read(&sent[SMB2_CREATE_HE]),
943 atomic_read(&failed[SMB2_CREATE_HE]));
Steve French1995d282018-07-27 15:14:04 -0500944 seq_printf(m, "\nCloses: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400945 atomic_read(&sent[SMB2_CLOSE_HE]),
946 atomic_read(&failed[SMB2_CLOSE_HE]));
Steve French1995d282018-07-27 15:14:04 -0500947 seq_printf(m, "\nFlushes: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400948 atomic_read(&sent[SMB2_FLUSH_HE]),
949 atomic_read(&failed[SMB2_FLUSH_HE]));
Steve French1995d282018-07-27 15:14:04 -0500950 seq_printf(m, "\nReads: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400951 atomic_read(&sent[SMB2_READ_HE]),
952 atomic_read(&failed[SMB2_READ_HE]));
Steve French1995d282018-07-27 15:14:04 -0500953 seq_printf(m, "\nWrites: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400954 atomic_read(&sent[SMB2_WRITE_HE]),
955 atomic_read(&failed[SMB2_WRITE_HE]));
Steve French1995d282018-07-27 15:14:04 -0500956 seq_printf(m, "\nLocks: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400957 atomic_read(&sent[SMB2_LOCK_HE]),
958 atomic_read(&failed[SMB2_LOCK_HE]));
Steve French1995d282018-07-27 15:14:04 -0500959 seq_printf(m, "\nIOCTLs: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400960 atomic_read(&sent[SMB2_IOCTL_HE]),
961 atomic_read(&failed[SMB2_IOCTL_HE]));
Steve French1995d282018-07-27 15:14:04 -0500962 seq_printf(m, "\nQueryDirectories: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400963 atomic_read(&sent[SMB2_QUERY_DIRECTORY_HE]),
964 atomic_read(&failed[SMB2_QUERY_DIRECTORY_HE]));
Steve French1995d282018-07-27 15:14:04 -0500965 seq_printf(m, "\nChangeNotifies: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400966 atomic_read(&sent[SMB2_CHANGE_NOTIFY_HE]),
967 atomic_read(&failed[SMB2_CHANGE_NOTIFY_HE]));
Steve French1995d282018-07-27 15:14:04 -0500968 seq_printf(m, "\nQueryInfos: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400969 atomic_read(&sent[SMB2_QUERY_INFO_HE]),
970 atomic_read(&failed[SMB2_QUERY_INFO_HE]));
Steve French1995d282018-07-27 15:14:04 -0500971 seq_printf(m, "\nSetInfos: %d total %d failed",
Pavel Shilovskyd60622e2012-05-28 15:19:39 +0400972 atomic_read(&sent[SMB2_SET_INFO_HE]),
973 atomic_read(&failed[SMB2_SET_INFO_HE]));
974 seq_printf(m, "\nOplockBreaks: %d sent %d failed",
975 atomic_read(&sent[SMB2_OPLOCK_BREAK_HE]),
976 atomic_read(&failed[SMB2_OPLOCK_BREAK_HE]));
977#endif
978}
979
Pavel Shilovskyf0df7372012-09-18 16:20:26 -0700980static void
981smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
982{
David Howells2b0143b2015-03-17 22:25:59 +0000983 struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
Pavel Shilovsky53ef1012013-09-05 16:11:28 +0400984 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
985
Pavel Shilovskyf0df7372012-09-18 16:20:26 -0700986 cfile->fid.persistent_fid = fid->persistent_fid;
987 cfile->fid.volatile_fid = fid->volatile_fid;
Pavel Shilovsky42873b02013-09-05 21:30:16 +0400988 server->ops->set_oplock_level(cinode, oplock, fid->epoch,
989 &fid->purge_cache);
Pavel Shilovsky18cceb62013-09-05 13:01:06 +0400990 cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
Aurelien Aptel94f87372016-09-22 07:38:50 +0200991 memcpy(cfile->fid.create_guid, fid->create_guid, 16);
Pavel Shilovskyf0df7372012-09-18 16:20:26 -0700992}
993
Pavel Shilovsky760ad0c2012-09-25 11:00:07 +0400994static void
Pavel Shilovskyf0df7372012-09-18 16:20:26 -0700995smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
996 struct cifs_fid *fid)
997{
Pavel Shilovsky760ad0c2012-09-25 11:00:07 +0400998 SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
Pavel Shilovskyf0df7372012-09-18 16:20:26 -0700999}
1000
Pavel Shilovsky7a5cfb12012-09-18 16:20:28 -07001001static int
Steve French41c13582013-11-14 00:05:36 -06001002SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
1003 u64 persistent_fid, u64 volatile_fid,
1004 struct copychunk_ioctl *pcchunk)
1005{
1006 int rc;
1007 unsigned int ret_data_len;
1008 struct resume_key_req *res_key;
1009
1010 rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
1011 FSCTL_SRV_REQUEST_RESUME_KEY, true /* is_fsctl */,
1012 NULL, 0 /* no input */,
1013 (char **)&res_key, &ret_data_len);
1014
1015 if (rc) {
1016 cifs_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
1017 goto req_res_key_exit;
1018 }
1019 if (ret_data_len < sizeof(struct resume_key_req)) {
1020 cifs_dbg(VFS, "Invalid refcopy resume key length\n");
1021 rc = -EINVAL;
1022 goto req_res_key_exit;
1023 }
1024 memcpy(pcchunk->SourceKey, res_key->ResumeKey, COPY_CHUNK_RES_KEY_SIZE);
1025
1026req_res_key_exit:
1027 kfree(res_key);
1028 return rc;
1029}
1030
Sachin Prabhu620d8742017-02-10 16:03:51 +05301031static ssize_t
Sachin Prabhu312bbc52017-04-04 02:12:04 -05001032smb2_copychunk_range(const unsigned int xid,
Steve French41c13582013-11-14 00:05:36 -06001033 struct cifsFileInfo *srcfile,
1034 struct cifsFileInfo *trgtfile, u64 src_off,
1035 u64 len, u64 dest_off)
1036{
1037 int rc;
1038 unsigned int ret_data_len;
1039 struct copychunk_ioctl *pcchunk;
Steve French9bf0c9c2013-11-16 18:05:28 -06001040 struct copychunk_ioctl_rsp *retbuf = NULL;
1041 struct cifs_tcon *tcon;
1042 int chunks_copied = 0;
1043 bool chunk_sizes_updated = false;
Sachin Prabhu620d8742017-02-10 16:03:51 +05301044 ssize_t bytes_written, total_bytes_written = 0;
Steve French41c13582013-11-14 00:05:36 -06001045
1046 pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
1047
1048 if (pcchunk == NULL)
1049 return -ENOMEM;
1050
Sachin Prabhu312bbc52017-04-04 02:12:04 -05001051 cifs_dbg(FYI, "in smb2_copychunk_range - about to call request res key\n");
Steve French41c13582013-11-14 00:05:36 -06001052 /* Request a key from the server to identify the source of the copy */
1053 rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink),
1054 srcfile->fid.persistent_fid,
1055 srcfile->fid.volatile_fid, pcchunk);
1056
1057 /* Note: request_res_key sets res_key null only if rc !=0 */
1058 if (rc)
Steve French9bf0c9c2013-11-16 18:05:28 -06001059 goto cchunk_out;
Steve French41c13582013-11-14 00:05:36 -06001060
1061 /* For now array only one chunk long, will make more flexible later */
Fabian Frederickbc09d142014-12-10 15:41:15 -08001062 pcchunk->ChunkCount = cpu_to_le32(1);
Steve French41c13582013-11-14 00:05:36 -06001063 pcchunk->Reserved = 0;
Steve French41c13582013-11-14 00:05:36 -06001064 pcchunk->Reserved2 = 0;
1065
Steve French9bf0c9c2013-11-16 18:05:28 -06001066 tcon = tlink_tcon(trgtfile->tlink);
1067
1068 while (len > 0) {
1069 pcchunk->SourceOffset = cpu_to_le64(src_off);
1070 pcchunk->TargetOffset = cpu_to_le64(dest_off);
1071 pcchunk->Length =
1072 cpu_to_le32(min_t(u32, len, tcon->max_bytes_chunk));
1073
1074 /* Request server copy to target from src identified by key */
1075 rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
Steve French41c13582013-11-14 00:05:36 -06001076 trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001077 true /* is_fsctl */, (char *)pcchunk,
Steve French9bf0c9c2013-11-16 18:05:28 -06001078 sizeof(struct copychunk_ioctl), (char **)&retbuf,
1079 &ret_data_len);
1080 if (rc == 0) {
1081 if (ret_data_len !=
1082 sizeof(struct copychunk_ioctl_rsp)) {
1083 cifs_dbg(VFS, "invalid cchunk response size\n");
1084 rc = -EIO;
1085 goto cchunk_out;
1086 }
1087 if (retbuf->TotalBytesWritten == 0) {
1088 cifs_dbg(FYI, "no bytes copied\n");
1089 rc = -EIO;
1090 goto cchunk_out;
1091 }
1092 /*
1093 * Check if server claimed to write more than we asked
1094 */
1095 if (le32_to_cpu(retbuf->TotalBytesWritten) >
1096 le32_to_cpu(pcchunk->Length)) {
1097 cifs_dbg(VFS, "invalid copy chunk response\n");
1098 rc = -EIO;
1099 goto cchunk_out;
1100 }
1101 if (le32_to_cpu(retbuf->ChunksWritten) != 1) {
1102 cifs_dbg(VFS, "invalid num chunks written\n");
1103 rc = -EIO;
1104 goto cchunk_out;
1105 }
1106 chunks_copied++;
Steve French41c13582013-11-14 00:05:36 -06001107
Sachin Prabhu620d8742017-02-10 16:03:51 +05301108 bytes_written = le32_to_cpu(retbuf->TotalBytesWritten);
1109 src_off += bytes_written;
1110 dest_off += bytes_written;
1111 len -= bytes_written;
1112 total_bytes_written += bytes_written;
Steve French41c13582013-11-14 00:05:36 -06001113
Sachin Prabhu620d8742017-02-10 16:03:51 +05301114 cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %zu\n",
Steve French9bf0c9c2013-11-16 18:05:28 -06001115 le32_to_cpu(retbuf->ChunksWritten),
1116 le32_to_cpu(retbuf->ChunkBytesWritten),
Sachin Prabhu620d8742017-02-10 16:03:51 +05301117 bytes_written);
Steve French9bf0c9c2013-11-16 18:05:28 -06001118 } else if (rc == -EINVAL) {
1119 if (ret_data_len != sizeof(struct copychunk_ioctl_rsp))
1120 goto cchunk_out;
Steve French41c13582013-11-14 00:05:36 -06001121
Steve French9bf0c9c2013-11-16 18:05:28 -06001122 cifs_dbg(FYI, "MaxChunks %d BytesChunk %d MaxCopy %d\n",
1123 le32_to_cpu(retbuf->ChunksWritten),
1124 le32_to_cpu(retbuf->ChunkBytesWritten),
1125 le32_to_cpu(retbuf->TotalBytesWritten));
1126
1127 /*
1128 * Check if this is the first request using these sizes,
1129 * (ie check if copy succeed once with original sizes
1130 * and check if the server gave us different sizes after
1131 * we already updated max sizes on previous request).
1132 * if not then why is the server returning an error now
1133 */
1134 if ((chunks_copied != 0) || chunk_sizes_updated)
1135 goto cchunk_out;
1136
1137 /* Check that server is not asking us to grow size */
1138 if (le32_to_cpu(retbuf->ChunkBytesWritten) <
1139 tcon->max_bytes_chunk)
1140 tcon->max_bytes_chunk =
1141 le32_to_cpu(retbuf->ChunkBytesWritten);
1142 else
1143 goto cchunk_out; /* server gave us bogus size */
1144
1145 /* No need to change MaxChunks since already set to 1 */
1146 chunk_sizes_updated = true;
Sachin Prabhu2477bc52015-02-04 13:10:26 +00001147 } else
1148 goto cchunk_out;
Steve French9bf0c9c2013-11-16 18:05:28 -06001149 }
1150
1151cchunk_out:
Steve French41c13582013-11-14 00:05:36 -06001152 kfree(pcchunk);
Steve French24df1482016-09-29 04:20:23 -05001153 kfree(retbuf);
Sachin Prabhu620d8742017-02-10 16:03:51 +05301154 if (rc)
1155 return rc;
1156 else
1157 return total_bytes_written;
Steve French41c13582013-11-14 00:05:36 -06001158}
1159
1160static int
Pavel Shilovsky7a5cfb12012-09-18 16:20:28 -07001161smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
1162 struct cifs_fid *fid)
1163{
1164 return SMB2_flush(xid, tcon, fid->persistent_fid, fid->volatile_fid);
1165}
1166
Pavel Shilovsky09a47072012-09-18 16:20:29 -07001167static unsigned int
1168smb2_read_data_offset(char *buf)
1169{
1170 struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
1171 return rsp->DataOffset;
1172}
1173
1174static unsigned int
Long Li74dcf412017-11-22 17:38:46 -07001175smb2_read_data_length(char *buf, bool in_remaining)
Pavel Shilovsky09a47072012-09-18 16:20:29 -07001176{
1177 struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
Long Li74dcf412017-11-22 17:38:46 -07001178
1179 if (in_remaining)
1180 return le32_to_cpu(rsp->DataRemaining);
1181
Pavel Shilovsky09a47072012-09-18 16:20:29 -07001182 return le32_to_cpu(rsp->DataLength);
1183}
1184
Pavel Shilovskyd8e05032012-09-18 16:20:30 -07001185
1186static int
Steve Frenchdb8b6312014-09-22 05:13:55 -05001187smb2_sync_read(const unsigned int xid, struct cifs_fid *pfid,
Pavel Shilovskyd8e05032012-09-18 16:20:30 -07001188 struct cifs_io_parms *parms, unsigned int *bytes_read,
1189 char **buf, int *buf_type)
1190{
Steve Frenchdb8b6312014-09-22 05:13:55 -05001191 parms->persistent_fid = pfid->persistent_fid;
1192 parms->volatile_fid = pfid->volatile_fid;
Pavel Shilovskyd8e05032012-09-18 16:20:30 -07001193 return SMB2_read(xid, parms, bytes_read, buf, buf_type);
1194}
1195
Pavel Shilovsky009d3442012-09-18 16:20:30 -07001196static int
Steve Frenchdb8b6312014-09-22 05:13:55 -05001197smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid,
Pavel Shilovsky009d3442012-09-18 16:20:30 -07001198 struct cifs_io_parms *parms, unsigned int *written,
1199 struct kvec *iov, unsigned long nr_segs)
1200{
1201
Steve Frenchdb8b6312014-09-22 05:13:55 -05001202 parms->persistent_fid = pfid->persistent_fid;
1203 parms->volatile_fid = pfid->volatile_fid;
Pavel Shilovsky009d3442012-09-18 16:20:30 -07001204 return SMB2_write(xid, parms, written, iov, nr_segs);
1205}
1206
Steve Frenchd43cc792014-08-13 17:16:29 -05001207/* Set or clear the SPARSE_FILE attribute based on value passed in setsparse */
1208static bool smb2_set_sparse(const unsigned int xid, struct cifs_tcon *tcon,
1209 struct cifsFileInfo *cfile, struct inode *inode, __u8 setsparse)
1210{
1211 struct cifsInodeInfo *cifsi;
1212 int rc;
1213
1214 cifsi = CIFS_I(inode);
1215
1216 /* if file already sparse don't bother setting sparse again */
1217 if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && setsparse)
1218 return true; /* already sparse */
1219
1220 if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) && !setsparse)
1221 return true; /* already not sparse */
1222
1223 /*
1224 * Can't check for sparse support on share the usual way via the
1225 * FS attribute info (FILE_SUPPORTS_SPARSE_FILES) on the share
1226 * since Samba server doesn't set the flag on the share, yet
1227 * supports the set sparse FSCTL and returns sparse correctly
1228 * in the file attributes. If we fail setting sparse though we
1229 * mark that server does not support sparse files for this share
1230 * to avoid repeatedly sending the unsupported fsctl to server
1231 * if the file is repeatedly extended.
1232 */
1233 if (tcon->broken_sparse_sup)
1234 return false;
1235
1236 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1237 cfile->fid.volatile_fid, FSCTL_SET_SPARSE,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001238 true /* is_fctl */,
Aurelien Aptel51146622017-02-28 15:08:41 +01001239 &setsparse, 1, NULL, NULL);
Steve Frenchd43cc792014-08-13 17:16:29 -05001240 if (rc) {
1241 tcon->broken_sparse_sup = true;
1242 cifs_dbg(FYI, "set sparse rc = %d\n", rc);
1243 return false;
1244 }
1245
1246 if (setsparse)
1247 cifsi->cifsAttrs |= FILE_ATTRIBUTE_SPARSE_FILE;
1248 else
1249 cifsi->cifsAttrs &= (~FILE_ATTRIBUTE_SPARSE_FILE);
1250
1251 return true;
1252}
1253
Pavel Shilovskyc839ff22012-09-18 16:20:32 -07001254static int
1255smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
1256 struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
1257{
1258 __le64 eof = cpu_to_le64(size);
Steve French3d1a3742014-08-11 21:05:25 -05001259 struct inode *inode;
1260
1261 /*
1262 * If extending file more than one page make sparse. Many Linux fs
1263 * make files sparse by default when extending via ftruncate
1264 */
David Howells2b0143b2015-03-17 22:25:59 +00001265 inode = d_inode(cfile->dentry);
Steve French3d1a3742014-08-11 21:05:25 -05001266
1267 if (!set_alloc && (size > inode->i_size + 8192)) {
Steve French3d1a3742014-08-11 21:05:25 -05001268 __u8 set_sparse = 1;
Steve French3d1a3742014-08-11 21:05:25 -05001269
Steve Frenchd43cc792014-08-13 17:16:29 -05001270 /* whether set sparse succeeds or not, extend the file */
1271 smb2_set_sparse(xid, tcon, cfile, inode, set_sparse);
Steve French3d1a3742014-08-11 21:05:25 -05001272 }
1273
Pavel Shilovskyc839ff22012-09-18 16:20:32 -07001274 return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
Steve Frenchf29ebb42014-07-19 21:44:58 -05001275 cfile->fid.volatile_fid, cfile->pid, &eof, false);
Pavel Shilovskyc839ff22012-09-18 16:20:32 -07001276}
1277
Steve French02b16662015-06-27 21:18:36 -07001278static int
1279smb2_duplicate_extents(const unsigned int xid,
1280 struct cifsFileInfo *srcfile,
1281 struct cifsFileInfo *trgtfile, u64 src_off,
1282 u64 len, u64 dest_off)
1283{
1284 int rc;
1285 unsigned int ret_data_len;
Steve French02b16662015-06-27 21:18:36 -07001286 struct duplicate_extents_to_file dup_ext_buf;
1287 struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
1288
1289 /* server fileays advertise duplicate extent support with this flag */
1290 if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) &
1291 FILE_SUPPORTS_BLOCK_REFCOUNTING) == 0)
1292 return -EOPNOTSUPP;
1293
1294 dup_ext_buf.VolatileFileHandle = srcfile->fid.volatile_fid;
1295 dup_ext_buf.PersistentFileHandle = srcfile->fid.persistent_fid;
1296 dup_ext_buf.SourceFileOffset = cpu_to_le64(src_off);
1297 dup_ext_buf.TargetFileOffset = cpu_to_le64(dest_off);
1298 dup_ext_buf.ByteCount = cpu_to_le64(len);
1299 cifs_dbg(FYI, "duplicate extents: src off %lld dst off %lld len %lld",
1300 src_off, dest_off, len);
1301
1302 rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
1303 if (rc)
1304 goto duplicate_extents_out;
1305
1306 rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
1307 trgtfile->fid.volatile_fid,
1308 FSCTL_DUPLICATE_EXTENTS_TO_FILE,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001309 true /* is_fsctl */,
Aurelien Aptel51146622017-02-28 15:08:41 +01001310 (char *)&dup_ext_buf,
Steve French02b16662015-06-27 21:18:36 -07001311 sizeof(struct duplicate_extents_to_file),
Steve French24df1482016-09-29 04:20:23 -05001312 NULL,
Steve French02b16662015-06-27 21:18:36 -07001313 &ret_data_len);
1314
1315 if (ret_data_len > 0)
1316 cifs_dbg(FYI, "non-zero response length in duplicate extents");
1317
1318duplicate_extents_out:
1319 return rc;
1320}
Steve French02b16662015-06-27 21:18:36 -07001321
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001322static int
Steve French64a5cfa2013-10-14 15:31:32 -05001323smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
1324 struct cifsFileInfo *cfile)
1325{
1326 return SMB2_set_compression(xid, tcon, cfile->fid.persistent_fid,
1327 cfile->fid.volatile_fid);
1328}
1329
1330static int
Steve Frenchb3152e22015-06-24 03:17:02 -05001331smb3_set_integrity(const unsigned int xid, struct cifs_tcon *tcon,
1332 struct cifsFileInfo *cfile)
1333{
1334 struct fsctl_set_integrity_information_req integr_info;
Steve Frenchb3152e22015-06-24 03:17:02 -05001335 unsigned int ret_data_len;
1336
1337 integr_info.ChecksumAlgorithm = cpu_to_le16(CHECKSUM_TYPE_UNCHANGED);
1338 integr_info.Flags = 0;
1339 integr_info.Reserved = 0;
1340
1341 return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1342 cfile->fid.volatile_fid,
1343 FSCTL_SET_INTEGRITY_INFORMATION,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001344 true /* is_fsctl */,
Aurelien Aptel51146622017-02-28 15:08:41 +01001345 (char *)&integr_info,
Steve Frenchb3152e22015-06-24 03:17:02 -05001346 sizeof(struct fsctl_set_integrity_information_req),
Steve French24df1482016-09-29 04:20:23 -05001347 NULL,
Steve Frenchb3152e22015-06-24 03:17:02 -05001348 &ret_data_len);
1349
1350}
1351
1352static int
Steve French834170c2016-09-30 21:14:26 -05001353smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
1354 struct cifsFileInfo *cfile, void __user *ioc_buf)
1355{
1356 char *retbuf = NULL;
1357 unsigned int ret_data_len = 0;
1358 int rc;
1359 struct smb_snapshot_array snapshot_in;
1360
1361 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1362 cfile->fid.volatile_fid,
1363 FSCTL_SRV_ENUMERATE_SNAPSHOTS,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001364 true /* is_fsctl */,
Aurelien Aptel51146622017-02-28 15:08:41 +01001365 NULL, 0 /* no input data */,
Steve French834170c2016-09-30 21:14:26 -05001366 (char **)&retbuf,
1367 &ret_data_len);
1368 cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n",
1369 rc, ret_data_len);
1370 if (rc)
1371 return rc;
1372
1373 if (ret_data_len && (ioc_buf != NULL) && (retbuf != NULL)) {
1374 /* Fixup buffer */
1375 if (copy_from_user(&snapshot_in, ioc_buf,
1376 sizeof(struct smb_snapshot_array))) {
1377 rc = -EFAULT;
1378 kfree(retbuf);
1379 return rc;
1380 }
1381 if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
1382 rc = -ERANGE;
David Disseldorp0e5c7952017-05-03 17:39:09 +02001383 kfree(retbuf);
Steve French834170c2016-09-30 21:14:26 -05001384 return rc;
1385 }
1386
1387 if (ret_data_len > snapshot_in.snapshot_array_size)
1388 ret_data_len = snapshot_in.snapshot_array_size;
1389
1390 if (copy_to_user(ioc_buf, retbuf, ret_data_len))
1391 rc = -EFAULT;
1392 }
1393
1394 kfree(retbuf);
1395 return rc;
1396}
1397
1398static int
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001399smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
1400 const char *path, struct cifs_sb_info *cifs_sb,
1401 struct cifs_fid *fid, __u16 search_flags,
1402 struct cifs_search_info *srch_inf)
1403{
1404 __le16 *utf16_path;
1405 int rc;
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001406 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001407 struct cifs_open_parms oparms;
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001408
1409 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
1410 if (!utf16_path)
1411 return -ENOMEM;
1412
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001413 oparms.tcon = tcon;
1414 oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA;
1415 oparms.disposition = FILE_OPEN;
1416 oparms.create_options = 0;
1417 oparms.fid = fid;
Pavel Shilovsky9cbc0b72013-07-09 18:40:58 +04001418 oparms.reconnect = false;
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001419
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001420 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001421 kfree(utf16_path);
1422 if (rc) {
Pavel Shilovskydcd878382017-06-06 16:58:58 -07001423 cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001424 return rc;
1425 }
1426
1427 srch_inf->entries_in_buffer = 0;
1428 srch_inf->index_of_last_entry = 0;
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001429
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001430 rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
1431 fid->volatile_fid, 0, srch_inf);
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001432 if (rc) {
Pavel Shilovskydcd878382017-06-06 16:58:58 -07001433 cifs_dbg(FYI, "query directory failed rc=%d\n", rc);
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001434 SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07001435 }
1436 return rc;
1437}
1438
1439static int
1440smb2_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
1441 struct cifs_fid *fid, __u16 search_flags,
1442 struct cifs_search_info *srch_inf)
1443{
1444 return SMB2_query_directory(xid, tcon, fid->persistent_fid,
1445 fid->volatile_fid, 0, srch_inf);
1446}
1447
1448static int
1449smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
1450 struct cifs_fid *fid)
1451{
1452 return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
1453}
1454
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001455/*
1456* If we negotiate SMB2 protocol and get STATUS_PENDING - update
1457* the number of credits and return true. Otherwise - return false.
1458*/
1459static bool
1460smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
1461{
Ronnie Sahlberg49f466b2018-06-01 10:53:06 +10001462 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001463
Pavel Shilovsky31473fc2016-10-24 15:33:04 -07001464 if (shdr->Status != STATUS_PENDING)
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001465 return false;
1466
1467 if (!length) {
1468 spin_lock(&server->req_lock);
Pavel Shilovsky31473fc2016-10-24 15:33:04 -07001469 server->credits += le16_to_cpu(shdr->CreditRequest);
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001470 spin_unlock(&server->req_lock);
1471 wake_up(&server->request_q);
1472 }
1473
1474 return true;
1475}
1476
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001477static bool
1478smb2_is_session_expired(char *buf)
1479{
Ronnie Sahlberg49f466b2018-06-01 10:53:06 +10001480 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001481
Mark Symsd81243c2018-05-24 09:47:31 +01001482 if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED &&
1483 shdr->Status != STATUS_USER_SESSION_DELETED)
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001484 return false;
1485
Mark Symsd81243c2018-05-24 09:47:31 +01001486 cifs_dbg(FYI, "Session expired or deleted\n");
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001487 return true;
1488}
1489
Pavel Shilovsky983c88a2012-09-18 16:20:33 -07001490static int
1491smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
1492 struct cifsInodeInfo *cinode)
1493{
Pavel Shilovsky0822f512012-09-19 06:22:45 -07001494 if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
1495 return SMB2_lease_break(0, tcon, cinode->lease_key,
1496 smb2_get_lease_state(cinode));
1497
Pavel Shilovsky983c88a2012-09-18 16:20:33 -07001498 return SMB2_oplock_break(0, tcon, fid->persistent_fid,
1499 fid->volatile_fid,
Pavel Shilovsky18cceb62013-09-05 13:01:06 +04001500 CIFS_CACHE_READ(cinode) ? 1 : 0);
Pavel Shilovsky983c88a2012-09-18 16:20:33 -07001501}
1502
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -07001503static int
1504smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
1505 struct kstatfs *buf)
1506{
1507 int rc;
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -07001508 __le16 srch_path = 0; /* Null - open root of share */
1509 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001510 struct cifs_open_parms oparms;
1511 struct cifs_fid fid;
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -07001512
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001513 oparms.tcon = tcon;
1514 oparms.desired_access = FILE_READ_ATTRIBUTES;
1515 oparms.disposition = FILE_OPEN;
1516 oparms.create_options = 0;
1517 oparms.fid = &fid;
Pavel Shilovsky9cbc0b72013-07-09 18:40:58 +04001518 oparms.reconnect = false;
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001519
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001520 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -07001521 if (rc)
1522 return rc;
1523 buf->f_type = SMB2_MAGIC_NUMBER;
Pavel Shilovsky064f6042013-07-09 18:20:30 +04001524 rc = SMB2_QFS_info(xid, tcon, fid.persistent_fid, fid.volatile_fid,
1525 buf);
1526 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -07001527 return rc;
1528}
1529
Steve French2d304212018-06-24 23:28:12 -05001530static int
1531smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
1532 struct kstatfs *buf)
1533{
1534 int rc;
1535 __le16 srch_path = 0; /* Null - open root of share */
1536 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
1537 struct cifs_open_parms oparms;
1538 struct cifs_fid fid;
1539
1540 if (!tcon->posix_extensions)
1541 return smb2_queryfs(xid, tcon, buf);
1542
1543 oparms.tcon = tcon;
1544 oparms.desired_access = FILE_READ_ATTRIBUTES;
1545 oparms.disposition = FILE_OPEN;
1546 oparms.create_options = 0;
1547 oparms.fid = &fid;
1548 oparms.reconnect = false;
1549
1550 rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
1551 if (rc)
1552 return rc;
1553
1554 rc = SMB311_posix_qfs_info(xid, tcon, fid.persistent_fid,
1555 fid.volatile_fid, buf);
1556 buf->f_type = SMB2_MAGIC_NUMBER;
1557 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
1558 return rc;
1559}
Steve French2d304212018-06-24 23:28:12 -05001560
Pavel Shilovsky027e8ee2012-09-19 06:22:43 -07001561static bool
1562smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
1563{
1564 return ob1->fid.persistent_fid == ob2->fid.persistent_fid &&
1565 ob1->fid.volatile_fid == ob2->fid.volatile_fid;
1566}
1567
Pavel Shilovskyf7ba7fe2012-09-19 06:22:43 -07001568static int
1569smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
1570 __u64 length, __u32 type, int lock, int unlock, bool wait)
1571{
1572 if (unlock && !lock)
1573 type = SMB2_LOCKFLAG_UNLOCK;
1574 return SMB2_lock(xid, tlink_tcon(cfile->tlink),
1575 cfile->fid.persistent_fid, cfile->fid.volatile_fid,
1576 current->tgid, length, offset, type, wait);
1577}
1578
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -07001579static void
1580smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid)
1581{
1582 memcpy(fid->lease_key, CIFS_I(inode)->lease_key, SMB2_LEASE_KEY_SIZE);
1583}
1584
1585static void
1586smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
1587{
1588 memcpy(CIFS_I(inode)->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
1589}
1590
1591static void
1592smb2_new_lease_key(struct cifs_fid *fid)
1593{
Steve Frenchfa70b872016-09-22 00:39:34 -05001594 generate_random_uuid(fid->lease_key);
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -07001595}
1596
Aurelien Aptel9d496402017-02-13 16:16:49 +01001597static int
1598smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
1599 const char *search_name,
1600 struct dfs_info3_param **target_nodes,
1601 unsigned int *num_of_nodes,
1602 const struct nls_table *nls_codepage, int remap)
1603{
1604 int rc;
1605 __le16 *utf16_path = NULL;
1606 int utf16_path_len = 0;
1607 struct cifs_tcon *tcon;
1608 struct fsctl_get_dfs_referral_req *dfs_req = NULL;
1609 struct get_dfs_referral_rsp *dfs_rsp = NULL;
1610 u32 dfs_req_size = 0, dfs_rsp_size = 0;
1611
1612 cifs_dbg(FYI, "smb2_get_dfs_refer path <%s>\n", search_name);
1613
1614 /*
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001615 * Try to use the IPC tcon, otherwise just use any
Aurelien Aptel9d496402017-02-13 16:16:49 +01001616 */
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001617 tcon = ses->tcon_ipc;
1618 if (tcon == NULL) {
1619 spin_lock(&cifs_tcp_ses_lock);
1620 tcon = list_first_entry_or_null(&ses->tcon_list,
1621 struct cifs_tcon,
1622 tcon_list);
1623 if (tcon)
1624 tcon->tc_count++;
1625 spin_unlock(&cifs_tcp_ses_lock);
1626 }
Aurelien Aptel9d496402017-02-13 16:16:49 +01001627
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001628 if (tcon == NULL) {
Aurelien Aptel9d496402017-02-13 16:16:49 +01001629 cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
1630 ses);
1631 rc = -ENOTCONN;
1632 goto out;
1633 }
1634
1635 utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
1636 &utf16_path_len,
1637 nls_codepage, remap);
1638 if (!utf16_path) {
1639 rc = -ENOMEM;
1640 goto out;
1641 }
1642
1643 dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
1644 dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
1645 if (!dfs_req) {
1646 rc = -ENOMEM;
1647 goto out;
1648 }
1649
1650 /* Highest DFS referral version understood */
1651 dfs_req->MaxReferralLevel = DFS_VERSION;
1652
1653 /* Path to resolve in an UTF-16 null-terminated string */
1654 memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
1655
1656 do {
Aurelien Aptel9d496402017-02-13 16:16:49 +01001657 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
1658 FSCTL_DFS_GET_REFERRALS,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001659 true /* is_fsctl */,
Aurelien Aptel9d496402017-02-13 16:16:49 +01001660 (char *)dfs_req, dfs_req_size,
1661 (char **)&dfs_rsp, &dfs_rsp_size);
Aurelien Aptel9d496402017-02-13 16:16:49 +01001662 } while (rc == -EAGAIN);
1663
1664 if (rc) {
Steve French2564f2f2018-03-21 23:16:36 -05001665 if ((rc != -ENOENT) && (rc != -EOPNOTSUPP))
Aurelien Aptel57025912017-11-21 14:47:56 +01001666 cifs_dbg(VFS, "ioctl error in smb2_get_dfs_refer rc=%d\n", rc);
Aurelien Aptel9d496402017-02-13 16:16:49 +01001667 goto out;
1668 }
1669
1670 rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
1671 num_of_nodes, target_nodes,
1672 nls_codepage, remap, search_name,
1673 true /* is_unicode */);
1674 if (rc) {
1675 cifs_dbg(VFS, "parse error in smb2_get_dfs_refer rc=%d\n", rc);
1676 goto out;
1677 }
1678
1679 out:
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001680 if (tcon && !tcon->ipc) {
1681 /* ipc tcons are not refcounted */
Aurelien Aptel9d496402017-02-13 16:16:49 +01001682 spin_lock(&cifs_tcp_ses_lock);
1683 tcon->tc_count--;
1684 spin_unlock(&cifs_tcp_ses_lock);
1685 }
1686 kfree(utf16_path);
1687 kfree(dfs_req);
1688 kfree(dfs_rsp);
1689 return rc;
1690}
Pavel Shilovsky78932422016-07-24 10:37:38 +03001691#define SMB2_SYMLINK_STRUCT_SIZE \
1692 (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
1693
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001694static int
1695smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
1696 const char *full_path, char **target_path,
1697 struct cifs_sb_info *cifs_sb)
1698{
1699 int rc;
1700 __le16 *utf16_path;
1701 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
1702 struct cifs_open_parms oparms;
1703 struct cifs_fid fid;
Ronnie Sahlberg91cb74f2018-04-13 09:03:19 +10001704 struct kvec err_iov = {NULL, 0};
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001705 struct smb2_err_rsp *err_buf = NULL;
1706 int resp_buftype;
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001707 struct smb2_symlink_err_rsp *symlink;
Pavel Shilovsky78932422016-07-24 10:37:38 +03001708 unsigned int sub_len;
1709 unsigned int sub_offset;
1710 unsigned int print_len;
1711 unsigned int print_offset;
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001712
1713 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
1714
1715 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
1716 if (!utf16_path)
1717 return -ENOMEM;
1718
1719 oparms.tcon = tcon;
1720 oparms.desired_access = FILE_READ_ATTRIBUTES;
1721 oparms.disposition = FILE_OPEN;
1722 oparms.create_options = 0;
1723 oparms.fid = &fid;
1724 oparms.reconnect = false;
1725
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001726 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov,
1727 &resp_buftype);
Gustavo A. R. Silva0d568cd2018-04-13 10:13:29 -05001728 if (!rc || !err_iov.iov_base) {
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001729 rc = -ENOENT;
Dan Carpenterff361fd2018-06-19 15:25:30 +03001730 goto free_path;
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001731 }
Pavel Shilovsky78932422016-07-24 10:37:38 +03001732
Ronnie Sahlberg91cb74f2018-04-13 09:03:19 +10001733 err_buf = err_iov.iov_base;
Pavel Shilovsky78932422016-07-24 10:37:38 +03001734 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10001735 err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001736 rc = -ENOENT;
1737 goto querty_exit;
Pavel Shilovsky78932422016-07-24 10:37:38 +03001738 }
1739
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001740 /* open must fail on symlink - reset rc */
1741 rc = 0;
1742 symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
1743 sub_len = le16_to_cpu(symlink->SubstituteNameLength);
1744 sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
Pavel Shilovsky78932422016-07-24 10:37:38 +03001745 print_len = le16_to_cpu(symlink->PrintNameLength);
1746 print_offset = le16_to_cpu(symlink->PrintNameOffset);
1747
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10001748 if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001749 rc = -ENOENT;
1750 goto querty_exit;
Pavel Shilovsky78932422016-07-24 10:37:38 +03001751 }
1752
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10001753 if (err_iov.iov_len <
1754 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001755 rc = -ENOENT;
1756 goto querty_exit;
Pavel Shilovsky78932422016-07-24 10:37:38 +03001757 }
1758
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001759 *target_path = cifs_strndup_from_utf16(
1760 (char *)symlink->PathBuffer + sub_offset,
1761 sub_len, true, cifs_sb->local_nls);
1762 if (!(*target_path)) {
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001763 rc = -ENOMEM;
1764 goto querty_exit;
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001765 }
1766 convert_delimiter(*target_path, '/');
1767 cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001768
1769 querty_exit:
1770 free_rsp_buf(resp_buftype, err_buf);
Dan Carpenterff361fd2018-06-19 15:25:30 +03001771 free_path:
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04001772 kfree(utf16_path);
1773 return rc;
1774}
1775
Arnd Bergmann84908422017-06-27 17:06:13 +02001776#ifdef CONFIG_CIFS_ACL
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05001777static struct cifs_ntsd *
1778get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
1779 const struct cifs_fid *cifsfid, u32 *pacllen)
1780{
1781 struct cifs_ntsd *pntsd = NULL;
1782 unsigned int xid;
1783 int rc = -EOPNOTSUPP;
1784 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1785
1786 if (IS_ERR(tlink))
1787 return ERR_CAST(tlink);
1788
1789 xid = get_xid();
1790 cifs_dbg(FYI, "trying to get acl\n");
1791
1792 rc = SMB2_query_acl(xid, tlink_tcon(tlink), cifsfid->persistent_fid,
1793 cifsfid->volatile_fid, (void **)&pntsd, pacllen);
1794 free_xid(xid);
1795
1796 cifs_put_tlink(tlink);
1797
1798 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1799 if (rc)
1800 return ERR_PTR(rc);
1801 return pntsd;
1802
1803}
1804
1805static struct cifs_ntsd *
1806get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
1807 const char *path, u32 *pacllen)
1808{
1809 struct cifs_ntsd *pntsd = NULL;
1810 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
1811 unsigned int xid;
1812 int rc;
1813 struct cifs_tcon *tcon;
1814 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1815 struct cifs_fid fid;
1816 struct cifs_open_parms oparms;
1817 __le16 *utf16_path;
1818
1819 cifs_dbg(FYI, "get smb3 acl for path %s\n", path);
1820 if (IS_ERR(tlink))
1821 return ERR_CAST(tlink);
1822
1823 tcon = tlink_tcon(tlink);
1824 xid = get_xid();
1825
1826 if (backup_cred(cifs_sb))
Colin Ian King709340a2017-07-05 13:47:34 +01001827 oparms.create_options = CREATE_OPEN_BACKUP_INTENT;
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05001828 else
1829 oparms.create_options = 0;
1830
1831 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
Steve Frenchcfe89092018-05-19 02:04:55 -05001832 if (!utf16_path) {
1833 rc = -ENOMEM;
1834 free_xid(xid);
1835 return ERR_PTR(rc);
1836 }
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05001837
1838 oparms.tcon = tcon;
1839 oparms.desired_access = READ_CONTROL;
1840 oparms.disposition = FILE_OPEN;
1841 oparms.fid = &fid;
1842 oparms.reconnect = false;
1843
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001844 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05001845 kfree(utf16_path);
1846 if (!rc) {
1847 rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
1848 fid.volatile_fid, (void **)&pntsd, pacllen);
1849 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
1850 }
1851
1852 cifs_put_tlink(tlink);
1853 free_xid(xid);
1854
1855 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1856 if (rc)
1857 return ERR_PTR(rc);
1858 return pntsd;
1859}
1860
Shirish Pargaonkar366ed842017-06-28 22:37:32 -05001861#ifdef CONFIG_CIFS_ACL
1862static int
1863set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1864 struct inode *inode, const char *path, int aclflag)
1865{
1866 u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
1867 unsigned int xid;
1868 int rc, access_flags = 0;
1869 struct cifs_tcon *tcon;
1870 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1871 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1872 struct cifs_fid fid;
1873 struct cifs_open_parms oparms;
1874 __le16 *utf16_path;
1875
1876 cifs_dbg(FYI, "set smb3 acl for path %s\n", path);
1877 if (IS_ERR(tlink))
1878 return PTR_ERR(tlink);
1879
1880 tcon = tlink_tcon(tlink);
1881 xid = get_xid();
1882
1883 if (backup_cred(cifs_sb))
1884 oparms.create_options = CREATE_OPEN_BACKUP_INTENT;
1885 else
1886 oparms.create_options = 0;
1887
1888 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1889 access_flags = WRITE_OWNER;
1890 else
1891 access_flags = WRITE_DAC;
1892
1893 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
Steve Frenchcfe89092018-05-19 02:04:55 -05001894 if (!utf16_path) {
1895 rc = -ENOMEM;
1896 free_xid(xid);
1897 return rc;
1898 }
Shirish Pargaonkar366ed842017-06-28 22:37:32 -05001899
1900 oparms.tcon = tcon;
1901 oparms.desired_access = access_flags;
1902 oparms.disposition = FILE_OPEN;
1903 oparms.path = path;
1904 oparms.fid = &fid;
1905 oparms.reconnect = false;
1906
Ronnie Sahlberg9d874c32018-06-08 13:21:18 +10001907 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
Shirish Pargaonkar366ed842017-06-28 22:37:32 -05001908 kfree(utf16_path);
1909 if (!rc) {
1910 rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
1911 fid.volatile_fid, pnntsd, acllen, aclflag);
1912 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
1913 }
1914
1915 cifs_put_tlink(tlink);
1916 free_xid(xid);
1917 return rc;
1918}
1919#endif /* CIFS_ACL */
1920
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05001921/* Retrieve an ACL from the server */
1922static struct cifs_ntsd *
1923get_smb2_acl(struct cifs_sb_info *cifs_sb,
1924 struct inode *inode, const char *path,
1925 u32 *pacllen)
1926{
1927 struct cifs_ntsd *pntsd = NULL;
1928 struct cifsFileInfo *open_file = NULL;
1929
1930 if (inode)
1931 open_file = find_readable_file(CIFS_I(inode), true);
1932 if (!open_file)
1933 return get_smb2_acl_by_path(cifs_sb, path, pacllen);
1934
1935 pntsd = get_smb2_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
1936 cifsFileInfo_put(open_file);
1937 return pntsd;
1938}
Arnd Bergmann84908422017-06-27 17:06:13 +02001939#endif
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05001940
Steve French30175622014-08-17 18:16:40 -05001941static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
1942 loff_t offset, loff_t len, bool keep_size)
1943{
1944 struct inode *inode;
1945 struct cifsInodeInfo *cifsi;
1946 struct cifsFileInfo *cfile = file->private_data;
1947 struct file_zero_data_information fsctl_buf;
1948 long rc;
1949 unsigned int xid;
1950
1951 xid = get_xid();
1952
David Howells2b0143b2015-03-17 22:25:59 +00001953 inode = d_inode(cfile->dentry);
Steve French30175622014-08-17 18:16:40 -05001954 cifsi = CIFS_I(inode);
1955
1956 /* if file not oplocked can't be sure whether asking to extend size */
1957 if (!CIFS_CACHE_READ(cifsi))
Steve Frenchcfe89092018-05-19 02:04:55 -05001958 if (keep_size == false) {
1959 rc = -EOPNOTSUPP;
1960 free_xid(xid);
1961 return rc;
1962 }
Steve French30175622014-08-17 18:16:40 -05001963
Steve French2bb93d22014-08-20 18:56:29 -05001964 /*
Steve French30175622014-08-17 18:16:40 -05001965 * Must check if file sparse since fallocate -z (zero range) assumes
1966 * non-sparse allocation
1967 */
Steve Frenchcfe89092018-05-19 02:04:55 -05001968 if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) {
1969 rc = -EOPNOTSUPP;
1970 free_xid(xid);
1971 return rc;
1972 }
Steve French30175622014-08-17 18:16:40 -05001973
1974 /*
1975 * need to make sure we are not asked to extend the file since the SMB3
1976 * fsctl does not change the file size. In the future we could change
1977 * this to zero the first part of the range then set the file size
1978 * which for a non sparse file would zero the newly extended range
1979 */
1980 if (keep_size == false)
Steve Frenchcfe89092018-05-19 02:04:55 -05001981 if (i_size_read(inode) < offset + len) {
1982 rc = -EOPNOTSUPP;
1983 free_xid(xid);
1984 return rc;
1985 }
Steve French30175622014-08-17 18:16:40 -05001986
1987 cifs_dbg(FYI, "offset %lld len %lld", offset, len);
1988
1989 fsctl_buf.FileOffset = cpu_to_le64(offset);
1990 fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
1991
1992 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
1993 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01001994 true /* is_fctl */, (char *)&fsctl_buf,
Steve French30175622014-08-17 18:16:40 -05001995 sizeof(struct file_zero_data_information), NULL, NULL);
1996 free_xid(xid);
1997 return rc;
1998}
1999
Steve French31742c52014-08-17 08:38:47 -05002000static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
2001 loff_t offset, loff_t len)
2002{
2003 struct inode *inode;
2004 struct cifsInodeInfo *cifsi;
2005 struct cifsFileInfo *cfile = file->private_data;
2006 struct file_zero_data_information fsctl_buf;
2007 long rc;
2008 unsigned int xid;
2009 __u8 set_sparse = 1;
2010
2011 xid = get_xid();
2012
David Howells2b0143b2015-03-17 22:25:59 +00002013 inode = d_inode(cfile->dentry);
Steve French31742c52014-08-17 08:38:47 -05002014 cifsi = CIFS_I(inode);
2015
2016 /* Need to make file sparse, if not already, before freeing range. */
2017 /* Consider adding equivalent for compressed since it could also work */
Steve Frenchcfe89092018-05-19 02:04:55 -05002018 if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) {
2019 rc = -EOPNOTSUPP;
2020 free_xid(xid);
2021 return rc;
2022 }
Steve French31742c52014-08-17 08:38:47 -05002023
2024 cifs_dbg(FYI, "offset %lld len %lld", offset, len);
2025
2026 fsctl_buf.FileOffset = cpu_to_le64(offset);
2027 fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
2028
2029 rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
2030 cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
Aurelien Aptel63a83b82018-01-24 13:46:11 +01002031 true /* is_fctl */, (char *)&fsctl_buf,
Steve French31742c52014-08-17 08:38:47 -05002032 sizeof(struct file_zero_data_information), NULL, NULL);
2033 free_xid(xid);
2034 return rc;
2035}
2036
Steve French9ccf3212014-10-18 17:01:15 -05002037static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
2038 loff_t off, loff_t len, bool keep_size)
2039{
2040 struct inode *inode;
2041 struct cifsInodeInfo *cifsi;
2042 struct cifsFileInfo *cfile = file->private_data;
2043 long rc = -EOPNOTSUPP;
2044 unsigned int xid;
2045
2046 xid = get_xid();
2047
David Howells2b0143b2015-03-17 22:25:59 +00002048 inode = d_inode(cfile->dentry);
Steve French9ccf3212014-10-18 17:01:15 -05002049 cifsi = CIFS_I(inode);
2050
2051 /* if file not oplocked can't be sure whether asking to extend size */
2052 if (!CIFS_CACHE_READ(cifsi))
Steve Frenchcfe89092018-05-19 02:04:55 -05002053 if (keep_size == false) {
2054 free_xid(xid);
2055 return rc;
2056 }
Steve French9ccf3212014-10-18 17:01:15 -05002057
2058 /*
2059 * Files are non-sparse by default so falloc may be a no-op
2060 * Must check if file sparse. If not sparse, and not extending
2061 * then no need to do anything since file already allocated
2062 */
2063 if ((cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) == 0) {
2064 if (keep_size == true)
Steve Frenchcfe89092018-05-19 02:04:55 -05002065 rc = 0;
Steve French9ccf3212014-10-18 17:01:15 -05002066 /* check if extending file */
2067 else if (i_size_read(inode) >= off + len)
2068 /* not extending file and already not sparse */
Steve Frenchcfe89092018-05-19 02:04:55 -05002069 rc = 0;
Steve French9ccf3212014-10-18 17:01:15 -05002070 /* BB: in future add else clause to extend file */
2071 else
Steve Frenchcfe89092018-05-19 02:04:55 -05002072 rc = -EOPNOTSUPP;
2073 free_xid(xid);
2074 return rc;
Steve French9ccf3212014-10-18 17:01:15 -05002075 }
2076
2077 if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
2078 /*
2079 * Check if falloc starts within first few pages of file
2080 * and ends within a few pages of the end of file to
2081 * ensure that most of file is being forced to be
2082 * fallocated now. If so then setting whole file sparse
2083 * ie potentially making a few extra pages at the beginning
2084 * or end of the file non-sparse via set_sparse is harmless.
2085 */
Steve Frenchcfe89092018-05-19 02:04:55 -05002086 if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) {
2087 rc = -EOPNOTSUPP;
2088 free_xid(xid);
2089 return rc;
2090 }
Steve French9ccf3212014-10-18 17:01:15 -05002091
2092 rc = smb2_set_sparse(xid, tcon, cfile, inode, false);
2093 }
2094 /* BB: else ... in future add code to extend file and set sparse */
2095
2096
2097 free_xid(xid);
2098 return rc;
2099}
2100
2101
Steve French31742c52014-08-17 08:38:47 -05002102static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
2103 loff_t off, loff_t len)
2104{
2105 /* KEEP_SIZE already checked for by do_fallocate */
2106 if (mode & FALLOC_FL_PUNCH_HOLE)
2107 return smb3_punch_hole(file, tcon, off, len);
Steve French30175622014-08-17 18:16:40 -05002108 else if (mode & FALLOC_FL_ZERO_RANGE) {
2109 if (mode & FALLOC_FL_KEEP_SIZE)
2110 return smb3_zero_range(file, tcon, off, len, true);
2111 return smb3_zero_range(file, tcon, off, len, false);
Steve French9ccf3212014-10-18 17:01:15 -05002112 } else if (mode == FALLOC_FL_KEEP_SIZE)
2113 return smb3_simple_falloc(file, tcon, off, len, true);
2114 else if (mode == 0)
2115 return smb3_simple_falloc(file, tcon, off, len, false);
Steve French31742c52014-08-17 08:38:47 -05002116
2117 return -EOPNOTSUPP;
2118}
2119
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04002120static void
Sachin Prabhuc11f1df2014-03-11 16:11:47 +00002121smb2_downgrade_oplock(struct TCP_Server_Info *server,
2122 struct cifsInodeInfo *cinode, bool set_level2)
2123{
2124 if (set_level2)
2125 server->ops->set_oplock_level(cinode, SMB2_OPLOCK_LEVEL_II,
2126 0, NULL);
2127 else
2128 server->ops->set_oplock_level(cinode, 0, 0, NULL);
2129}
2130
2131static void
Pavel Shilovsky42873b02013-09-05 21:30:16 +04002132smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
2133 unsigned int epoch, bool *purge_cache)
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04002134{
2135 oplock &= 0xFF;
2136 if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
2137 return;
2138 if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
Pavel Shilovsky42873b02013-09-05 21:30:16 +04002139 cinode->oplock = CIFS_CACHE_RHW_FLG;
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04002140 cifs_dbg(FYI, "Batch Oplock granted on inode %p\n",
2141 &cinode->vfs_inode);
2142 } else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
Pavel Shilovsky42873b02013-09-05 21:30:16 +04002143 cinode->oplock = CIFS_CACHE_RW_FLG;
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04002144 cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n",
2145 &cinode->vfs_inode);
2146 } else if (oplock == SMB2_OPLOCK_LEVEL_II) {
2147 cinode->oplock = CIFS_CACHE_READ_FLG;
2148 cifs_dbg(FYI, "Level II Oplock granted on inode %p\n",
2149 &cinode->vfs_inode);
2150 } else
2151 cinode->oplock = 0;
2152}
2153
2154static void
Pavel Shilovsky42873b02013-09-05 21:30:16 +04002155smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
2156 unsigned int epoch, bool *purge_cache)
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04002157{
2158 char message[5] = {0};
2159
2160 oplock &= 0xFF;
2161 if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
2162 return;
2163
2164 cinode->oplock = 0;
2165 if (oplock & SMB2_LEASE_READ_CACHING_HE) {
2166 cinode->oplock |= CIFS_CACHE_READ_FLG;
2167 strcat(message, "R");
2168 }
2169 if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) {
2170 cinode->oplock |= CIFS_CACHE_HANDLE_FLG;
2171 strcat(message, "H");
2172 }
2173 if (oplock & SMB2_LEASE_WRITE_CACHING_HE) {
2174 cinode->oplock |= CIFS_CACHE_WRITE_FLG;
2175 strcat(message, "W");
2176 }
2177 if (!cinode->oplock)
2178 strcat(message, "None");
2179 cifs_dbg(FYI, "%s Lease granted on inode %p\n", message,
2180 &cinode->vfs_inode);
2181}
2182
Pavel Shilovsky42873b02013-09-05 21:30:16 +04002183static void
2184smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
2185 unsigned int epoch, bool *purge_cache)
2186{
2187 unsigned int old_oplock = cinode->oplock;
2188
2189 smb21_set_oplock_level(cinode, oplock, epoch, purge_cache);
2190
2191 if (purge_cache) {
2192 *purge_cache = false;
2193 if (old_oplock == CIFS_CACHE_READ_FLG) {
2194 if (cinode->oplock == CIFS_CACHE_READ_FLG &&
2195 (epoch - cinode->epoch > 0))
2196 *purge_cache = true;
2197 else if (cinode->oplock == CIFS_CACHE_RH_FLG &&
2198 (epoch - cinode->epoch > 1))
2199 *purge_cache = true;
2200 else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
2201 (epoch - cinode->epoch > 1))
2202 *purge_cache = true;
2203 else if (cinode->oplock == 0 &&
2204 (epoch - cinode->epoch > 0))
2205 *purge_cache = true;
2206 } else if (old_oplock == CIFS_CACHE_RH_FLG) {
2207 if (cinode->oplock == CIFS_CACHE_RH_FLG &&
2208 (epoch - cinode->epoch > 0))
2209 *purge_cache = true;
2210 else if (cinode->oplock == CIFS_CACHE_RHW_FLG &&
2211 (epoch - cinode->epoch > 1))
2212 *purge_cache = true;
2213 }
2214 cinode->epoch = epoch;
2215 }
2216}
2217
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04002218static bool
2219smb2_is_read_op(__u32 oplock)
2220{
2221 return oplock == SMB2_OPLOCK_LEVEL_II;
2222}
2223
2224static bool
2225smb21_is_read_op(__u32 oplock)
2226{
2227 return (oplock & SMB2_LEASE_READ_CACHING_HE) &&
2228 !(oplock & SMB2_LEASE_WRITE_CACHING_HE);
2229}
2230
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002231static __le32
2232map_oplock_to_lease(u8 oplock)
2233{
2234 if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
2235 return SMB2_LEASE_WRITE_CACHING | SMB2_LEASE_READ_CACHING;
2236 else if (oplock == SMB2_OPLOCK_LEVEL_II)
2237 return SMB2_LEASE_READ_CACHING;
2238 else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
2239 return SMB2_LEASE_HANDLE_CACHING | SMB2_LEASE_READ_CACHING |
2240 SMB2_LEASE_WRITE_CACHING;
2241 return 0;
2242}
2243
Pavel Shilovskya41a28b2013-09-04 13:07:41 +04002244static char *
2245smb2_create_lease_buf(u8 *lease_key, u8 oplock)
2246{
2247 struct create_lease *buf;
2248
2249 buf = kzalloc(sizeof(struct create_lease), GFP_KERNEL);
2250 if (!buf)
2251 return NULL;
2252
Stefano Brivio729c0c92018-07-05 15:10:02 +02002253 memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002254 buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
Pavel Shilovskya41a28b2013-09-04 13:07:41 +04002255
2256 buf->ccontext.DataOffset = cpu_to_le16(offsetof
2257 (struct create_lease, lcontext));
2258 buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context));
2259 buf->ccontext.NameOffset = cpu_to_le16(offsetof
2260 (struct create_lease, Name));
2261 buf->ccontext.NameLength = cpu_to_le16(4);
Steve French12197a72014-05-14 05:29:40 -07002262 /* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
Pavel Shilovskya41a28b2013-09-04 13:07:41 +04002263 buf->Name[0] = 'R';
2264 buf->Name[1] = 'q';
2265 buf->Name[2] = 'L';
2266 buf->Name[3] = 's';
2267 return (char *)buf;
2268}
2269
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002270static char *
2271smb3_create_lease_buf(u8 *lease_key, u8 oplock)
2272{
2273 struct create_lease_v2 *buf;
2274
2275 buf = kzalloc(sizeof(struct create_lease_v2), GFP_KERNEL);
2276 if (!buf)
2277 return NULL;
2278
Stefano Brivio729c0c92018-07-05 15:10:02 +02002279 memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002280 buf->lcontext.LeaseState = map_oplock_to_lease(oplock);
2281
2282 buf->ccontext.DataOffset = cpu_to_le16(offsetof
2283 (struct create_lease_v2, lcontext));
2284 buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
2285 buf->ccontext.NameOffset = cpu_to_le16(offsetof
2286 (struct create_lease_v2, Name));
2287 buf->ccontext.NameLength = cpu_to_le16(4);
Steve French12197a72014-05-14 05:29:40 -07002288 /* SMB2_CREATE_REQUEST_LEASE is "RqLs" */
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002289 buf->Name[0] = 'R';
2290 buf->Name[1] = 'q';
2291 buf->Name[2] = 'L';
2292 buf->Name[3] = 's';
2293 return (char *)buf;
2294}
2295
Pavel Shilovskyb5c7cde2013-09-05 20:16:45 +04002296static __u8
Ronnie Sahlberg96164ab2018-04-26 08:10:18 -06002297smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
Pavel Shilovskyb5c7cde2013-09-05 20:16:45 +04002298{
2299 struct create_lease *lc = (struct create_lease *)buf;
2300
Pavel Shilovsky42873b02013-09-05 21:30:16 +04002301 *epoch = 0; /* not used */
Pavel Shilovskyb5c7cde2013-09-05 20:16:45 +04002302 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
2303 return SMB2_OPLOCK_LEVEL_NOCHANGE;
2304 return le32_to_cpu(lc->lcontext.LeaseState);
2305}
2306
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002307static __u8
Ronnie Sahlberg96164ab2018-04-26 08:10:18 -06002308smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key)
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002309{
2310 struct create_lease_v2 *lc = (struct create_lease_v2 *)buf;
2311
Pavel Shilovsky42873b02013-09-05 21:30:16 +04002312 *epoch = le16_to_cpu(lc->lcontext.Epoch);
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002313 if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)
2314 return SMB2_OPLOCK_LEVEL_NOCHANGE;
Ronnie Sahlberg96164ab2018-04-26 08:10:18 -06002315 if (lease_key)
Stefano Brivio729c0c92018-07-05 15:10:02 +02002316 memcpy(lease_key, &lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
Pavel Shilovskyf0473902013-09-04 13:44:05 +04002317 return le32_to_cpu(lc->lcontext.LeaseState);
2318}
2319
Pavel Shilovsky7f6c5002014-06-22 11:03:22 +04002320static unsigned int
2321smb2_wp_retry_size(struct inode *inode)
2322{
2323 return min_t(unsigned int, CIFS_SB(inode->i_sb)->wsize,
2324 SMB2_MAX_BUFFER_SIZE);
2325}
2326
Pavel Shilovsky52755802014-08-18 20:49:57 +04002327static bool
2328smb2_dir_needs_close(struct cifsFileInfo *cfile)
2329{
2330 return !cfile->invalidHandle;
2331}
2332
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002333static void
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002334fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
2335 struct smb_rqst *old_rq)
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002336{
2337 struct smb2_sync_hdr *shdr =
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002338 (struct smb2_sync_hdr *)old_rq->rq_iov[0].iov_base;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002339
2340 memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
2341 tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
2342 tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
2343 tr_hdr->Flags = cpu_to_le16(0x01);
2344 get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
2345 memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002346}
2347
Ronnie Sahlberg262916b2018-02-20 12:45:21 +11002348/* We can not use the normal sg_set_buf() as we will sometimes pass a
2349 * stack object as buf.
2350 */
2351static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
2352 unsigned int buflen)
2353{
2354 sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
2355}
2356
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002357/* Assumes:
Paulo Alcantaracd2dca62018-06-13 13:54:14 -03002358 * rqst->rq_iov[0] is transform header
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002359 * rqst->rq_iov[1+] data to be encrypted/decrypted
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002360 */
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002361static struct scatterlist *
2362init_sg(struct smb_rqst *rqst, u8 *sign)
2363{
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002364 unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002365 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002366 struct scatterlist *sg;
2367 unsigned int i;
2368 unsigned int j;
2369
2370 sg = kmalloc_array(sg_len, sizeof(struct scatterlist), GFP_KERNEL);
2371 if (!sg)
2372 return NULL;
2373
2374 sg_init_table(sg, sg_len);
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002375 smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 20, assoc_data_len);
2376 for (i = 1; i < rqst->rq_nvec; i++)
2377 smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
2378 rqst->rq_iov[i].iov_len);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002379 for (j = 0; i < sg_len - 1; i++, j++) {
Steve Frenchd5f07fb2018-06-05 17:46:24 -05002380 unsigned int len, offset;
2381
2382 rqst_page_get_length(rqst, j, &len, &offset);
2383 sg_set_page(&sg[i], rqst->rq_pages[j], len, offset);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002384 }
Ronnie Sahlberg262916b2018-02-20 12:45:21 +11002385 smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002386 return sg;
2387}
2388
Pavel Shilovsky61cfac6f2017-02-28 16:05:19 -08002389static int
2390smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
2391{
2392 struct cifs_ses *ses;
2393 u8 *ses_enc_key;
2394
2395 spin_lock(&cifs_tcp_ses_lock);
2396 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
2397 if (ses->Suid != ses_id)
2398 continue;
2399 ses_enc_key = enc ? ses->smb3encryptionkey :
2400 ses->smb3decryptionkey;
2401 memcpy(key, ses_enc_key, SMB3_SIGN_KEY_SIZE);
2402 spin_unlock(&cifs_tcp_ses_lock);
2403 return 0;
2404 }
2405 spin_unlock(&cifs_tcp_ses_lock);
2406
2407 return 1;
2408}
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002409/*
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002410 * Encrypt or decrypt @rqst message. @rqst[0] has the following format:
2411 * iov[0] - transform header (associate data),
2412 * iov[1-N] - SMB2 header and pages - data to encrypt.
2413 * On success return encrypted data in iov[1-N] and pages, leave iov[0]
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002414 * untouched.
2415 */
2416static int
2417crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
2418{
2419 struct smb2_transform_hdr *tr_hdr =
Paulo Alcantaracd2dca62018-06-13 13:54:14 -03002420 (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002421 unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002422 int rc = 0;
2423 struct scatterlist *sg;
2424 u8 sign[SMB2_SIGNATURE_SIZE] = {};
Pavel Shilovsky61cfac6f2017-02-28 16:05:19 -08002425 u8 key[SMB3_SIGN_KEY_SIZE];
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002426 struct aead_request *req;
2427 char *iv;
2428 unsigned int iv_len;
Gilad Ben-Yossefa5186b82017-10-18 08:00:46 +01002429 DECLARE_CRYPTO_WAIT(wait);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002430 struct crypto_aead *tfm;
2431 unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
2432
Pavel Shilovsky61cfac6f2017-02-28 16:05:19 -08002433 rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key);
2434 if (rc) {
2435 cifs_dbg(VFS, "%s: Could not get %scryption key\n", __func__,
2436 enc ? "en" : "de");
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002437 return 0;
2438 }
2439
2440 rc = smb3_crypto_aead_allocate(server);
2441 if (rc) {
2442 cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__);
2443 return rc;
2444 }
2445
2446 tfm = enc ? server->secmech.ccmaesencrypt :
2447 server->secmech.ccmaesdecrypt;
Pavel Shilovsky61cfac6f2017-02-28 16:05:19 -08002448 rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002449 if (rc) {
2450 cifs_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
2451 return rc;
2452 }
2453
2454 rc = crypto_aead_setauthsize(tfm, SMB2_SIGNATURE_SIZE);
2455 if (rc) {
2456 cifs_dbg(VFS, "%s: Failed to set authsize %d\n", __func__, rc);
2457 return rc;
2458 }
2459
2460 req = aead_request_alloc(tfm, GFP_KERNEL);
2461 if (!req) {
2462 cifs_dbg(VFS, "%s: Failed to alloc aead request", __func__);
2463 return -ENOMEM;
2464 }
2465
2466 if (!enc) {
2467 memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
2468 crypt_len += SMB2_SIGNATURE_SIZE;
2469 }
2470
2471 sg = init_sg(rqst, sign);
2472 if (!sg) {
Christophe Jaillet517a6e42017-06-11 09:12:47 +02002473 cifs_dbg(VFS, "%s: Failed to init sg", __func__);
2474 rc = -ENOMEM;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002475 goto free_req;
2476 }
2477
2478 iv_len = crypto_aead_ivsize(tfm);
2479 iv = kzalloc(iv_len, GFP_KERNEL);
2480 if (!iv) {
2481 cifs_dbg(VFS, "%s: Failed to alloc IV", __func__);
Christophe Jaillet517a6e42017-06-11 09:12:47 +02002482 rc = -ENOMEM;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002483 goto free_sg;
2484 }
2485 iv[0] = 3;
2486 memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
2487
2488 aead_request_set_crypt(req, sg, sg, crypt_len, iv);
2489 aead_request_set_ad(req, assoc_data_len);
2490
2491 aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
Gilad Ben-Yossefa5186b82017-10-18 08:00:46 +01002492 crypto_req_done, &wait);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002493
Gilad Ben-Yossefa5186b82017-10-18 08:00:46 +01002494 rc = crypto_wait_req(enc ? crypto_aead_encrypt(req)
2495 : crypto_aead_decrypt(req), &wait);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002496
2497 if (!rc && enc)
2498 memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
2499
2500 kfree(iv);
2501free_sg:
2502 kfree(sg);
2503free_req:
2504 kfree(req);
2505 return rc;
2506}
2507
2508static int
2509smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
2510 struct smb_rqst *old_rq)
2511{
2512 struct kvec *iov;
2513 struct page **pages;
2514 struct smb2_transform_hdr *tr_hdr;
2515 unsigned int npages = old_rq->rq_npages;
Paulo Alcantara35e2cc12018-06-15 10:22:44 -03002516 unsigned int orig_len;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002517 int i;
2518 int rc = -ENOMEM;
2519
2520 pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
2521 if (!pages)
2522 return rc;
2523
2524 new_rq->rq_pages = pages;
Steve Frenchd5f07fb2018-06-05 17:46:24 -05002525 new_rq->rq_offset = old_rq->rq_offset;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002526 new_rq->rq_npages = old_rq->rq_npages;
2527 new_rq->rq_pagesz = old_rq->rq_pagesz;
2528 new_rq->rq_tailsz = old_rq->rq_tailsz;
2529
2530 for (i = 0; i < npages; i++) {
2531 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2532 if (!pages[i])
2533 goto err_free_pages;
2534 }
2535
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002536 iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
2537 GFP_KERNEL);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002538 if (!iov)
2539 goto err_free_pages;
2540
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002541 /* copy all iovs from the old */
2542 memcpy(&iov[1], &old_rq->rq_iov[0],
2543 sizeof(struct kvec) * old_rq->rq_nvec);
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002544
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002545 new_rq->rq_iov = iov;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002546 new_rq->rq_nvec = old_rq->rq_nvec + 1;
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002547
2548 tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
2549 if (!tr_hdr)
2550 goto err_free_iov;
2551
Ronnie Sahlberg81f39f92018-06-28 10:47:14 +10002552 orig_len = smb_rqst_len(server, old_rq);
Paulo Alcantara35e2cc12018-06-15 10:22:44 -03002553
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002554 /* fill the 2nd iov with a transform header */
2555 fill_transform_hdr(tr_hdr, orig_len, old_rq);
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002556 new_rq->rq_iov[0].iov_base = tr_hdr;
2557 new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002558
2559 /* copy pages form the old */
2560 for (i = 0; i < npages; i++) {
Steve Frenchd5f07fb2018-06-05 17:46:24 -05002561 char *dst, *src;
2562 unsigned int offset, len;
2563
2564 rqst_page_get_length(new_rq, i, &len, &offset);
2565
2566 dst = (char *) kmap(new_rq->rq_pages[i]) + offset;
2567 src = (char *) kmap(old_rq->rq_pages[i]) + offset;
2568
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002569 memcpy(dst, src, len);
2570 kunmap(new_rq->rq_pages[i]);
2571 kunmap(old_rq->rq_pages[i]);
2572 }
2573
2574 rc = crypt_message(server, new_rq, 1);
2575 cifs_dbg(FYI, "encrypt message returned %d", rc);
2576 if (rc)
2577 goto err_free_tr_hdr;
2578
2579 return rc;
2580
2581err_free_tr_hdr:
2582 kfree(tr_hdr);
2583err_free_iov:
2584 kfree(iov);
2585err_free_pages:
2586 for (i = i - 1; i >= 0; i--)
2587 put_page(pages[i]);
2588 kfree(pages);
2589 return rc;
2590}
2591
2592static void
2593smb3_free_transform_rq(struct smb_rqst *rqst)
2594{
2595 int i = rqst->rq_npages - 1;
2596
2597 for (; i >= 0; i--)
2598 put_page(rqst->rq_pages[i]);
2599 kfree(rqst->rq_pages);
2600 /* free transform header */
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002601 kfree(rqst->rq_iov[0].iov_base);
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002602 kfree(rqst->rq_iov);
2603}
2604
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002605static int
2606smb3_is_transform_hdr(void *buf)
2607{
2608 struct smb2_transform_hdr *trhdr = buf;
2609
2610 return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
2611}
2612
2613static int
2614decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
2615 unsigned int buf_data_size, struct page **pages,
2616 unsigned int npages, unsigned int page_data_size)
2617{
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002618 struct kvec iov[2];
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002619 struct smb_rqst rqst = {NULL};
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002620 int rc;
2621
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002622 iov[0].iov_base = buf;
2623 iov[0].iov_len = sizeof(struct smb2_transform_hdr);
2624 iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
2625 iov[1].iov_len = buf_data_size;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002626
2627 rqst.rq_iov = iov;
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002628 rqst.rq_nvec = 2;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002629 rqst.rq_pages = pages;
2630 rqst.rq_npages = npages;
2631 rqst.rq_pagesz = PAGE_SIZE;
2632 rqst.rq_tailsz = (page_data_size % PAGE_SIZE) ? : PAGE_SIZE;
2633
2634 rc = crypt_message(server, &rqst, 0);
2635 cifs_dbg(FYI, "decrypt message returned %d\n", rc);
2636
2637 if (rc)
2638 return rc;
2639
Ronnie Sahlbergc713c872018-06-12 08:00:58 +10002640 memmove(buf, iov[1].iov_base, buf_data_size);
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10002641
2642 server->total_read = buf_data_size + page_data_size;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002643
2644 return rc;
2645}
2646
2647static int
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002648read_data_into_pages(struct TCP_Server_Info *server, struct page **pages,
2649 unsigned int npages, unsigned int len)
2650{
2651 int i;
2652 int length;
2653
2654 for (i = 0; i < npages; i++) {
2655 struct page *page = pages[i];
2656 size_t n;
2657
2658 n = len;
2659 if (len >= PAGE_SIZE) {
2660 /* enough data to fill the page */
2661 n = PAGE_SIZE;
2662 len -= n;
2663 } else {
2664 zero_user(page, len, PAGE_SIZE - len);
2665 len = 0;
2666 }
Long Li1dbe3462018-05-30 12:47:55 -07002667 length = cifs_read_page_from_socket(server, page, 0, n);
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002668 if (length < 0)
2669 return length;
2670 server->total_read += length;
2671 }
2672
2673 return 0;
2674}
2675
2676static int
2677init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size,
2678 unsigned int cur_off, struct bio_vec **page_vec)
2679{
2680 struct bio_vec *bvec;
2681 int i;
2682
2683 bvec = kcalloc(npages, sizeof(struct bio_vec), GFP_KERNEL);
2684 if (!bvec)
2685 return -ENOMEM;
2686
2687 for (i = 0; i < npages; i++) {
2688 bvec[i].bv_page = pages[i];
2689 bvec[i].bv_offset = (i == 0) ? cur_off : 0;
2690 bvec[i].bv_len = min_t(unsigned int, PAGE_SIZE, data_size);
2691 data_size -= bvec[i].bv_len;
2692 }
2693
2694 if (data_size != 0) {
2695 cifs_dbg(VFS, "%s: something went wrong\n", __func__);
2696 kfree(bvec);
2697 return -EIO;
2698 }
2699
2700 *page_vec = bvec;
2701 return 0;
2702}
2703
2704static int
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002705handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
2706 char *buf, unsigned int buf_len, struct page **pages,
2707 unsigned int npages, unsigned int page_data_size)
2708{
2709 unsigned int data_offset;
2710 unsigned int data_len;
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002711 unsigned int cur_off;
2712 unsigned int cur_page_idx;
2713 unsigned int pad_len;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002714 struct cifs_readdata *rdata = mid->callback_data;
Ronnie Sahlberg49f466b2018-06-01 10:53:06 +10002715 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002716 struct bio_vec *bvec = NULL;
2717 struct iov_iter iter;
2718 struct kvec iov;
2719 int length;
Long Li74dcf412017-11-22 17:38:46 -07002720 bool use_rdma_mr = false;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002721
2722 if (shdr->Command != SMB2_READ) {
2723 cifs_dbg(VFS, "only big read responses are supported\n");
2724 return -ENOTSUPP;
2725 }
2726
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07002727 if (server->ops->is_session_expired &&
2728 server->ops->is_session_expired(buf)) {
2729 cifs_reconnect(server);
2730 wake_up(&server->response_q);
2731 return -1;
2732 }
2733
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002734 if (server->ops->is_status_pending &&
2735 server->ops->is_status_pending(buf, server, 0))
2736 return -1;
2737
2738 rdata->result = server->ops->map_error(buf, false);
2739 if (rdata->result != 0) {
2740 cifs_dbg(FYI, "%s: server returned error %d\n",
2741 __func__, rdata->result);
2742 dequeue_mid(mid, rdata->result);
2743 return 0;
2744 }
2745
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002746 data_offset = server->ops->read_data_offset(buf);
Long Li74dcf412017-11-22 17:38:46 -07002747#ifdef CONFIG_CIFS_SMB_DIRECT
2748 use_rdma_mr = rdata->mr;
2749#endif
2750 data_len = server->ops->read_data_length(buf, use_rdma_mr);
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002751
2752 if (data_offset < server->vals->read_rsp_size) {
2753 /*
2754 * win2k8 sometimes sends an offset of 0 when the read
2755 * is beyond the EOF. Treat it as if the data starts just after
2756 * the header.
2757 */
2758 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
2759 __func__, data_offset);
2760 data_offset = server->vals->read_rsp_size;
2761 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
2762 /* data_offset is beyond the end of smallbuf */
2763 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
2764 __func__, data_offset);
2765 rdata->result = -EIO;
2766 dequeue_mid(mid, rdata->result);
2767 return 0;
2768 }
2769
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002770 pad_len = data_offset - server->vals->read_rsp_size;
2771
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002772 if (buf_len <= data_offset) {
2773 /* read response payload is in pages */
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002774 cur_page_idx = pad_len / PAGE_SIZE;
2775 cur_off = pad_len % PAGE_SIZE;
2776
2777 if (cur_page_idx != 0) {
2778 /* data offset is beyond the 1st page of response */
2779 cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
2780 __func__, data_offset);
2781 rdata->result = -EIO;
2782 dequeue_mid(mid, rdata->result);
2783 return 0;
2784 }
2785
2786 if (data_len > page_data_size - pad_len) {
2787 /* data_len is corrupt -- discard frame */
2788 rdata->result = -EIO;
2789 dequeue_mid(mid, rdata->result);
2790 return 0;
2791 }
2792
2793 rdata->result = init_read_bvec(pages, npages, page_data_size,
2794 cur_off, &bvec);
2795 if (rdata->result != 0) {
2796 dequeue_mid(mid, rdata->result);
2797 return 0;
2798 }
2799
2800 iov_iter_bvec(&iter, WRITE | ITER_BVEC, bvec, npages, data_len);
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002801 } else if (buf_len >= data_offset + data_len) {
2802 /* read response payload is in buf */
2803 WARN_ONCE(npages > 0, "read data can be either in buf or in pages");
2804 iov.iov_base = buf + data_offset;
2805 iov.iov_len = data_len;
2806 iov_iter_kvec(&iter, WRITE | ITER_KVEC, &iov, 1, data_len);
2807 } else {
2808 /* read response payload cannot be in both buf and pages */
2809 WARN_ONCE(1, "buf can not contain only a part of read data");
2810 rdata->result = -EIO;
2811 dequeue_mid(mid, rdata->result);
2812 return 0;
2813 }
2814
2815 /* set up first iov for signature check */
2816 rdata->iov[0].iov_base = buf;
2817 rdata->iov[0].iov_len = 4;
2818 rdata->iov[1].iov_base = buf + 4;
2819 rdata->iov[1].iov_len = server->vals->read_rsp_size - 4;
2820 cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
2821 rdata->iov[0].iov_base, server->vals->read_rsp_size);
2822
2823 length = rdata->copy_into_pages(server, rdata, &iter);
2824
2825 kfree(bvec);
2826
2827 if (length < 0)
2828 return length;
2829
2830 dequeue_mid(mid, false);
2831 return length;
2832}
2833
2834static int
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002835receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
2836{
2837 char *buf = server->smallbuf;
2838 struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
2839 unsigned int npages;
2840 struct page **pages;
2841 unsigned int len;
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002842 unsigned int buflen = server->pdu_size;
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002843 int rc;
2844 int i = 0;
2845
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002846 len = min_t(unsigned int, buflen, server->vals->read_rsp_size +
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002847 sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
2848
2849 rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len);
2850 if (rc < 0)
2851 return rc;
2852 server->total_read += rc;
2853
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002854 len = le32_to_cpu(tr_hdr->OriginalMessageSize) -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11002855 server->vals->read_rsp_size;
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002856 npages = DIV_ROUND_UP(len, PAGE_SIZE);
2857
2858 pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
2859 if (!pages) {
2860 rc = -ENOMEM;
2861 goto discard_data;
2862 }
2863
2864 for (; i < npages; i++) {
2865 pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
2866 if (!pages[i]) {
2867 rc = -ENOMEM;
2868 goto discard_data;
2869 }
2870 }
2871
2872 /* read read data into pages */
2873 rc = read_data_into_pages(server, pages, npages, len);
2874 if (rc)
2875 goto free_pages;
2876
Pavel Shilovsky350be252017-04-10 10:31:33 -07002877 rc = cifs_discard_remaining_data(server);
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002878 if (rc)
2879 goto free_pages;
2880
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002881 rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size,
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002882 pages, npages, len);
2883 if (rc)
2884 goto free_pages;
2885
2886 *mid = smb2_find_mid(server, buf);
2887 if (*mid == NULL)
2888 cifs_dbg(FYI, "mid not found\n");
2889 else {
2890 cifs_dbg(FYI, "mid found\n");
2891 (*mid)->decrypted = true;
2892 rc = handle_read_data(server, *mid, buf,
2893 server->vals->read_rsp_size,
2894 pages, npages, len);
2895 }
2896
2897free_pages:
2898 for (i = i - 1; i >= 0; i--)
2899 put_page(pages[i]);
2900 kfree(pages);
2901 return rc;
2902discard_data:
Pavel Shilovsky350be252017-04-10 10:31:33 -07002903 cifs_discard_remaining_data(server);
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002904 goto free_pages;
2905}
2906
2907static int
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002908receive_encrypted_standard(struct TCP_Server_Info *server,
2909 struct mid_q_entry **mid)
2910{
2911 int length;
2912 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10002913 unsigned int pdu_length = server->pdu_size;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002914 unsigned int buf_size;
2915 struct mid_q_entry *mid_entry;
2916
2917 /* switch to large buffer if too big for a small one */
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002918 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) {
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002919 server->large_buf = true;
2920 memcpy(server->bigbuf, buf, server->total_read);
2921 buf = server->bigbuf;
2922 }
2923
2924 /* now read the rest */
2925 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002926 pdu_length - HEADER_SIZE(server) + 1);
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002927 if (length < 0)
2928 return length;
2929 server->total_read += length;
2930
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002931 buf_size = pdu_length - sizeof(struct smb2_transform_hdr);
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002932 length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0);
2933 if (length)
2934 return length;
2935
2936 mid_entry = smb2_find_mid(server, buf);
2937 if (mid_entry == NULL)
2938 cifs_dbg(FYI, "mid not found\n");
2939 else {
2940 cifs_dbg(FYI, "mid found\n");
2941 mid_entry->decrypted = true;
2942 }
2943
2944 *mid = mid_entry;
2945
2946 if (mid_entry && mid_entry->handle)
2947 return mid_entry->handle(server, mid_entry);
2948
2949 return cifs_handle_standard(server, mid_entry);
2950}
2951
2952static int
2953smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
2954{
2955 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10002956 unsigned int pdu_length = server->pdu_size;
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002957 struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
2958 unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
2959
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002960 if (pdu_length < sizeof(struct smb2_transform_hdr) +
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002961 sizeof(struct smb2_sync_hdr)) {
2962 cifs_dbg(VFS, "Transform message is too small (%u)\n",
2963 pdu_length);
2964 cifs_reconnect(server);
2965 wake_up(&server->response_q);
2966 return -ECONNABORTED;
2967 }
2968
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002969 if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) {
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002970 cifs_dbg(VFS, "Transform message is broken\n");
2971 cifs_reconnect(server);
2972 wake_up(&server->response_q);
2973 return -ECONNABORTED;
2974 }
2975
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002976 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
Pavel Shilovskyc42a6ab2016-11-17 16:20:23 -08002977 return receive_encrypted_read(server, mid);
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002978
2979 return receive_encrypted_standard(server, mid);
2980}
2981
2982int
2983smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
2984{
2985 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
2986
Ronnie Sahlberg1fc6ad22018-06-01 10:53:07 +10002987 return handle_read_data(server, mid, buf, server->pdu_size,
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08002988 NULL, 0, 0);
2989}
2990
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10002991static int
2992smb2_next_header(char *buf)
2993{
2994 struct smb2_sync_hdr *hdr = (struct smb2_sync_hdr *)buf;
2995 struct smb2_transform_hdr *t_hdr = (struct smb2_transform_hdr *)buf;
2996
2997 if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM)
2998 return sizeof(struct smb2_transform_hdr) +
2999 le32_to_cpu(t_hdr->OriginalMessageSize);
3000
3001 return le32_to_cpu(hdr->NextCommand);
3002}
3003
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003004struct smb_version_operations smb20_operations = {
3005 .compare_fids = smb2_compare_fids,
3006 .setup_request = smb2_setup_request,
3007 .setup_async_request = smb2_setup_async_request,
3008 .check_receive = smb2_check_receive,
3009 .add_credits = smb2_add_credits,
3010 .set_credits = smb2_set_credits,
3011 .get_credits_field = smb2_get_credits_field,
3012 .get_credits = smb2_get_credits,
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +04003013 .wait_mtu_credits = cifs_wait_mtu_credits,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003014 .get_next_mid = smb2_get_next_mid,
3015 .read_data_offset = smb2_read_data_offset,
3016 .read_data_length = smb2_read_data_length,
3017 .map_error = map_smb2_to_linux_error,
3018 .find_mid = smb2_find_mid,
3019 .check_message = smb2_check_message,
3020 .dump_detail = smb2_dump_detail,
3021 .clear_stats = smb2_clear_stats,
3022 .print_stats = smb2_print_stats,
3023 .is_oplock_break = smb2_is_valid_oplock_break,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08003024 .handle_cancelled_mid = smb2_handle_cancelled_mid,
Sachin Prabhuc11f1df2014-03-11 16:11:47 +00003025 .downgrade_oplock = smb2_downgrade_oplock,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003026 .need_neg = smb2_need_neg,
3027 .negotiate = smb2_negotiate,
3028 .negotiate_wsize = smb2_negotiate_wsize,
3029 .negotiate_rsize = smb2_negotiate_rsize,
3030 .sess_setup = SMB2_sess_setup,
3031 .logoff = SMB2_logoff,
3032 .tree_connect = SMB2_tcon,
3033 .tree_disconnect = SMB2_tdis,
Steve French34f62642013-10-09 02:07:00 -05003034 .qfs_tcon = smb2_qfs_tcon,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003035 .is_path_accessible = smb2_is_path_accessible,
3036 .can_echo = smb2_can_echo,
3037 .echo = SMB2_echo,
3038 .query_path_info = smb2_query_path_info,
3039 .get_srv_inum = smb2_get_srv_inum,
3040 .query_file_info = smb2_query_file_info,
3041 .set_path_size = smb2_set_path_size,
3042 .set_file_size = smb2_set_file_size,
3043 .set_file_info = smb2_set_file_info,
Steve French64a5cfa2013-10-14 15:31:32 -05003044 .set_compression = smb2_set_compression,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003045 .mkdir = smb2_mkdir,
3046 .mkdir_setinfo = smb2_mkdir_setinfo,
3047 .rmdir = smb2_rmdir,
3048 .unlink = smb2_unlink,
3049 .rename = smb2_rename_path,
3050 .create_hardlink = smb2_create_hardlink,
3051 .query_symlink = smb2_query_symlink,
Sachin Prabhu5b23c972016-07-11 16:53:20 +01003052 .query_mf_symlink = smb3_query_mf_symlink,
3053 .create_mf_symlink = smb3_create_mf_symlink,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003054 .open = smb2_open_file,
3055 .set_fid = smb2_set_fid,
3056 .close = smb2_close_file,
3057 .flush = smb2_flush_file,
3058 .async_readv = smb2_async_readv,
3059 .async_writev = smb2_async_writev,
3060 .sync_read = smb2_sync_read,
3061 .sync_write = smb2_sync_write,
3062 .query_dir_first = smb2_query_dir_first,
3063 .query_dir_next = smb2_query_dir_next,
3064 .close_dir = smb2_close_dir,
3065 .calc_smb_size = smb2_calc_size,
3066 .is_status_pending = smb2_is_status_pending,
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07003067 .is_session_expired = smb2_is_session_expired,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003068 .oplock_response = smb2_oplock_response,
3069 .queryfs = smb2_queryfs,
3070 .mand_lock = smb2_mand_lock,
3071 .mand_unlock_range = smb2_unlock_range,
3072 .push_mand_locks = smb2_push_mandatory_locks,
3073 .get_lease_key = smb2_get_lease_key,
3074 .set_lease_key = smb2_set_lease_key,
3075 .new_lease_key = smb2_new_lease_key,
3076 .calc_signature = smb2_calc_signature,
3077 .is_read_op = smb2_is_read_op,
3078 .set_oplock_level = smb2_set_oplock_level,
Pavel Shilovskya41a28b2013-09-04 13:07:41 +04003079 .create_lease_buf = smb2_create_lease_buf,
Pavel Shilovskyb5c7cde2013-09-05 20:16:45 +04003080 .parse_lease_buf = smb2_parse_lease_buf,
Sachin Prabhu312bbc52017-04-04 02:12:04 -05003081 .copychunk_range = smb2_copychunk_range,
Pavel Shilovsky7f6c5002014-06-22 11:03:22 +04003082 .wp_retry_size = smb2_wp_retry_size,
Pavel Shilovsky52755802014-08-18 20:49:57 +04003083 .dir_needs_close = smb2_dir_needs_close,
Aurelien Aptel9d496402017-02-13 16:16:49 +01003084 .get_dfs_refer = smb2_get_dfs_refer,
Sachin Prabhuef65aae2017-01-18 15:35:57 +05303085 .select_sectype = smb2_select_sectype,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003086#ifdef CONFIG_CIFS_XATTR
3087 .query_all_EAs = smb2_query_eas,
Ronnie Sahlberg55175542017-08-24 11:24:56 +10003088 .set_EA = smb2_set_ea,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003089#endif /* CIFS_XATTR */
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05003090#ifdef CONFIG_CIFS_ACL
3091 .get_acl = get_smb2_acl,
3092 .get_acl_by_fid = get_smb2_acl_by_fid,
Shirish Pargaonkar366ed842017-06-28 22:37:32 -05003093 .set_acl = set_smb2_acl,
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05003094#endif /* CIFS_ACL */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10003095 .next_header = smb2_next_header,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003096};
3097
Steve French1080ef72011-02-24 18:07:19 +00003098struct smb_version_operations smb21_operations = {
Pavel Shilovsky027e8ee2012-09-19 06:22:43 -07003099 .compare_fids = smb2_compare_fids,
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +04003100 .setup_request = smb2_setup_request,
Pavel Shilovskyc95b8ee2012-07-11 14:45:28 +04003101 .setup_async_request = smb2_setup_async_request,
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +04003102 .check_receive = smb2_check_receive,
Pavel Shilovsky28ea5292012-05-23 16:18:00 +04003103 .add_credits = smb2_add_credits,
3104 .set_credits = smb2_set_credits,
3105 .get_credits_field = smb2_get_credits_field,
3106 .get_credits = smb2_get_credits,
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +04003107 .wait_mtu_credits = smb2_wait_mtu_credits,
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +04003108 .get_next_mid = smb2_get_next_mid,
Pavel Shilovsky09a47072012-09-18 16:20:29 -07003109 .read_data_offset = smb2_read_data_offset,
3110 .read_data_length = smb2_read_data_length,
3111 .map_error = map_smb2_to_linux_error,
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +04003112 .find_mid = smb2_find_mid,
3113 .check_message = smb2_check_message,
3114 .dump_detail = smb2_dump_detail,
Pavel Shilovskyd60622e2012-05-28 15:19:39 +04003115 .clear_stats = smb2_clear_stats,
3116 .print_stats = smb2_print_stats,
Pavel Shilovsky983c88a2012-09-18 16:20:33 -07003117 .is_oplock_break = smb2_is_valid_oplock_break,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08003118 .handle_cancelled_mid = smb2_handle_cancelled_mid,
Sachin Prabhuc11f1df2014-03-11 16:11:47 +00003119 .downgrade_oplock = smb2_downgrade_oplock,
Pavel Shilovskyec2e4522011-12-27 16:12:43 +04003120 .need_neg = smb2_need_neg,
3121 .negotiate = smb2_negotiate,
Pavel Shilovsky3a3bab52012-09-18 16:20:28 -07003122 .negotiate_wsize = smb2_negotiate_wsize,
3123 .negotiate_rsize = smb2_negotiate_rsize,
Pavel Shilovsky5478f9b2011-12-27 16:22:00 +04003124 .sess_setup = SMB2_sess_setup,
3125 .logoff = SMB2_logoff,
Pavel Shilovskyfaaf9462011-12-27 16:04:00 +04003126 .tree_connect = SMB2_tcon,
3127 .tree_disconnect = SMB2_tdis,
Steve French34f62642013-10-09 02:07:00 -05003128 .qfs_tcon = smb2_qfs_tcon,
Pavel Shilovsky2503a0d2011-12-26 22:58:46 +04003129 .is_path_accessible = smb2_is_path_accessible,
Pavel Shilovsky9094fad2012-07-12 18:30:44 +04003130 .can_echo = smb2_can_echo,
3131 .echo = SMB2_echo,
Pavel Shilovskybe4cb9e2011-12-29 17:06:33 +04003132 .query_path_info = smb2_query_path_info,
3133 .get_srv_inum = smb2_get_srv_inum,
Pavel Shilovskyb7546bc2012-09-18 16:20:27 -07003134 .query_file_info = smb2_query_file_info,
Pavel Shilovskyc839ff22012-09-18 16:20:32 -07003135 .set_path_size = smb2_set_path_size,
3136 .set_file_size = smb2_set_file_size,
Pavel Shilovsky1feeaac2012-09-18 16:20:32 -07003137 .set_file_info = smb2_set_file_info,
Steve French64a5cfa2013-10-14 15:31:32 -05003138 .set_compression = smb2_set_compression,
Pavel Shilovskya0e73182011-07-19 12:56:37 +04003139 .mkdir = smb2_mkdir,
3140 .mkdir_setinfo = smb2_mkdir_setinfo,
Pavel Shilovsky1a500f02012-07-10 16:14:38 +04003141 .rmdir = smb2_rmdir,
Pavel Shilovskycbe6f432012-09-18 16:20:25 -07003142 .unlink = smb2_unlink,
Pavel Shilovsky35143eb2012-09-18 16:20:31 -07003143 .rename = smb2_rename_path,
Pavel Shilovsky568798c2012-09-18 16:20:31 -07003144 .create_hardlink = smb2_create_hardlink,
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04003145 .query_symlink = smb2_query_symlink,
Steve Frenchc22870e2014-09-16 07:18:19 -05003146 .query_mf_symlink = smb3_query_mf_symlink,
Steve French5ab97572014-09-15 04:49:28 -05003147 .create_mf_symlink = smb3_create_mf_symlink,
Pavel Shilovskyf0df7372012-09-18 16:20:26 -07003148 .open = smb2_open_file,
3149 .set_fid = smb2_set_fid,
3150 .close = smb2_close_file,
Pavel Shilovsky7a5cfb12012-09-18 16:20:28 -07003151 .flush = smb2_flush_file,
Pavel Shilovsky09a47072012-09-18 16:20:29 -07003152 .async_readv = smb2_async_readv,
Pavel Shilovsky33319142012-09-18 16:20:29 -07003153 .async_writev = smb2_async_writev,
Pavel Shilovskyd8e05032012-09-18 16:20:30 -07003154 .sync_read = smb2_sync_read,
Pavel Shilovsky009d3442012-09-18 16:20:30 -07003155 .sync_write = smb2_sync_write,
Pavel Shilovskyd324f08d2012-09-18 16:20:33 -07003156 .query_dir_first = smb2_query_dir_first,
3157 .query_dir_next = smb2_query_dir_next,
3158 .close_dir = smb2_close_dir,
3159 .calc_smb_size = smb2_calc_size,
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07003160 .is_status_pending = smb2_is_status_pending,
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07003161 .is_session_expired = smb2_is_session_expired,
Pavel Shilovsky983c88a2012-09-18 16:20:33 -07003162 .oplock_response = smb2_oplock_response,
Pavel Shilovsky6fc05c22012-09-18 16:20:34 -07003163 .queryfs = smb2_queryfs,
Pavel Shilovskyf7ba7fe2012-09-19 06:22:43 -07003164 .mand_lock = smb2_mand_lock,
3165 .mand_unlock_range = smb2_unlock_range,
Pavel Shilovskyb1407992012-09-19 06:22:44 -07003166 .push_mand_locks = smb2_push_mandatory_locks,
Pavel Shilovskyb8c32db2012-09-19 06:22:44 -07003167 .get_lease_key = smb2_get_lease_key,
3168 .set_lease_key = smb2_set_lease_key,
3169 .new_lease_key = smb2_new_lease_key,
Steve French38107d42012-12-08 22:08:06 -06003170 .calc_signature = smb2_calc_signature,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003171 .is_read_op = smb21_is_read_op,
3172 .set_oplock_level = smb21_set_oplock_level,
Pavel Shilovskya41a28b2013-09-04 13:07:41 +04003173 .create_lease_buf = smb2_create_lease_buf,
Pavel Shilovskyb5c7cde2013-09-05 20:16:45 +04003174 .parse_lease_buf = smb2_parse_lease_buf,
Sachin Prabhu312bbc52017-04-04 02:12:04 -05003175 .copychunk_range = smb2_copychunk_range,
Pavel Shilovsky7f6c5002014-06-22 11:03:22 +04003176 .wp_retry_size = smb2_wp_retry_size,
Pavel Shilovsky52755802014-08-18 20:49:57 +04003177 .dir_needs_close = smb2_dir_needs_close,
Steve French834170c2016-09-30 21:14:26 -05003178 .enum_snapshots = smb3_enum_snapshots,
Aurelien Aptel9d496402017-02-13 16:16:49 +01003179 .get_dfs_refer = smb2_get_dfs_refer,
Sachin Prabhuef65aae2017-01-18 15:35:57 +05303180 .select_sectype = smb2_select_sectype,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003181#ifdef CONFIG_CIFS_XATTR
3182 .query_all_EAs = smb2_query_eas,
Ronnie Sahlberg55175542017-08-24 11:24:56 +10003183 .set_EA = smb2_set_ea,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003184#endif /* CIFS_XATTR */
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05003185#ifdef CONFIG_CIFS_ACL
3186 .get_acl = get_smb2_acl,
3187 .get_acl_by_fid = get_smb2_acl_by_fid,
Shirish Pargaonkar366ed842017-06-28 22:37:32 -05003188 .set_acl = set_smb2_acl,
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05003189#endif /* CIFS_ACL */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10003190 .next_header = smb2_next_header,
Steve French38107d42012-12-08 22:08:06 -06003191};
3192
Steve French38107d42012-12-08 22:08:06 -06003193struct smb_version_operations smb30_operations = {
3194 .compare_fids = smb2_compare_fids,
3195 .setup_request = smb2_setup_request,
3196 .setup_async_request = smb2_setup_async_request,
3197 .check_receive = smb2_check_receive,
3198 .add_credits = smb2_add_credits,
3199 .set_credits = smb2_set_credits,
3200 .get_credits_field = smb2_get_credits_field,
3201 .get_credits = smb2_get_credits,
Pavel Shilovskycb7e9ea2014-06-05 19:03:27 +04003202 .wait_mtu_credits = smb2_wait_mtu_credits,
Steve French38107d42012-12-08 22:08:06 -06003203 .get_next_mid = smb2_get_next_mid,
3204 .read_data_offset = smb2_read_data_offset,
3205 .read_data_length = smb2_read_data_length,
3206 .map_error = map_smb2_to_linux_error,
3207 .find_mid = smb2_find_mid,
3208 .check_message = smb2_check_message,
3209 .dump_detail = smb2_dump_detail,
3210 .clear_stats = smb2_clear_stats,
3211 .print_stats = smb2_print_stats,
Steve French769ee6a2013-06-19 14:15:30 -05003212 .dump_share_caps = smb2_dump_share_caps,
Steve French38107d42012-12-08 22:08:06 -06003213 .is_oplock_break = smb2_is_valid_oplock_break,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08003214 .handle_cancelled_mid = smb2_handle_cancelled_mid,
Sachin Prabhuc11f1df2014-03-11 16:11:47 +00003215 .downgrade_oplock = smb2_downgrade_oplock,
Steve French38107d42012-12-08 22:08:06 -06003216 .need_neg = smb2_need_neg,
3217 .negotiate = smb2_negotiate,
3218 .negotiate_wsize = smb2_negotiate_wsize,
3219 .negotiate_rsize = smb2_negotiate_rsize,
3220 .sess_setup = SMB2_sess_setup,
3221 .logoff = SMB2_logoff,
3222 .tree_connect = SMB2_tcon,
3223 .tree_disconnect = SMB2_tdis,
Steven Frenchaf6a12e2013-10-09 20:55:53 -05003224 .qfs_tcon = smb3_qfs_tcon,
Steve French38107d42012-12-08 22:08:06 -06003225 .is_path_accessible = smb2_is_path_accessible,
3226 .can_echo = smb2_can_echo,
3227 .echo = SMB2_echo,
3228 .query_path_info = smb2_query_path_info,
3229 .get_srv_inum = smb2_get_srv_inum,
3230 .query_file_info = smb2_query_file_info,
3231 .set_path_size = smb2_set_path_size,
3232 .set_file_size = smb2_set_file_size,
3233 .set_file_info = smb2_set_file_info,
Steve French64a5cfa2013-10-14 15:31:32 -05003234 .set_compression = smb2_set_compression,
Steve French38107d42012-12-08 22:08:06 -06003235 .mkdir = smb2_mkdir,
3236 .mkdir_setinfo = smb2_mkdir_setinfo,
3237 .rmdir = smb2_rmdir,
3238 .unlink = smb2_unlink,
3239 .rename = smb2_rename_path,
3240 .create_hardlink = smb2_create_hardlink,
Pavel Shilovskyb42bf882013-08-14 19:25:21 +04003241 .query_symlink = smb2_query_symlink,
Steve Frenchc22870e2014-09-16 07:18:19 -05003242 .query_mf_symlink = smb3_query_mf_symlink,
Steve French5ab97572014-09-15 04:49:28 -05003243 .create_mf_symlink = smb3_create_mf_symlink,
Steve French38107d42012-12-08 22:08:06 -06003244 .open = smb2_open_file,
3245 .set_fid = smb2_set_fid,
3246 .close = smb2_close_file,
3247 .flush = smb2_flush_file,
3248 .async_readv = smb2_async_readv,
3249 .async_writev = smb2_async_writev,
3250 .sync_read = smb2_sync_read,
3251 .sync_write = smb2_sync_write,
3252 .query_dir_first = smb2_query_dir_first,
3253 .query_dir_next = smb2_query_dir_next,
3254 .close_dir = smb2_close_dir,
3255 .calc_smb_size = smb2_calc_size,
3256 .is_status_pending = smb2_is_status_pending,
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07003257 .is_session_expired = smb2_is_session_expired,
Steve French38107d42012-12-08 22:08:06 -06003258 .oplock_response = smb2_oplock_response,
3259 .queryfs = smb2_queryfs,
3260 .mand_lock = smb2_mand_lock,
3261 .mand_unlock_range = smb2_unlock_range,
3262 .push_mand_locks = smb2_push_mandatory_locks,
3263 .get_lease_key = smb2_get_lease_key,
3264 .set_lease_key = smb2_set_lease_key,
3265 .new_lease_key = smb2_new_lease_key,
Steve French373512e2015-12-18 13:05:30 -06003266 .generate_signingkey = generate_smb30signingkey,
Steve French38107d42012-12-08 22:08:06 -06003267 .calc_signature = smb3_calc_signature,
Steve Frenchb3152e22015-06-24 03:17:02 -05003268 .set_integrity = smb3_set_integrity,
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04003269 .is_read_op = smb21_is_read_op,
Pavel Shilovsky42873b02013-09-05 21:30:16 +04003270 .set_oplock_level = smb3_set_oplock_level,
Pavel Shilovskyf0473902013-09-04 13:44:05 +04003271 .create_lease_buf = smb3_create_lease_buf,
3272 .parse_lease_buf = smb3_parse_lease_buf,
Sachin Prabhu312bbc52017-04-04 02:12:04 -05003273 .copychunk_range = smb2_copychunk_range,
Steve Frenchca9e7a12015-10-01 21:40:10 -05003274 .duplicate_extents = smb2_duplicate_extents,
Steve Frenchff1c0382013-11-19 23:44:46 -06003275 .validate_negotiate = smb3_validate_negotiate,
Pavel Shilovsky7f6c5002014-06-22 11:03:22 +04003276 .wp_retry_size = smb2_wp_retry_size,
Pavel Shilovsky52755802014-08-18 20:49:57 +04003277 .dir_needs_close = smb2_dir_needs_close,
Steve French31742c52014-08-17 08:38:47 -05003278 .fallocate = smb3_fallocate,
Steve French834170c2016-09-30 21:14:26 -05003279 .enum_snapshots = smb3_enum_snapshots,
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07003280 .init_transform_rq = smb3_init_transform_rq,
3281 .free_transform_rq = smb3_free_transform_rq,
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08003282 .is_transform_hdr = smb3_is_transform_hdr,
3283 .receive_transform = smb3_receive_transform,
Aurelien Aptel9d496402017-02-13 16:16:49 +01003284 .get_dfs_refer = smb2_get_dfs_refer,
Sachin Prabhuef65aae2017-01-18 15:35:57 +05303285 .select_sectype = smb2_select_sectype,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003286#ifdef CONFIG_CIFS_XATTR
3287 .query_all_EAs = smb2_query_eas,
Ronnie Sahlberg55175542017-08-24 11:24:56 +10003288 .set_EA = smb2_set_ea,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003289#endif /* CIFS_XATTR */
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05003290#ifdef CONFIG_CIFS_ACL
3291 .get_acl = get_smb2_acl,
3292 .get_acl_by_fid = get_smb2_acl_by_fid,
Shirish Pargaonkar366ed842017-06-28 22:37:32 -05003293 .set_acl = set_smb2_acl,
Shirish Pargaonkar2f1afe22017-06-22 22:52:05 -05003294#endif /* CIFS_ACL */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10003295 .next_header = smb2_next_header,
Steve French1080ef72011-02-24 18:07:19 +00003296};
3297
Steve Frenchaab18932015-06-23 23:37:11 -05003298struct smb_version_operations smb311_operations = {
3299 .compare_fids = smb2_compare_fids,
3300 .setup_request = smb2_setup_request,
3301 .setup_async_request = smb2_setup_async_request,
3302 .check_receive = smb2_check_receive,
3303 .add_credits = smb2_add_credits,
3304 .set_credits = smb2_set_credits,
3305 .get_credits_field = smb2_get_credits_field,
3306 .get_credits = smb2_get_credits,
3307 .wait_mtu_credits = smb2_wait_mtu_credits,
3308 .get_next_mid = smb2_get_next_mid,
3309 .read_data_offset = smb2_read_data_offset,
3310 .read_data_length = smb2_read_data_length,
3311 .map_error = map_smb2_to_linux_error,
3312 .find_mid = smb2_find_mid,
3313 .check_message = smb2_check_message,
3314 .dump_detail = smb2_dump_detail,
3315 .clear_stats = smb2_clear_stats,
3316 .print_stats = smb2_print_stats,
3317 .dump_share_caps = smb2_dump_share_caps,
3318 .is_oplock_break = smb2_is_valid_oplock_break,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08003319 .handle_cancelled_mid = smb2_handle_cancelled_mid,
Steve Frenchaab18932015-06-23 23:37:11 -05003320 .downgrade_oplock = smb2_downgrade_oplock,
3321 .need_neg = smb2_need_neg,
3322 .negotiate = smb2_negotiate,
3323 .negotiate_wsize = smb2_negotiate_wsize,
3324 .negotiate_rsize = smb2_negotiate_rsize,
3325 .sess_setup = SMB2_sess_setup,
3326 .logoff = SMB2_logoff,
3327 .tree_connect = SMB2_tcon,
3328 .tree_disconnect = SMB2_tdis,
3329 .qfs_tcon = smb3_qfs_tcon,
3330 .is_path_accessible = smb2_is_path_accessible,
3331 .can_echo = smb2_can_echo,
3332 .echo = SMB2_echo,
3333 .query_path_info = smb2_query_path_info,
3334 .get_srv_inum = smb2_get_srv_inum,
3335 .query_file_info = smb2_query_file_info,
3336 .set_path_size = smb2_set_path_size,
3337 .set_file_size = smb2_set_file_size,
3338 .set_file_info = smb2_set_file_info,
3339 .set_compression = smb2_set_compression,
3340 .mkdir = smb2_mkdir,
3341 .mkdir_setinfo = smb2_mkdir_setinfo,
Steve Frenchbea851b2018-06-14 21:56:32 -05003342 .posix_mkdir = smb311_posix_mkdir,
Steve Frenchaab18932015-06-23 23:37:11 -05003343 .rmdir = smb2_rmdir,
3344 .unlink = smb2_unlink,
3345 .rename = smb2_rename_path,
3346 .create_hardlink = smb2_create_hardlink,
3347 .query_symlink = smb2_query_symlink,
3348 .query_mf_symlink = smb3_query_mf_symlink,
3349 .create_mf_symlink = smb3_create_mf_symlink,
3350 .open = smb2_open_file,
3351 .set_fid = smb2_set_fid,
3352 .close = smb2_close_file,
3353 .flush = smb2_flush_file,
3354 .async_readv = smb2_async_readv,
3355 .async_writev = smb2_async_writev,
3356 .sync_read = smb2_sync_read,
3357 .sync_write = smb2_sync_write,
3358 .query_dir_first = smb2_query_dir_first,
3359 .query_dir_next = smb2_query_dir_next,
3360 .close_dir = smb2_close_dir,
3361 .calc_smb_size = smb2_calc_size,
3362 .is_status_pending = smb2_is_status_pending,
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07003363 .is_session_expired = smb2_is_session_expired,
Steve Frenchaab18932015-06-23 23:37:11 -05003364 .oplock_response = smb2_oplock_response,
Steve French2d304212018-06-24 23:28:12 -05003365 .queryfs = smb311_queryfs,
Steve Frenchaab18932015-06-23 23:37:11 -05003366 .mand_lock = smb2_mand_lock,
3367 .mand_unlock_range = smb2_unlock_range,
3368 .push_mand_locks = smb2_push_mandatory_locks,
3369 .get_lease_key = smb2_get_lease_key,
3370 .set_lease_key = smb2_set_lease_key,
3371 .new_lease_key = smb2_new_lease_key,
Steve French373512e2015-12-18 13:05:30 -06003372 .generate_signingkey = generate_smb311signingkey,
Steve Frenchaab18932015-06-23 23:37:11 -05003373 .calc_signature = smb3_calc_signature,
Steve Frenchb3152e22015-06-24 03:17:02 -05003374 .set_integrity = smb3_set_integrity,
Steve Frenchaab18932015-06-23 23:37:11 -05003375 .is_read_op = smb21_is_read_op,
3376 .set_oplock_level = smb3_set_oplock_level,
3377 .create_lease_buf = smb3_create_lease_buf,
3378 .parse_lease_buf = smb3_parse_lease_buf,
Sachin Prabhu312bbc52017-04-04 02:12:04 -05003379 .copychunk_range = smb2_copychunk_range,
Steve French02b16662015-06-27 21:18:36 -07003380 .duplicate_extents = smb2_duplicate_extents,
Steve Frenchaab18932015-06-23 23:37:11 -05003381/* .validate_negotiate = smb3_validate_negotiate, */ /* not used in 3.11 */
3382 .wp_retry_size = smb2_wp_retry_size,
3383 .dir_needs_close = smb2_dir_needs_close,
3384 .fallocate = smb3_fallocate,
Steve French834170c2016-09-30 21:14:26 -05003385 .enum_snapshots = smb3_enum_snapshots,
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07003386 .init_transform_rq = smb3_init_transform_rq,
3387 .free_transform_rq = smb3_free_transform_rq,
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08003388 .is_transform_hdr = smb3_is_transform_hdr,
3389 .receive_transform = smb3_receive_transform,
Aurelien Aptel9d496402017-02-13 16:16:49 +01003390 .get_dfs_refer = smb2_get_dfs_refer,
Sachin Prabhuef65aae2017-01-18 15:35:57 +05303391 .select_sectype = smb2_select_sectype,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003392#ifdef CONFIG_CIFS_XATTR
3393 .query_all_EAs = smb2_query_eas,
Ronnie Sahlberg55175542017-08-24 11:24:56 +10003394 .set_EA = smb2_set_ea,
Ronnie Sahlberg95907fe2017-08-24 11:24:55 +10003395#endif /* CIFS_XATTR */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10003396 .next_header = smb2_next_header,
Steve Frenchaab18932015-06-23 23:37:11 -05003397};
Steve Frenchaab18932015-06-23 23:37:11 -05003398
Steve Frenchdd446b12012-11-28 23:21:06 -06003399struct smb_version_values smb20_values = {
3400 .version_string = SMB20_VERSION_STRING,
3401 .protocol_id = SMB20_PROT_ID,
3402 .req_capabilities = 0, /* MBZ */
3403 .large_lock_type = 0,
3404 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
3405 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
3406 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10003407 .header_size = sizeof(struct smb2_sync_hdr),
3408 .header_preamble_size = 0,
Steve Frenchdd446b12012-11-28 23:21:06 -06003409 .max_header_size = MAX_SMB2_HDR_SIZE,
3410 .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
3411 .lock_cmd = SMB2_LOCK,
3412 .cap_unix = 0,
3413 .cap_nt_find = SMB2_NT_FIND,
3414 .cap_large_files = SMB2_LARGE_FILES,
Jeff Layton502858822013-06-27 12:45:00 -04003415 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
3416 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
Pavel Shilovskya41a28b2013-09-04 13:07:41 +04003417 .create_lease_size = sizeof(struct create_lease),
Steve Frenchdd446b12012-11-28 23:21:06 -06003418};
3419
Steve French1080ef72011-02-24 18:07:19 +00003420struct smb_version_values smb21_values = {
3421 .version_string = SMB21_VERSION_STRING,
Steve Frenche4aa25e2012-10-01 12:26:22 -05003422 .protocol_id = SMB21_PROT_ID,
3423 .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */
3424 .large_lock_type = 0,
3425 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
3426 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
3427 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10003428 .header_size = sizeof(struct smb2_sync_hdr),
3429 .header_preamble_size = 0,
Steve Frenche4aa25e2012-10-01 12:26:22 -05003430 .max_header_size = MAX_SMB2_HDR_SIZE,
3431 .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
3432 .lock_cmd = SMB2_LOCK,
3433 .cap_unix = 0,
3434 .cap_nt_find = SMB2_NT_FIND,
3435 .cap_large_files = SMB2_LARGE_FILES,
Jeff Layton502858822013-06-27 12:45:00 -04003436 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
3437 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
Pavel Shilovskya41a28b2013-09-04 13:07:41 +04003438 .create_lease_size = sizeof(struct create_lease),
Steve Frenche4aa25e2012-10-01 12:26:22 -05003439};
3440
Steve French9764c022017-09-17 10:41:35 -05003441struct smb_version_values smb3any_values = {
3442 .version_string = SMB3ANY_VERSION_STRING,
3443 .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
3444 .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
3445 .large_lock_type = 0,
3446 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
3447 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
3448 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10003449 .header_size = sizeof(struct smb2_sync_hdr),
3450 .header_preamble_size = 0,
Steve French9764c022017-09-17 10:41:35 -05003451 .max_header_size = MAX_SMB2_HDR_SIZE,
3452 .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
3453 .lock_cmd = SMB2_LOCK,
3454 .cap_unix = 0,
3455 .cap_nt_find = SMB2_NT_FIND,
3456 .cap_large_files = SMB2_LARGE_FILES,
3457 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
3458 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
3459 .create_lease_size = sizeof(struct create_lease_v2),
3460};
3461
3462struct smb_version_values smbdefault_values = {
3463 .version_string = SMBDEFAULT_VERSION_STRING,
3464 .protocol_id = SMB302_PROT_ID, /* doesn't matter, send protocol array */
3465 .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
3466 .large_lock_type = 0,
3467 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
3468 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
3469 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10003470 .header_size = sizeof(struct smb2_sync_hdr),
3471 .header_preamble_size = 0,
Steve French9764c022017-09-17 10:41:35 -05003472 .max_header_size = MAX_SMB2_HDR_SIZE,
3473 .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
3474 .lock_cmd = SMB2_LOCK,
3475 .cap_unix = 0,
3476 .cap_nt_find = SMB2_NT_FIND,
3477 .cap_large_files = SMB2_LARGE_FILES,
3478 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
3479 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
3480 .create_lease_size = sizeof(struct create_lease_v2),
3481};
3482
Steve Frenche4aa25e2012-10-01 12:26:22 -05003483struct smb_version_values smb30_values = {
3484 .version_string = SMB30_VERSION_STRING,
3485 .protocol_id = SMB30_PROT_ID,
Steve French373512e2015-12-18 13:05:30 -06003486 .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
Pavel Shilovsky027e8ee2012-09-19 06:22:43 -07003487 .large_lock_type = 0,
3488 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
3489 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
3490 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10003491 .header_size = sizeof(struct smb2_sync_hdr),
3492 .header_preamble_size = 0,
Pavel Shilovsky093b2bd2011-06-08 15:51:07 +04003493 .max_header_size = MAX_SMB2_HDR_SIZE,
Pavel Shilovsky09a47072012-09-18 16:20:29 -07003494 .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
Pavel Shilovsky2dc7e1c2011-12-26 22:53:34 +04003495 .lock_cmd = SMB2_LOCK,
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003496 .cap_unix = 0,
3497 .cap_nt_find = SMB2_NT_FIND,
3498 .cap_large_files = SMB2_LARGE_FILES,
Jeff Layton502858822013-06-27 12:45:00 -04003499 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
3500 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
Pavel Shilovskyf0473902013-09-04 13:44:05 +04003501 .create_lease_size = sizeof(struct create_lease_v2),
Steve French1080ef72011-02-24 18:07:19 +00003502};
Steve French20b6d8b2013-06-12 22:48:41 -05003503
3504struct smb_version_values smb302_values = {
3505 .version_string = SMB302_VERSION_STRING,
3506 .protocol_id = SMB302_PROT_ID,
Steve French373512e2015-12-18 13:05:30 -06003507 .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
Steve French20b6d8b2013-06-12 22:48:41 -05003508 .large_lock_type = 0,
3509 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
3510 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
3511 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10003512 .header_size = sizeof(struct smb2_sync_hdr),
3513 .header_preamble_size = 0,
Steve French20b6d8b2013-06-12 22:48:41 -05003514 .max_header_size = MAX_SMB2_HDR_SIZE,
3515 .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
3516 .lock_cmd = SMB2_LOCK,
3517 .cap_unix = 0,
3518 .cap_nt_find = SMB2_NT_FIND,
3519 .cap_large_files = SMB2_LARGE_FILES,
Jeff Layton502858822013-06-27 12:45:00 -04003520 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
3521 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
Pavel Shilovskyf0473902013-09-04 13:44:05 +04003522 .create_lease_size = sizeof(struct create_lease_v2),
Steve French20b6d8b2013-06-12 22:48:41 -05003523};
Steve French5f7fbf72014-12-17 22:52:58 -06003524
Steve French5f7fbf72014-12-17 22:52:58 -06003525struct smb_version_values smb311_values = {
3526 .version_string = SMB311_VERSION_STRING,
3527 .protocol_id = SMB311_PROT_ID,
Steve French19558802017-06-21 16:50:20 -05003528 .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES | SMB2_GLOBAL_CAP_ENCRYPTION,
Steve French5f7fbf72014-12-17 22:52:58 -06003529 .large_lock_type = 0,
3530 .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
3531 .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
3532 .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10003533 .header_size = sizeof(struct smb2_sync_hdr),
3534 .header_preamble_size = 0,
Steve French5f7fbf72014-12-17 22:52:58 -06003535 .max_header_size = MAX_SMB2_HDR_SIZE,
3536 .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
3537 .lock_cmd = SMB2_LOCK,
3538 .cap_unix = 0,
3539 .cap_nt_find = SMB2_NT_FIND,
3540 .cap_large_files = SMB2_LARGE_FILES,
3541 .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
3542 .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
3543 .create_lease_size = sizeof(struct create_lease_v2),
3544};