connect.c 144.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/connect.c
 *
4
 *   Copyright (C) International Business Machines  Corp., 2002,2011
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
S
Steve French 已提交
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
L
Linus Torvalds 已提交
20 21 22 23
 */
#include <linux/fs.h>
#include <linux/net.h>
#include <linux/string.h>
24
#include <linux/sched/signal.h>
L
Linus Torvalds 已提交
25 26
#include <linux/list.h>
#include <linux/wait.h>
27
#include <linux/slab.h>
L
Linus Torvalds 已提交
28 29 30 31
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
#include <linux/mempool.h>
32
#include <linux/delay.h>
33
#include <linux/completion.h>
34
#include <linux/kthread.h>
35
#include <linux/pagevec.h>
36
#include <linux/freezer.h>
37
#include <linux/namei.h>
38
#include <linux/uuid.h>
39
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
40
#include <asm/processor.h>
41
#include <linux/inet.h>
42
#include <linux/module.h>
43
#include <keys/user-type.h>
44
#include <net/ipv6.h>
45
#include <linux/parser.h>
46
#include <linux/bvec.h>
L
Linus Torvalds 已提交
47 48 49 50 51 52 53 54 55
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
#include "ntlmssp.h"
#include "nterr.h"
#include "rfc1002pdu.h"
56
#include "fscache.h"
57
#include "smb2proto.h"
58
#include "smbdirect.h"
59
#include "dns_resolve.h"
60
#include "cifsfs.h"
61 62 63
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
L
Linus Torvalds 已提交
64 65

extern mempool_t *cifs_req_poolp;
66
extern bool disable_legacy_dialects;
L
Linus Torvalds 已提交
67

68
/* FIXME: should these be tunable? */
69
#define TLINK_ERROR_EXPIRE	(1 * HZ)
70
#define TLINK_IDLE_EXPIRE	(600 * HZ)
71

72 73 74 75
enum {
	/* Mount options that take no arguments */
	Opt_user_xattr, Opt_nouser_xattr,
	Opt_forceuid, Opt_noforceuid,
J
Jeff Layton 已提交
76
	Opt_forcegid, Opt_noforcegid,
77
	Opt_noblocksend, Opt_noautotune, Opt_nolease,
78
	Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
79
	Opt_mapposix, Opt_nomapposix,
80 81
	Opt_mapchars, Opt_nomapchars, Opt_sfu,
	Opt_nosfu, Opt_nodfs, Opt_posixpaths,
82
	Opt_noposixpaths, Opt_nounix, Opt_unix,
83 84
	Opt_nocase,
	Opt_brl, Opt_nobrl,
S
Steve French 已提交
85
	Opt_handlecache, Opt_nohandlecache,
86
	Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
87 88 89 90 91 92 93
	Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
	Opt_nohard, Opt_nosoft,
	Opt_nointr, Opt_intr,
	Opt_nostrictsync, Opt_strictsync,
	Opt_serverino, Opt_noserverino,
	Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
	Opt_acl, Opt_noacl, Opt_locallease,
94
	Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
95
	Opt_fsc, Opt_mfsymlinks,
96
	Opt_multiuser, Opt_sloppy, Opt_nosharesock,
97
	Opt_persistent, Opt_nopersistent,
S
Steve French 已提交
98
	Opt_resilient, Opt_noresilient,
99
	Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
100
	Opt_multichannel, Opt_nomultichannel,
101
	Opt_compress,
102 103 104 105 106

	/* Mount options which take numeric value */
	Opt_backupuid, Opt_backupgid, Opt_uid,
	Opt_cruid, Opt_gid, Opt_file_mode,
	Opt_dirmode, Opt_port,
107
	Opt_min_enc_offload,
108
	Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
109
	Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
110
	Opt_snapshot, Opt_max_channels,
111 112 113

	/* Mount options which take string value */
	Opt_user, Opt_pass, Opt_ip,
114
	Opt_domain, Opt_srcaddr, Opt_iocharset,
115
	Opt_netbiosname, Opt_servern,
116
	Opt_ver, Opt_vers, Opt_sec, Opt_cache,
117 118 119 120 121 122

	/* Mount options to be ignored */
	Opt_ignore,

	/* Options which could be blank */
	Opt_blank_pass,
123 124
	Opt_blank_user,
	Opt_blank_ip,
125 126 127 128 129 130 131 132 133 134

	Opt_err
};

static const match_table_t cifs_mount_option_tokens = {

	{ Opt_user_xattr, "user_xattr" },
	{ Opt_nouser_xattr, "nouser_xattr" },
	{ Opt_forceuid, "forceuid" },
	{ Opt_noforceuid, "noforceuid" },
J
Jeff Layton 已提交
135 136
	{ Opt_forcegid, "forcegid" },
	{ Opt_noforcegid, "noforcegid" },
137 138
	{ Opt_noblocksend, "noblocksend" },
	{ Opt_noautotune, "noautotune" },
139
	{ Opt_nolease, "nolease" },
140 141 142 143
	{ Opt_hard, "hard" },
	{ Opt_soft, "soft" },
	{ Opt_perm, "perm" },
	{ Opt_noperm, "noperm" },
144
	{ Opt_mapchars, "mapchars" }, /* SFU style */
145
	{ Opt_nomapchars, "nomapchars" },
146 147
	{ Opt_mapposix, "mapposix" }, /* SFM style */
	{ Opt_nomapposix, "nomapposix" },
148 149 150 151 152 153 154
	{ Opt_sfu, "sfu" },
	{ Opt_nosfu, "nosfu" },
	{ Opt_nodfs, "nodfs" },
	{ Opt_posixpaths, "posixpaths" },
	{ Opt_noposixpaths, "noposixpaths" },
	{ Opt_nounix, "nounix" },
	{ Opt_nounix, "nolinux" },
155 156 157 158
	{ Opt_nounix, "noposix" },
	{ Opt_unix, "unix" },
	{ Opt_unix, "linux" },
	{ Opt_unix, "posix" },
159 160 161 162
	{ Opt_nocase, "nocase" },
	{ Opt_nocase, "ignorecase" },
	{ Opt_brl, "brl" },
	{ Opt_nobrl, "nobrl" },
S
Steve French 已提交
163 164
	{ Opt_handlecache, "handlecache" },
	{ Opt_nohandlecache, "nohandlecache" },
165 166
	{ Opt_nobrl, "nolock" },
	{ Opt_forcemandatorylock, "forcemandatorylock" },
167
	{ Opt_forcemandatorylock, "forcemand" },
168 169
	{ Opt_setuids, "setuids" },
	{ Opt_nosetuids, "nosetuids" },
170
	{ Opt_setuidfromacl, "idsfromsid" },
171 172 173 174 175 176 177 178 179 180 181
	{ Opt_dynperm, "dynperm" },
	{ Opt_nodynperm, "nodynperm" },
	{ Opt_nohard, "nohard" },
	{ Opt_nosoft, "nosoft" },
	{ Opt_nointr, "nointr" },
	{ Opt_intr, "intr" },
	{ Opt_nostrictsync, "nostrictsync" },
	{ Opt_strictsync, "strictsync" },
	{ Opt_serverino, "serverino" },
	{ Opt_noserverino, "noserverino" },
	{ Opt_rwpidforward, "rwpidforward" },
182
	{ Opt_modesid, "modefromsid" },
183 184 185 186 187 188
	{ Opt_cifsacl, "cifsacl" },
	{ Opt_nocifsacl, "nocifsacl" },
	{ Opt_acl, "acl" },
	{ Opt_noacl, "noacl" },
	{ Opt_locallease, "locallease" },
	{ Opt_sign, "sign" },
189
	{ Opt_ignore_signature, "signloosely" },
190 191 192 193 194
	{ Opt_seal, "seal" },
	{ Opt_noac, "noac" },
	{ Opt_fsc, "fsc" },
	{ Opt_mfsymlinks, "mfsymlinks" },
	{ Opt_multiuser, "multiuser" },
195
	{ Opt_sloppy, "sloppy" },
196
	{ Opt_nosharesock, "nosharesock" },
197 198
	{ Opt_persistent, "persistenthandles"},
	{ Opt_nopersistent, "nopersistenthandles"},
S
Steve French 已提交
199 200
	{ Opt_resilient, "resilienthandles"},
	{ Opt_noresilient, "noresilienthandles"},
201
	{ Opt_domainauto, "domainauto"},
L
Long Li 已提交
202
	{ Opt_rdma, "rdma"},
203 204
	{ Opt_multichannel, "multichannel" },
	{ Opt_nomultichannel, "nomultichannel" },
205 206 207 208 209 210 211 212 213 214

	{ Opt_backupuid, "backupuid=%s" },
	{ Opt_backupgid, "backupgid=%s" },
	{ Opt_uid, "uid=%s" },
	{ Opt_cruid, "cruid=%s" },
	{ Opt_gid, "gid=%s" },
	{ Opt_file_mode, "file_mode=%s" },
	{ Opt_dirmode, "dirmode=%s" },
	{ Opt_dirmode, "dir_mode=%s" },
	{ Opt_port, "port=%s" },
215
	{ Opt_min_enc_offload, "esize=%s" },
216
	{ Opt_blocksize, "bsize=%s" },
217 218 219
	{ Opt_rsize, "rsize=%s" },
	{ Opt_wsize, "wsize=%s" },
	{ Opt_actimeo, "actimeo=%s" },
220
	{ Opt_handletimeout, "handletimeout=%s" },
S
Steve French 已提交
221
	{ Opt_echo_interval, "echo_interval=%s" },
222
	{ Opt_max_credits, "max_credits=%s" },
223
	{ Opt_snapshot, "snapshot=%s" },
224
	{ Opt_max_channels, "max_channels=%s" },
225
	{ Opt_compress, "compress=%s" },
226

227 228
	{ Opt_blank_user, "user=" },
	{ Opt_blank_user, "username=" },
229 230 231
	{ Opt_user, "user=%s" },
	{ Opt_user, "username=%s" },
	{ Opt_blank_pass, "pass=" },
232
	{ Opt_blank_pass, "password=" },
233 234
	{ Opt_pass, "pass=%s" },
	{ Opt_pass, "password=%s" },
235 236
	{ Opt_blank_ip, "ip=" },
	{ Opt_blank_ip, "addr=" },
237 238
	{ Opt_ip, "ip=%s" },
	{ Opt_ip, "addr=%s" },
239 240 241
	{ Opt_ignore, "unc=%s" },
	{ Opt_ignore, "target=%s" },
	{ Opt_ignore, "path=%s" },
242 243 244 245
	{ Opt_domain, "dom=%s" },
	{ Opt_domain, "domain=%s" },
	{ Opt_domain, "workgroup=%s" },
	{ Opt_srcaddr, "srcaddr=%s" },
246
	{ Opt_ignore, "prefixpath=%s" },
247 248 249 250
	{ Opt_iocharset, "iocharset=%s" },
	{ Opt_netbiosname, "netbiosname=%s" },
	{ Opt_servern, "servern=%s" },
	{ Opt_ver, "ver=%s" },
251
	{ Opt_vers, "vers=%s" },
252
	{ Opt_sec, "sec=%s" },
253
	{ Opt_cache, "cache=%s" },
254 255 256

	{ Opt_ignore, "cred" },
	{ Opt_ignore, "credentials" },
257 258
	{ Opt_ignore, "cred=%s" },
	{ Opt_ignore, "credentials=%s" },
259 260 261 262 263 264 265 266 267 268 269 270
	{ Opt_ignore, "guest" },
	{ Opt_ignore, "rw" },
	{ Opt_ignore, "ro" },
	{ Opt_ignore, "suid" },
	{ Opt_ignore, "nosuid" },
	{ Opt_ignore, "exec" },
	{ Opt_ignore, "noexec" },
	{ Opt_ignore, "nodev" },
	{ Opt_ignore, "noauto" },
	{ Opt_ignore, "dev" },
	{ Opt_ignore, "mand" },
	{ Opt_ignore, "nomand" },
271
	{ Opt_ignore, "relatime" },
272
	{ Opt_ignore, "_netdev" },
273
	{ Opt_rootfs, "rootfs" },
274 275 276 277 278 279 280

	{ Opt_err, NULL }
};

enum {
	Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
	Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
281 282
	Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
	Opt_sec_ntlmv2i, Opt_sec_lanman,
283 284 285 286 287 288 289 290 291 292 293 294 295
	Opt_sec_none,

	Opt_sec_err
};

static const match_table_t cifs_secflavor_tokens = {
	{ Opt_sec_krb5, "krb5" },
	{ Opt_sec_krb5i, "krb5i" },
	{ Opt_sec_krb5p, "krb5p" },
	{ Opt_sec_ntlmsspi, "ntlmsspi" },
	{ Opt_sec_ntlmssp, "ntlmssp" },
	{ Opt_ntlm, "ntlm" },
	{ Opt_sec_ntlmi, "ntlmi" },
296 297
	{ Opt_sec_ntlmv2, "nontlm" },
	{ Opt_sec_ntlmv2, "ntlmv2" },
298 299 300 301 302 303 304
	{ Opt_sec_ntlmv2i, "ntlmv2i" },
	{ Opt_sec_lanman, "lanman" },
	{ Opt_sec_none, "none" },

	{ Opt_sec_err, NULL }
};

305 306 307 308 309
/* cache flavors */
enum {
	Opt_cache_loose,
	Opt_cache_strict,
	Opt_cache_none,
310
	Opt_cache_ro,
311
	Opt_cache_rw,
312 313 314 315 316 317 318
	Opt_cache_err
};

static const match_table_t cifs_cacheflavor_tokens = {
	{ Opt_cache_loose, "loose" },
	{ Opt_cache_strict, "strict" },
	{ Opt_cache_none, "none" },
319
	{ Opt_cache_ro, "ro" },
320
	{ Opt_cache_rw, "singleclient" },
321 322 323
	{ Opt_cache_err, NULL }
};

324 325
static const match_table_t cifs_smb_version_tokens = {
	{ Smb_1, SMB1_VERSION_STRING },
S
Steve French 已提交
326
	{ Smb_20, SMB20_VERSION_STRING},
327
	{ Smb_21, SMB21_VERSION_STRING },
328
	{ Smb_30, SMB30_VERSION_STRING },
S
Steve French 已提交
329
	{ Smb_302, SMB302_VERSION_STRING },
330
	{ Smb_302, ALT_SMB302_VERSION_STRING },
331
	{ Smb_311, SMB311_VERSION_STRING },
332
	{ Smb_311, ALT_SMB311_VERSION_STRING },
333 334
	{ Smb_3any, SMB3ANY_VERSION_STRING },
	{ Smb_default, SMBDEFAULT_VERSION_STRING },
335
	{ Smb_version_err, NULL }
336 337
};

338 339
static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
J
Jeff Layton 已提交
340
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
341
static void cifs_prune_tlinks(struct work_struct *work);
342 343
static char *extract_hostname(const char *unc);

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
/*
 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
 * get their ip addresses changed at some point.
 *
 * This should be called with server->srv_mutex held.
 */
#ifdef CONFIG_CIFS_DFS_UPCALL
static int reconn_set_ipaddr(struct TCP_Server_Info *server)
{
	int rc;
	int len;
	char *unc, *ipaddr = NULL;

	if (!server->hostname)
		return -EINVAL;

	len = strlen(server->hostname) + 3;

	unc = kmalloc(len, GFP_KERNEL);
	if (!unc) {
		cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
		return -ENOMEM;
	}
367
	scnprintf(unc, len, "\\\\%s", server->hostname);
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390

	rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
	kfree(unc);

	if (rc < 0) {
		cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
			 __func__, server->hostname, rc);
		return rc;
	}

	rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
				  strlen(ipaddr));
	kfree(ipaddr);

	return !rc ? -1 : 0;
}
#else
static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
{
	return 0;
}
#endif

391 392 393
#ifdef CONFIG_CIFS_DFS_UPCALL
struct super_cb_data {
	struct TCP_Server_Info *server;
394
	struct super_block *sb;
395 396 397 398 399 400 401 402 403 404
};

/* These functions must be called with server->srv_mutex held */

static void super_cb(struct super_block *sb, void *arg)
{
	struct super_cb_data *d = arg;
	struct cifs_sb_info *cifs_sb;
	struct cifs_tcon *tcon;

405
	if (d->sb)
406 407 408 409 410
		return;

	cifs_sb = CIFS_SB(sb);
	tcon = cifs_sb_master_tcon(cifs_sb);
	if (tcon->ses->server == d->server)
411
		d->sb = sb;
412 413
}

414
static struct super_block *get_tcp_super(struct TCP_Server_Info *server)
415 416 417
{
	struct super_cb_data d = {
		.server = server,
418
		.sb = NULL,
419 420 421
	};

	iterate_supers_type(&cifs_fs_type, super_cb, &d);
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437

	if (unlikely(!d.sb))
		return ERR_PTR(-ENOENT);
	/*
	 * Grab an active reference in order to prevent automounts (DFS links)
	 * of expiring and then freeing up our cifs superblock pointer while
	 * we're doing failover.
	 */
	cifs_sb_active(d.sb);
	return d.sb;
}

static inline void put_tcp_super(struct super_block *sb)
{
	if (!IS_ERR_OR_NULL(sb))
		cifs_sb_deactive(sb);
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
}

static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
				    struct cifs_sb_info *cifs_sb,
				    struct dfs_cache_tgt_list *tgt_list,
				    struct dfs_cache_tgt_iterator **tgt_it)
{
	const char *name;

	if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
	    !server->nr_targets)
		return;

	if (!*tgt_it) {
		*tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
	} else {
		*tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
		if (!*tgt_it)
			*tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
	}

	cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);

	name = dfs_cache_get_tgt_name(*tgt_it);

	kfree(server->hostname);

	server->hostname = extract_hostname(name);
D
Dan Carpenter 已提交
466 467 468 469
	if (IS_ERR(server->hostname)) {
		cifs_dbg(FYI,
			 "%s: failed to extract hostname from target: %ld\n",
			 __func__, PTR_ERR(server->hostname));
470 471 472 473 474 475 476 477 478 479 480 481
	}
}

static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
					   struct dfs_cache_tgt_list *tl,
					   struct dfs_cache_tgt_iterator **it)
{
	if (!cifs_sb->origin_fullpath)
		return -EOPNOTSUPP;
	return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
}
#endif
L
Linus Torvalds 已提交
482

483 484 485 486 487 488 489 490
/*
 * cifs tcp session reconnection
 *
 * mark tcp session as reconnecting so temporarily locked
 * mark all smb sessions as reconnecting for tcp session
 * reconnect tcp session
 * wake up waiters on reconnection? - (not needed currently)
 */
P
Pavel Shilovsky 已提交
491
int
L
Linus Torvalds 已提交
492 493 494
cifs_reconnect(struct TCP_Server_Info *server)
{
	int rc = 0;
495
	struct list_head *tmp, *tmp2;
496 497
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
S
Steve French 已提交
498
	struct mid_q_entry *mid_entry;
499
	struct list_head retry_list;
500
#ifdef CONFIG_CIFS_DFS_UPCALL
501
	struct super_block *sb = NULL;
502 503
	struct cifs_sb_info *cifs_sb = NULL;
	struct dfs_cache_tgt_list tgt_list = {0};
504 505
	struct dfs_cache_tgt_iterator *tgt_it = NULL;
#endif
506

L
Linus Torvalds 已提交
507
	spin_lock(&GlobalMid_Lock);
508 509
	server->nr_targets = 1;
#ifdef CONFIG_CIFS_DFS_UPCALL
510
	spin_unlock(&GlobalMid_Lock);
511 512 513
	sb = get_tcp_super(server);
	if (IS_ERR(sb)) {
		rc = PTR_ERR(sb);
514 515
		cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
			 __func__, rc);
516
		sb = NULL;
517
	} else {
518 519
		cifs_sb = CIFS_SB(sb);

520
		rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
521
		if (rc && (rc != -EOPNOTSUPP)) {
522
			cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
523 524 525 526 527 528 529
				 __func__);
		} else {
			server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
		}
	}
	cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
		 server->nr_targets);
530
	spin_lock(&GlobalMid_Lock);
531
#endif
532
	if (server->tcpStatus == CifsExiting) {
S
Steve French 已提交
533
		/* the demux thread will exit normally
L
Linus Torvalds 已提交
534 535
		next time through the loop */
		spin_unlock(&GlobalMid_Lock);
536 537 538 539
#ifdef CONFIG_CIFS_DFS_UPCALL
		dfs_cache_free_tgts(&tgt_list);
		put_tcp_super(sb);
#endif
L
Linus Torvalds 已提交
540 541 542 543 544
		return rc;
	} else
		server->tcpStatus = CifsNeedReconnect;
	spin_unlock(&GlobalMid_Lock);
	server->maxBuf = 0;
545
	server->max_read = 0;
L
Linus Torvalds 已提交
546

547
	cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
S
Steve French 已提交
548
	trace_smb3_reconnect(server->CurrentMid, server->hostname);
L
Linus Torvalds 已提交
549 550 551

	/* before reconnecting the tcp session, mark the smb session (uid)
		and the tid bad so they are not used until reconnected */
552 553
	cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
		 __func__);
554
	spin_lock(&cifs_tcp_ses_lock);
555
	list_for_each(tmp, &server->smb_ses_list) {
556
		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
557
		ses->need_reconnect = true;
558
		list_for_each(tmp2, &ses->tcon_list) {
559
			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
S
Steve French 已提交
560
			tcon->need_reconnect = true;
L
Linus Torvalds 已提交
561
		}
A
Aurelien Aptel 已提交
562 563
		if (ses->tcon_ipc)
			ses->tcon_ipc->need_reconnect = true;
L
Linus Torvalds 已提交
564
	}
565
	spin_unlock(&cifs_tcp_ses_lock);
566

L
Linus Torvalds 已提交
567
	/* do not want to be sending data on a socket we are freeing */
568
	cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
J
Jeff Layton 已提交
569
	mutex_lock(&server->srv_mutex);
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
	if (server->ssocket) {
		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
		kernel_sock_shutdown(server->ssocket, SHUT_WR);
		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
		sock_release(server->ssocket);
		server->ssocket = NULL;
	}
	server->sequence_number = 0;
	server->session_estab = false;
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
	server->lstrp = jiffies;
L
Linus Torvalds 已提交
585

586
	/* mark submitted MIDs for retry and issue callback */
587
	INIT_LIST_HEAD(&retry_list);
588
	cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
L
Linus Torvalds 已提交
589
	spin_lock(&GlobalMid_Lock);
590 591
	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
592
		kref_get(&mid_entry->refcount);
593 594
		if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
			mid_entry->mid_state = MID_RETRY_NEEDED;
595
		list_move(&mid_entry->qhead, &retry_list);
596
		mid_entry->mid_flags |= MID_DELETED;
597 598
	}
	spin_unlock(&GlobalMid_Lock);
599
	mutex_unlock(&server->srv_mutex);
600

601
	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
602 603
	list_for_each_safe(tmp, tmp2, &retry_list) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
604 605
		list_del_init(&mid_entry->qhead);
		mid_entry->callback(mid_entry);
606
		cifs_mid_q_entry_release(mid_entry);
L
Linus Torvalds 已提交
607 608
	}

609 610
	if (cifs_rdma_enabled(server)) {
		mutex_lock(&server->srv_mutex);
611
		smbd_destroy(server);
612 613
		mutex_unlock(&server->srv_mutex);
	}
614

615
	do {
616
		try_to_freeze();
617

618
		mutex_lock(&server->srv_mutex);
619 620 621 622 623
		/*
		 * Set up next DFS target server (if any) for reconnect. If DFS
		 * feature is disabled, then we will retry last server we
		 * connected to before.
		 */
624 625 626 627
		if (cifs_rdma_enabled(server))
			rc = smbd_reconnect(server);
		else
			rc = generic_ip_connect(server);
S
Steve French 已提交
628
		if (rc) {
629
			cifs_dbg(FYI, "reconnect error %d\n", rc);
630 631 632 633
#ifdef CONFIG_CIFS_DFS_UPCALL
			reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
						&tgt_it);
#endif
634 635 636 637 638
			rc = reconn_set_ipaddr(server);
			if (rc) {
				cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
					 __func__, rc);
			}
639
			mutex_unlock(&server->srv_mutex);
640
			msleep(3000);
L
Linus Torvalds 已提交
641 642
		} else {
			atomic_inc(&tcpSesReconnectCount);
643
			set_credits(server, 1);
L
Linus Torvalds 已提交
644
			spin_lock(&GlobalMid_Lock);
645
			if (server->tcpStatus != CifsExiting)
646
				server->tcpStatus = CifsNeedNegotiate;
S
Steve French 已提交
647
			spin_unlock(&GlobalMid_Lock);
648
			mutex_unlock(&server->srv_mutex);
L
Linus Torvalds 已提交
649
		}
650
	} while (server->tcpStatus == CifsNeedReconnect);
651

652 653 654 655 656
#ifdef CONFIG_CIFS_DFS_UPCALL
	if (tgt_it) {
		rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
						    tgt_it);
		if (rc) {
657
			cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
658 659 660 661
				 __func__, rc);
		}
		rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
		if (rc) {
662
			cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
663 664
				 __func__, rc);
		}
665
		dfs_cache_free_tgts(&tgt_list);
666

667
	}
668 669

	put_tcp_super(sb);
670
#endif
671 672 673
	if (server->tcpStatus == CifsNeedNegotiate)
		mod_delayed_work(cifsiod_wq, &server->echo, 0);

L
Linus Torvalds 已提交
674 675 676
	return rc;
}

677 678 679 680 681 682
static void
cifs_echo_request(struct work_struct *work)
{
	int rc;
	struct TCP_Server_Info *server = container_of(work,
					struct TCP_Server_Info, echo.work);
683 684 685 686 687 688 689 690 691 692
	unsigned long echo_interval;

	/*
	 * If we need to renegotiate, set echo interval to zero to
	 * immediately call echo service where we can renegotiate.
	 */
	if (server->tcpStatus == CifsNeedNegotiate)
		echo_interval = 0;
	else
		echo_interval = server->echo_interval;
693

694
	/*
695 696
	 * We cannot send an echo if it is disabled.
	 * Also, no need to ping if we got a response recently.
697
	 */
698 699

	if (server->tcpStatus == CifsNeedReconnect ||
700 701
	    server->tcpStatus == CifsExiting ||
	    server->tcpStatus == CifsNew ||
702
	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
S
Steve French 已提交
703
	    time_before(jiffies, server->lstrp + echo_interval - HZ))
704 705
		goto requeue_echo;

706
	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
707
	if (rc)
708 709
		cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
			 server->hostname);
710 711

requeue_echo:
712
	queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
713 714
}

715
static bool
716
allocate_buffers(struct TCP_Server_Info *server)
717
{
718 719 720
	if (!server->bigbuf) {
		server->bigbuf = (char *)cifs_buf_get();
		if (!server->bigbuf) {
721
			cifs_server_dbg(VFS, "No memory for large SMB response\n");
722 723 724 725
			msleep(3000);
			/* retry will check if exiting */
			return false;
		}
726
	} else if (server->large_buf) {
727
		/* we are reusing a dirty large buf, clear its start */
728
		memset(server->bigbuf, 0, HEADER_SIZE(server));
729 730
	}

731 732 733
	if (!server->smallbuf) {
		server->smallbuf = (char *)cifs_small_buf_get();
		if (!server->smallbuf) {
734
			cifs_server_dbg(VFS, "No memory for SMB response\n");
735 736 737 738 739 740 741
			msleep(1000);
			/* retry will check if exiting */
			return false;
		}
		/* beginning of smb buffer is cleared in our buf_get */
	} else {
		/* if existing small buf clear beginning */
742
		memset(server->smallbuf, 0, HEADER_SIZE(server));
743 744 745 746 747
	}

	return true;
}

748 749 750
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
751
	/*
752
	 * We need to wait 3 echo intervals to make sure we handle such
753 754
	 * situations right:
	 * 1s  client sends a normal SMB request
755
	 * 2s  client gets a response
756 757 758 759 760 761
	 * 30s echo workqueue job pops, and decides we got a response recently
	 *     and don't need to send another
	 * ...
	 * 65s kernel_recvmsg times out, and we see that we haven't gotten
	 *     a response in >60s.
	 */
762 763
	if ((server->tcpStatus == CifsGood ||
	    server->tcpStatus == CifsNeedNegotiate) &&
764
	    time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
765 766
		cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
			 (3 * server->echo_interval) / HZ);
767 768 769 770 771 772 773 774
		cifs_reconnect(server);
		wake_up(&server->response_q);
		return true;
	}

	return false;
}

775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
static inline bool
zero_credits(struct TCP_Server_Info *server)
{
	int val;

	spin_lock(&server->req_lock);
	val = server->credits + server->echo_credits + server->oplock_credits;
	if (server->in_flight == 0 && val == 0) {
		spin_unlock(&server->req_lock);
		return true;
	}
	spin_unlock(&server->req_lock);
	return false;
}

790 791
static int
cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
792
{
J
Jeff Layton 已提交
793 794
	int length = 0;
	int total_read;
795

796 797
	smb_msg->msg_control = NULL;
	smb_msg->msg_controllen = 0;
798

799
	for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
800 801
		try_to_freeze();

802 803 804 805 806 807
		/* reconnect if no credits and no requests in flight */
		if (zero_credits(server)) {
			cifs_reconnect(server);
			return -ECONNABORTED;
		}

808 809
		if (server_unresponsive(server))
			return -ECONNABORTED;
810 811 812 813
		if (cifs_rdma_enabled(server) && server->smbd_conn)
			length = smbd_recv(server->smbd_conn, smb_msg);
		else
			length = sock_recvmsg(server->ssocket, smb_msg, 0);
814

815 816
		if (server->tcpStatus == CifsExiting)
			return -ESHUTDOWN;
817

818
		if (server->tcpStatus == CifsNeedReconnect) {
819
			cifs_reconnect(server);
820 821 822 823 824 825
			return -ECONNABORTED;
		}

		if (length == -ERESTARTSYS ||
		    length == -EAGAIN ||
		    length == -EINTR) {
826 827 828 829 830 831 832
			/*
			 * Minimum sleep to prevent looping, allowing socket
			 * to clear and app threads to set tcpStatus
			 * CifsNeedReconnect if server hung.
			 */
			usleep_range(1000, 2000);
			length = 0;
J
Jeff Layton 已提交
833
			continue;
834 835 836
		}

		if (length <= 0) {
837
			cifs_dbg(FYI, "Received no data or error: %d\n", length);
838
			cifs_reconnect(server);
839
			return -ECONNABORTED;
840 841
		}
	}
J
Jeff Layton 已提交
842
	return total_read;
843 844
}

J
Jeff Layton 已提交
845 846 847
int
cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
		      unsigned int to_read)
848
{
849 850
	struct msghdr smb_msg;
	struct kvec iov = {.iov_base = buf, .iov_len = to_read};
851
	iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
852

853 854
	return cifs_readv_from_socket(server, &smb_msg);
}
855

856 857
int
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
L
Long Li 已提交
858
	unsigned int page_offset, unsigned int to_read)
859 860
{
	struct msghdr smb_msg;
L
Long Li 已提交
861 862
	struct bio_vec bv = {
		.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
863
	iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
864
	return cifs_readv_from_socket(server, &smb_msg);
865 866
}

867
static bool
J
Jeff Layton 已提交
868
is_smb_response(struct TCP_Server_Info *server, unsigned char type)
869 870 871 872 873 874
{
	/*
	 * The first byte big endian of the length field,
	 * is actually not part of the length but the type
	 * with the most common, zero, as regular data.
	 */
J
Jeff Layton 已提交
875 876 877 878 879
	switch (type) {
	case RFC1002_SESSION_MESSAGE:
		/* Regular SMB response */
		return true;
	case RFC1002_SESSION_KEEP_ALIVE:
880
		cifs_dbg(FYI, "RFC 1002 session keep alive\n");
J
Jeff Layton 已提交
881 882
		break;
	case RFC1002_POSITIVE_SESSION_RESPONSE:
883
		cifs_dbg(FYI, "RFC 1002 positive session response\n");
J
Jeff Layton 已提交
884 885
		break;
	case RFC1002_NEGATIVE_SESSION_RESPONSE:
886 887 888 889
		/*
		 * We get this from Windows 98 instead of an error on
		 * SMB negprot response.
		 */
890
		cifs_dbg(FYI, "RFC 1002 negative session response\n");
891 892 893 894 895 896 897 898
		/* give server a second to clean up */
		msleep(1000);
		/*
		 * Always try 445 first on reconnect since we get NACK
		 * on some if we ever connected to port 139 (the NACK
		 * is since we do not begin with RFC1001 session
		 * initialize frame).
		 */
J
Jeff Layton 已提交
899
		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
900 901
		cifs_reconnect(server);
		wake_up(&server->response_q);
J
Jeff Layton 已提交
902 903
		break;
	default:
904
		cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
905 906 907
		cifs_reconnect(server);
	}

J
Jeff Layton 已提交
908
	return false;
909 910
}

J
Jeff Layton 已提交
911 912
void
dequeue_mid(struct mid_q_entry *mid, bool malformed)
913
{
914
#ifdef CONFIG_CIFS_STATS2
915
	mid->when_received = jiffies;
916
#endif
917 918
	spin_lock(&GlobalMid_Lock);
	if (!malformed)
919
		mid->mid_state = MID_RESPONSE_RECEIVED;
920
	else
921
		mid->mid_state = MID_RESPONSE_MALFORMED;
922 923 924 925 926 927 928
	/*
	 * Trying to handle/dequeue a mid after the send_recv()
	 * function has finished processing it is a bug.
	 */
	if (mid->mid_flags & MID_DELETED)
		printk_once(KERN_WARNING
			    "trying to dequeue a deleted mid\n");
929
	else {
930
		list_del_init(&mid->qhead);
931 932
		mid->mid_flags |= MID_DELETED;
	}
933
	spin_unlock(&GlobalMid_Lock);
934
}
935

936 937 938 939 940 941 942 943 944 945 946 947 948 949
static unsigned int
smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;

	/*
	 * SMB1 does not use credits.
	 */
	if (server->vals->header_preamble_size)
		return 0;

	return le16_to_cpu(shdr->CreditRequest);
}

950 951
static void
handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
952
	   char *buf, int malformed)
953
{
954 955
	if (server->ops->check_trans2 &&
	    server->ops->check_trans2(mid, server, buf, malformed))
956
		return;
957
	mid->credits_received = smb2_get_credits_from_hdr(buf, server);
958
	mid->resp_buf = buf;
959
	mid->large_buf = server->large_buf;
960 961 962 963 964 965 966 967
	/* Was previous buf put in mpx struct for multi-rsp? */
	if (!mid->multiRsp) {
		/* smb buffer will be freed by user thread */
		if (server->large_buf)
			server->bigbuf = NULL;
		else
			server->smallbuf = NULL;
	}
968
	dequeue_mid(mid, malformed);
969 970
}

971 972 973 974 975 976 977 978 979 980 981 982 983 984
static void clean_demultiplex_info(struct TCP_Server_Info *server)
{
	int length;

	/* take it off the list, if it's not already */
	spin_lock(&cifs_tcp_ses_lock);
	list_del_init(&server->tcp_ses_list);
	spin_unlock(&cifs_tcp_ses_lock);

	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
	wake_up_all(&server->response_q);

985
	/* check if we have blocked requests that need to free */
P
Pavel Shilovsky 已提交
986
	spin_lock(&server->req_lock);
987 988
	if (server->credits <= 0)
		server->credits = 1;
P
Pavel Shilovsky 已提交
989
	spin_unlock(&server->req_lock);
990 991 992 993 994 995 996 997 998 999
	/*
	 * Although there should not be any requests blocked on this queue it
	 * can not hurt to be paranoid and try to wake up requests that may
	 * haven been blocked when more than 50 at time were on the wire to the
	 * same server - they now will see the session is in exit state and get
	 * out of SendReceive.
	 */
	wake_up_all(&server->request_q);
	/* give those requests time to exit */
	msleep(125);
1000 1001
	if (cifs_rdma_enabled(server))
		smbd_destroy(server);
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
	if (server->ssocket) {
		sock_release(server->ssocket);
		server->ssocket = NULL;
	}

	if (!list_empty(&server->pending_mid_q)) {
		struct list_head dispose_list;
		struct mid_q_entry *mid_entry;
		struct list_head *tmp, *tmp2;

		INIT_LIST_HEAD(&dispose_list);
		spin_lock(&GlobalMid_Lock);
		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
1016
			cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
1017
			kref_get(&mid_entry->refcount);
1018
			mid_entry->mid_state = MID_SHUTDOWN;
1019
			list_move(&mid_entry->qhead, &dispose_list);
1020
			mid_entry->mid_flags |= MID_DELETED;
1021 1022 1023 1024 1025 1026
		}
		spin_unlock(&GlobalMid_Lock);

		/* now walk dispose list and issue callbacks */
		list_for_each_safe(tmp, tmp2, &dispose_list) {
			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
1027
			cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
1028 1029
			list_del_init(&mid_entry->qhead);
			mid_entry->callback(mid_entry);
1030
			cifs_mid_q_entry_release(mid_entry);
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
		}
		/* 1/8th of sec is more than enough time for them to exit */
		msleep(125);
	}

	if (!list_empty(&server->pending_mid_q)) {
		/*
		 * mpx threads have not exited yet give them at least the smb
		 * send timeout time for long ops.
		 *
		 * Due to delays on oplock break requests, we need to wait at
		 * least 45 seconds before giving up on a request getting a
		 * response and going ahead and killing cifsd.
		 */
1045
		cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
		msleep(46000);
		/*
		 * If threads still have not exited they are probably never
		 * coming home not much else we can do but free the memory.
		 */
	}

	kfree(server->hostname);
	kfree(server);

	length = atomic_dec_return(&tcpSesAllocCount);
	if (length > 0)
1058
		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
1059 1060
}

1061 1062 1063 1064 1065
static int
standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
	int length;
	char *buf = server->smallbuf;
1066
	unsigned int pdu_length = server->pdu_size;
1067 1068

	/* make sure this will fit in a large buffer */
1069 1070
	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
		server->vals->header_preamble_size) {
1071
		cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
1072 1073
		cifs_reconnect(server);
		wake_up(&server->response_q);
1074
		return -ECONNABORTED;
1075 1076 1077 1078 1079
	}

	/* switch to large buffer if too big for a small one */
	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
		server->large_buf = true;
1080
		memcpy(server->bigbuf, buf, server->total_read);
1081 1082 1083 1084
		buf = server->bigbuf;
	}

	/* now read the rest */
1085
	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
1086 1087 1088
				       pdu_length - HEADER_SIZE(server) + 1
				       + server->vals->header_preamble_size);

1089 1090 1091 1092
	if (length < 0)
		return length;
	server->total_read += length;

1093
	dump_smb(buf, server->total_read);
1094

1095 1096 1097 1098 1099 1100 1101 1102 1103
	return cifs_handle_standard(server, mid);
}

int
cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
	char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
	int length;

1104 1105 1106 1107 1108 1109 1110 1111 1112
	/*
	 * We know that we received enough to get to the MID as we
	 * checked the pdu_length earlier. Now check to see
	 * if the rest of the header is OK. We borrow the length
	 * var for the rest of the loop to avoid a new stack var.
	 *
	 * 48 bytes is enough to display the header and a little bit
	 * into the payload for debugging purposes.
	 */
1113
	length = server->ops->check_message(buf, server->total_read, server);
1114 1115 1116 1117
	if (length != 0)
		cifs_dump_mem("Bad SMB: ", buf,
			min_t(unsigned int, server->total_read, 48));

1118 1119 1120 1121 1122 1123 1124
	if (server->ops->is_session_expired &&
	    server->ops->is_session_expired(buf)) {
		cifs_reconnect(server);
		wake_up(&server->response_q);
		return -1;
	}

P
Pavel Shilovsky 已提交
1125
	if (server->ops->is_status_pending &&
1126
	    server->ops->is_status_pending(buf, server))
P
Pavel Shilovsky 已提交
1127 1128
		return -1;

1129 1130
	if (!mid)
		return length;
1131

1132
	handle_mid(mid, server, buf, length);
1133
	return 0;
1134 1135
}

1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
static void
smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;

	/*
	 * SMB1 does not use credits.
	 */
	if (server->vals->header_preamble_size)
		return;

	if (shdr->CreditRequest) {
		spin_lock(&server->req_lock);
		server->credits += le16_to_cpu(shdr->CreditRequest);
		spin_unlock(&server->req_lock);
		wake_up(&server->request_q);
	}
}


L
Linus Torvalds 已提交
1156
static int
1157
cifs_demultiplex_thread(void *p)
L
Linus Torvalds 已提交
1158
{
1159
	int i, num_mids, length;
1160
	struct TCP_Server_Info *server = p;
1161
	unsigned int pdu_length;
1162
	unsigned int next_offset;
1163
	char *buf = NULL;
1164
	struct task_struct *task_to_wake = NULL;
1165 1166
	struct mid_q_entry *mids[MAX_COMPOUND];
	char *bufs[MAX_COMPOUND];
L
Linus Torvalds 已提交
1167 1168

	current->flags |= PF_MEMALLOC;
1169
	cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
1170 1171 1172

	length = atomic_inc_return(&tcpSesAllocCount);
	if (length > 1)
1173
		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
L
Linus Torvalds 已提交
1174

1175
	set_freezable();
1176
	allow_kernel_signal(SIGKILL);
1177
	while (server->tcpStatus != CifsExiting) {
1178 1179
		if (try_to_freeze())
			continue;
1180

1181
		if (!allocate_buffers(server))
1182
			continue;
1183

1184 1185
		server->large_buf = false;
		buf = server->smallbuf;
1186
		pdu_length = 4; /* enough to get RFC1001 header */
1187

J
Jeff Layton 已提交
1188
		length = cifs_read_from_socket(server, buf, pdu_length);
J
Jeff Layton 已提交
1189
		if (length < 0)
L
Linus Torvalds 已提交
1190
			continue;
1191 1192 1193 1194 1195

		if (server->vals->header_preamble_size == 0)
			server->total_read = 0;
		else
			server->total_read = length;
L
Linus Torvalds 已提交
1196

1197 1198 1199 1200
		/*
		 * The right amount was read from socket - 4 bytes,
		 * so we can now interpret the length field.
		 */
1201
		pdu_length = get_rfc1002_length(buf);
1202

1203
		cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
J
Jeff Layton 已提交
1204
		if (!is_smb_response(server, buf[0]))
S
Steve French 已提交
1205
			continue;
1206 1207
next_pdu:
		server->pdu_size = pdu_length;
1208

1209
		/* make sure we have enough to get to the MID */
1210
		if (server->pdu_size < HEADER_SIZE(server) - 1 -
1211
		    server->vals->header_preamble_size) {
1212
			cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
1213
				 server->pdu_size);
1214 1215 1216
			cifs_reconnect(server);
			wake_up(&server->response_q);
			continue;
1217
		}
1218

1219
		/* read down to the MID */
1220 1221 1222 1223
		length = cifs_read_from_socket(server,
			     buf + server->vals->header_preamble_size,
			     HEADER_SIZE(server) - 1
			     - server->vals->header_preamble_size);
1224
		if (length < 0)
1225
			continue;
1226
		server->total_read += length;
L
Linus Torvalds 已提交
1227

1228 1229 1230 1231 1232 1233
		if (server->ops->next_header) {
			next_offset = server->ops->next_header(buf);
			if (next_offset)
				server->pdu_size = next_offset;
		}

1234 1235 1236 1237
		memset(mids, 0, sizeof(mids));
		memset(bufs, 0, sizeof(bufs));
		num_mids = 0;

1238 1239 1240 1241
		if (server->ops->is_transform_hdr &&
		    server->ops->receive_transform &&
		    server->ops->is_transform_hdr(buf)) {
			length = server->ops->receive_transform(server,
1242 1243 1244
								mids,
								bufs,
								&num_mids);
1245
		} else {
1246 1247
			mids[0] = server->ops->find_mid(server, buf);
			bufs[0] = buf;
1248
			num_mids = 1;
1249

1250 1251
			if (!mids[0] || !mids[0]->receive)
				length = standard_receive3(server, mids[0]);
1252
			else
1253
				length = mids[0]->receive(server, mids[0]);
1254
		}
1255

1256
		if (length < 0) {
1257 1258 1259
			for (i = 0; i < num_mids; i++)
				if (mids[i])
					cifs_mid_q_entry_release(mids[i]);
J
Jeff Layton 已提交
1260
			continue;
1261
		}
L
Linus Torvalds 已提交
1262

1263
		server->lstrp = jiffies;
S
Sachin Prabhu 已提交
1264

1265 1266 1267
		for (i = 0; i < num_mids; i++) {
			if (mids[i] != NULL) {
				mids[i]->resp_buf_size = server->pdu_size;
1268

1269 1270 1271 1272 1273 1274 1275
				if (!mids[i]->multiRsp || mids[i]->multiEnd)
					mids[i]->callback(mids[i]);

				cifs_mid_q_entry_release(mids[i]);
			} else if (server->ops->is_oplock_break &&
				   server->ops->is_oplock_break(bufs[i],
								server)) {
1276
				smb2_add_credits_from_hdr(bufs[i], server);
1277 1278
				cifs_dbg(FYI, "Received oplock break\n");
			} else {
1279
				cifs_server_dbg(VFS, "No task to wake, unknown frame "
1280 1281 1282 1283
					 "received! NumMids %d\n",
					 atomic_read(&midCount));
				cifs_dump_mem("Received Data is: ", bufs[i],
					      HEADER_SIZE(server));
1284
				smb2_add_credits_from_hdr(bufs[i], server);
1285
#ifdef CONFIG_CIFS_DEBUG2
1286 1287 1288 1289
				if (server->ops->dump_detail)
					server->ops->dump_detail(bufs[i],
								 server);
				cifs_dump_mids(server);
1290
#endif /* CIFS_DEBUG2 */
1291
			}
1292
		}
1293

1294 1295 1296 1297 1298 1299 1300 1301
		if (pdu_length > server->pdu_size) {
			if (!allocate_buffers(server))
				continue;
			pdu_length -= server->pdu_size;
			server->total_read = 0;
			server->large_buf = false;
			buf = server->smallbuf;
			goto next_pdu;
1302 1303 1304
		}
	} /* end while !EXITING */

1305
	/* buffer usually freed in free_mid - need to free it here on exit */
1306 1307 1308
	cifs_buf_release(server->bigbuf);
	if (server->smallbuf) /* no sense logging a debug message if NULL */
		cifs_small_buf_release(server->smallbuf);
L
Linus Torvalds 已提交
1309

1310
	task_to_wake = xchg(&server->tsk, NULL);
1311
	clean_demultiplex_info(server);
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322

	/* if server->tsk was NULL then wait for a signal before exiting */
	if (!task_to_wake) {
		set_current_state(TASK_INTERRUPTIBLE);
		while (!signal_pending(current)) {
			schedule();
			set_current_state(TASK_INTERRUPTIBLE);
		}
		set_current_state(TASK_RUNNING);
	}

1323
	module_put_and_exit(0);
L
Linus Torvalds 已提交
1324 1325
}

1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
/* extract the host portion of the UNC string */
static char *
extract_hostname(const char *unc)
{
	const char *src;
	char *dst, *delim;
	unsigned int len;

	/* skip double chars at beginning of string */
	/* BB: check validity of these bytes? */
1336 1337 1338 1339 1340 1341
	if (strlen(unc) < 3)
		return ERR_PTR(-EINVAL);
	for (src = unc; *src && *src == '\\'; src++)
		;
	if (!*src)
		return ERR_PTR(-EINVAL);
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358

	/* delimiter between hostname and sharename is always '\\' now */
	delim = strchr(src, '\\');
	if (!delim)
		return ERR_PTR(-EINVAL);

	len = delim - src;
	dst = kmalloc((len + 1), GFP_KERNEL);
	if (dst == NULL)
		return ERR_PTR(-ENOMEM);

	memcpy(dst, src, len);
	dst[len] = '\0';

	return dst;
}

1359 1360 1361 1362 1363 1364 1365 1366
static int get_option_ul(substring_t args[], unsigned long *option)
{
	int rc;
	char *string;

	string = match_strdup(args);
	if (string == NULL)
		return -ENOMEM;
1367
	rc = kstrtoul(string, 0, option);
1368 1369 1370 1371 1372
	kfree(string);

	return rc;
}

1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
static int get_option_uid(substring_t args[], kuid_t *result)
{
	unsigned long value;
	kuid_t uid;
	int rc;

	rc = get_option_ul(args, &value);
	if (rc)
		return rc;

	uid = make_kuid(current_user_ns(), value);
	if (!uid_valid(uid))
		return -EINVAL;

	*result = uid;
	return 0;
}

static int get_option_gid(substring_t args[], kgid_t *result)
{
	unsigned long value;
	kgid_t gid;
	int rc;

	rc = get_option_ul(args, &value);
	if (rc)
		return rc;

	gid = make_kgid(current_user_ns(), value);
	if (!gid_valid(gid))
		return -EINVAL;

	*result = gid;
	return 0;
}
1408 1409 1410 1411 1412 1413 1414

static int cifs_parse_security_flavors(char *value,
				       struct smb_vol *vol)
{

	substring_t args[MAX_OPT_ARGS];

1415 1416 1417 1418 1419 1420 1421
	/*
	 * With mount options, the last one should win. Reset any existing
	 * settings back to default.
	 */
	vol->sectype = Unspecified;
	vol->sign = false;

1422
	switch (match_token(value, cifs_secflavor_tokens, args)) {
1423 1424 1425 1426 1427 1428
	case Opt_sec_krb5p:
		cifs_dbg(VFS, "sec=krb5p is not supported!\n");
		return 1;
	case Opt_sec_krb5i:
		vol->sign = true;
		/* Fallthrough */
1429
	case Opt_sec_krb5:
1430
		vol->sectype = Kerberos;
1431
		break;
1432
	case Opt_sec_ntlmsspi:
1433
		vol->sign = true;
1434
		/* Fallthrough */
1435
	case Opt_sec_ntlmssp:
1436
		vol->sectype = RawNTLMSSP;
1437
		break;
1438
	case Opt_sec_ntlmi:
1439
		vol->sign = true;
1440
		/* Fallthrough */
1441
	case Opt_ntlm:
1442
		vol->sectype = NTLM;
1443
		break;
1444
	case Opt_sec_ntlmv2i:
1445
		vol->sign = true;
1446
		/* Fallthrough */
1447
	case Opt_sec_ntlmv2:
1448
		vol->sectype = NTLMv2;
1449 1450 1451
		break;
#ifdef CONFIG_CIFS_WEAK_PW_HASH
	case Opt_sec_lanman:
1452
		vol->sectype = LANMAN;
1453 1454 1455 1456 1457 1458
		break;
#endif
	case Opt_sec_none:
		vol->nullauth = 1;
		break;
	default:
1459
		cifs_dbg(VFS, "bad security option: %s\n", value);
1460 1461 1462 1463 1464 1465
		return 1;
	}

	return 0;
}

1466 1467 1468 1469 1470 1471 1472 1473 1474
static int
cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
{
	substring_t args[MAX_OPT_ARGS];

	switch (match_token(value, cifs_cacheflavor_tokens, args)) {
	case Opt_cache_loose:
		vol->direct_io = false;
		vol->strict_io = false;
1475
		vol->cache_ro = false;
1476
		vol->cache_rw = false;
1477 1478 1479 1480
		break;
	case Opt_cache_strict:
		vol->direct_io = false;
		vol->strict_io = true;
1481
		vol->cache_ro = false;
1482
		vol->cache_rw = false;
1483 1484 1485 1486
		break;
	case Opt_cache_none:
		vol->direct_io = true;
		vol->strict_io = false;
1487
		vol->cache_ro = false;
1488
		vol->cache_rw = false;
1489 1490 1491 1492 1493
		break;
	case Opt_cache_ro:
		vol->direct_io = false;
		vol->strict_io = false;
		vol->cache_ro = true;
1494 1495 1496 1497 1498 1499 1500
		vol->cache_rw = false;
		break;
	case Opt_cache_rw:
		vol->direct_io = false;
		vol->strict_io = false;
		vol->cache_ro = false;
		vol->cache_rw = true;
1501 1502
		break;
	default:
1503
		cifs_dbg(VFS, "bad cache= option: %s\n", value);
1504 1505 1506 1507 1508
		return 1;
	}
	return 0;
}

1509
static int
1510
cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
1511 1512 1513 1514
{
	substring_t args[MAX_OPT_ARGS];

	switch (match_token(value, cifs_smb_version_tokens, args)) {
1515
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
1516
	case Smb_1:
1517 1518 1519 1520
		if (disable_legacy_dialects) {
			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
			return 1;
		}
1521 1522 1523 1524
		if (is_smb3) {
			cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
			return 1;
		}
1525 1526 1527
		vol->ops = &smb1_operations;
		vol->vals = &smb1_values;
		break;
S
Steve French 已提交
1528
	case Smb_20:
1529 1530 1531 1532
		if (disable_legacy_dialects) {
			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
			return 1;
		}
1533 1534 1535 1536
		if (is_smb3) {
			cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
			return 1;
		}
1537
		vol->ops = &smb20_operations;
S
Steve French 已提交
1538 1539
		vol->vals = &smb20_values;
		break;
1540 1541 1542 1543 1544 1545 1546 1547
#else
	case Smb_1:
		cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
		return 1;
	case Smb_20:
		cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
		return 1;
#endif /* CIFS_ALLOW_INSECURE_LEGACY */
1548 1549 1550 1551
	case Smb_21:
		vol->ops = &smb21_operations;
		vol->vals = &smb21_values;
		break;
1552
	case Smb_30:
1553
		vol->ops = &smb30_operations;
1554 1555
		vol->vals = &smb30_values;
		break;
S
Steve French 已提交
1556 1557 1558 1559
	case Smb_302:
		vol->ops = &smb30_operations; /* currently identical with 3.0 */
		vol->vals = &smb302_values;
		break;
1560
	case Smb_311:
1561
		vol->ops = &smb311_operations;
1562 1563
		vol->vals = &smb311_values;
		break;
1564 1565 1566 1567 1568 1569 1570 1571
	case Smb_3any:
		vol->ops = &smb30_operations; /* currently identical with 3.0 */
		vol->vals = &smb3any_values;
		break;
	case Smb_default:
		vol->ops = &smb30_operations; /* currently identical with 3.0 */
		vol->vals = &smbdefault_values;
		break;
1572
	default:
1573
		cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
1574 1575 1576 1577 1578
		return 1;
	}
	return 0;
}

1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
/*
 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
 * fields with the result. Returns 0 on success and an error otherwise.
 */
static int
cifs_parse_devname(const char *devname, struct smb_vol *vol)
{
	char *pos;
	const char *delims = "/\\";
	size_t len;

1590 1591 1592 1593 1594
	if (unlikely(!devname || !*devname)) {
		cifs_dbg(VFS, "Device name not specified.\n");
		return -EINVAL;
	}

1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
	/* make sure we have a valid UNC double delimiter prefix */
	len = strspn(devname, delims);
	if (len != 2)
		return -EINVAL;

	/* find delimiter between host and sharename */
	pos = strpbrk(devname + 2, delims);
	if (!pos)
		return -EINVAL;

	/* skip past delimiter */
	++pos;

	/* now go until next delimiter or end of string */
	len = strcspn(pos, delims);

	/* move "pos" up to delimiter or NULL */
	pos += len;
	vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
	if (!vol->UNC)
		return -ENOMEM;

	convert_delimiter(vol->UNC, '\\');

1619 1620 1621 1622 1623 1624
	/* skip any delimiter */
	if (*pos == '/' || *pos == '\\')
		pos++;

	/* If pos is NULL then no prepath */
	if (!*pos)
1625 1626 1627 1628 1629 1630 1631 1632 1633
		return 0;

	vol->prepath = kstrdup(pos, GFP_KERNEL);
	if (!vol->prepath)
		return -ENOMEM;

	return 0;
}

L
Linus Torvalds 已提交
1634
static int
1635
cifs_parse_mount_options(const char *mountdata, const char *devname,
1636
			 struct smb_vol *vol, bool is_smb3)
L
Linus Torvalds 已提交
1637
{
1638
	char *data, *end;
1639
	char *mountdata_copy = NULL, *options;
L
Linus Torvalds 已提交
1640 1641
	unsigned int  temp_len, i, j;
	char separator[2];
1642 1643 1644 1645
	short int override_uid = -1;
	short int override_gid = -1;
	bool uid_specified = false;
	bool gid_specified = false;
1646 1647
	bool sloppy = false;
	char *invalid = NULL;
J
Jeff Layton 已提交
1648
	char *nodename = utsname()->nodename;
1649 1650 1651
	char *string = NULL;
	char *tmp_end, *value;
	char delim;
1652
	bool got_ip = false;
1653
	bool got_version = false;
1654 1655
	unsigned short port = 0;
	struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
L
Linus Torvalds 已提交
1656 1657

	separator[0] = ',';
1658
	separator[1] = 0;
1659
	delim = separator[0];
L
Linus Torvalds 已提交
1660

1661 1662 1663
	/* ensure we always start with zeroed-out smb_vol */
	memset(vol, 0, sizeof(*vol));

J
Jeff Layton 已提交
1664 1665 1666 1667 1668
	/*
	 * does not have to be perfect mapping since field is
	 * informational, only used for servers that do not support
	 * port 445 and it can be overridden at mount time
	 */
1669 1670
	memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
	for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
J
Jeff Layton 已提交
1671 1672
		vol->source_rfc1001_name[i] = toupper(nodename[i]);

1673
	vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1674 1675 1676
	/* null target name indicates to use *SMBSERVR default called name
	   if we end up sending RFC1001 session initialize */
	vol->target_rfc1001_name[0] = 0;
1677 1678
	vol->cred_uid = current_uid();
	vol->linux_uid = current_uid();
1679
	vol->linux_gid = current_gid();
1680
	vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
1681 1682 1683 1684 1685 1686 1687 1688
	/*
	 * default to SFM style remapping of seven reserved characters
	 * unless user overrides it or we negotiate CIFS POSIX where
	 * it is unnecessary.  Can not simultaneously use more than one mapping
	 * since then readdir could list files that open could not open
	 */
	vol->remap = true;

1689 1690
	/* default to only allowing write access to owner of the mount */
	vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
L
Linus Torvalds 已提交
1691 1692

	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1693 1694
	/* default is always to request posix paths. */
	vol->posix_paths = 1;
1695 1696
	/* default to using server inode numbers where available */
	vol->server_ino = 1;
1697

1698 1699 1700
	/* default is to use strict cifs caching semantics */
	vol->strict_io = true;

1701 1702
	vol->actimeo = CIFS_DEF_ACTIMEO;

1703 1704 1705
	/* Most clients set timeout to 0, allows server to use its default */
	vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */

1706 1707 1708
	/* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
	vol->ops = &smb30_operations;
	vol->vals = &smbdefault_values;
1709

R
Rabin Vincent 已提交
1710 1711
	vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;

1712 1713 1714 1715
	/* default to no multichannel (single server connection) */
	vol->multichannel = false;
	vol->max_channels = 1;

1716 1717 1718 1719 1720 1721
	if (!mountdata)
		goto cifs_parse_mount_err;

	mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
	if (!mountdata_copy)
		goto cifs_parse_mount_err;
L
Linus Torvalds 已提交
1722

1723
	options = mountdata_copy;
1724
	end = options + strlen(options);
1725

1726
	if (strncmp(options, "sep=", 4) == 0) {
S
Steve French 已提交
1727
		if (options[4] != 0) {
L
Linus Torvalds 已提交
1728 1729 1730
			separator[0] = options[4];
			options += 5;
		} else {
1731
			cifs_dbg(FYI, "Null separator not allowed\n");
L
Linus Torvalds 已提交
1732 1733
		}
	}
1734 1735
	vol->backupuid_specified = false; /* no backup intent for a user */
	vol->backupgid_specified = false; /* no backup intent for a group */
1736

1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748
	switch (cifs_parse_devname(devname, vol)) {
	case 0:
		break;
	case -ENOMEM:
		cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
		goto cifs_parse_mount_err;
	case -EINVAL:
		cifs_dbg(VFS, "Malformed UNC in devname.\n");
		goto cifs_parse_mount_err;
	default:
		cifs_dbg(VFS, "Unknown error parsing devname.\n");
		goto cifs_parse_mount_err;
1749 1750
	}

L
Linus Torvalds 已提交
1751
	while ((data = strsep(&options, separator)) != NULL) {
1752 1753 1754 1755
		substring_t args[MAX_OPT_ARGS];
		unsigned long option;
		int token;

L
Linus Torvalds 已提交
1756 1757 1758
		if (!*data)
			continue;

1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
		token = match_token(data, cifs_mount_option_tokens, args);

		switch (token) {

		/* Ingnore the following */
		case Opt_ignore:
			break;

		/* Boolean values */
		case Opt_user_xattr:
L
Linus Torvalds 已提交
1769
			vol->no_xattr = 0;
1770 1771
			break;
		case Opt_nouser_xattr:
L
Linus Torvalds 已提交
1772
			vol->no_xattr = 1;
1773 1774
			break;
		case Opt_forceuid:
1775
			override_uid = 1;
1776 1777
			break;
		case Opt_noforceuid:
1778
			override_uid = 0;
1779
			break;
J
Jeff Layton 已提交
1780 1781 1782 1783 1784 1785
		case Opt_forcegid:
			override_gid = 1;
			break;
		case Opt_noforcegid:
			override_gid = 0;
			break;
1786
		case Opt_noblocksend:
1787
			vol->noblocksnd = 1;
1788 1789
			break;
		case Opt_noautotune:
1790
			vol->noautotune = 1;
1791
			break;
1792 1793 1794
		case Opt_nolease:
			vol->no_lease = 1;
			break;
1795
		case Opt_hard:
L
Linus Torvalds 已提交
1796
			vol->retry = 1;
1797 1798
			break;
		case Opt_soft:
L
Linus Torvalds 已提交
1799
			vol->retry = 0;
1800 1801
			break;
		case Opt_perm:
L
Linus Torvalds 已提交
1802
			vol->noperm = 0;
1803 1804
			break;
		case Opt_noperm:
L
Linus Torvalds 已提交
1805
			vol->noperm = 1;
1806 1807
			break;
		case Opt_mapchars:
1808 1809
			vol->sfu_remap = true;
			vol->remap = false; /* disable SFM mapping */
1810 1811
			break;
		case Opt_nomapchars:
1812 1813 1814 1815 1816 1817 1818 1819
			vol->sfu_remap = false;
			break;
		case Opt_mapposix:
			vol->remap = true;
			vol->sfu_remap = false; /* disable SFU mapping */
			break;
		case Opt_nomapposix:
			vol->remap = false;
1820 1821
			break;
		case Opt_sfu:
1822
			vol->sfu_emul = 1;
1823 1824
			break;
		case Opt_nosfu:
1825
			vol->sfu_emul = 0;
1826 1827
			break;
		case Opt_nodfs:
S
Steve French 已提交
1828
			vol->nodfs = 1;
1829
			break;
1830 1831 1832 1833 1834
		case Opt_rootfs:
#ifdef CONFIG_CIFS_ROOT
			vol->rootfs = true;
#endif
			break;
1835
		case Opt_posixpaths:
1836
			vol->posix_paths = 1;
1837 1838
			break;
		case Opt_noposixpaths:
1839
			vol->posix_paths = 0;
1840 1841
			break;
		case Opt_nounix:
1842 1843 1844
			if (vol->linux_ext)
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
1845
			vol->no_linux_ext = 1;
1846
			break;
1847 1848 1849 1850 1851 1852
		case Opt_unix:
			if (vol->no_linux_ext)
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
			vol->linux_ext = 1;
			break;
1853
		case Opt_nocase:
1854
			vol->nocase = 1;
1855 1856
			break;
		case Opt_brl:
1857
			vol->nobrl =  0;
1858 1859
			break;
		case Opt_nobrl:
1860
			vol->nobrl =  1;
1861 1862
			/*
			 * turn off mandatory locking in mode
1863
			 * if remote locking is turned off since the
1864 1865
			 * local vfs will do advisory
			 */
1866 1867
			if (vol->file_mode ==
				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1868
				vol->file_mode = S_IALLUGO;
1869
			break;
S
Steve French 已提交
1870 1871 1872 1873 1874 1875
		case Opt_nohandlecache:
			vol->nohandlecache = 1;
			break;
		case Opt_handlecache:
			vol->nohandlecache = 0;
			break;
1876
		case Opt_forcemandatorylock:
1877
			vol->mand_lock = 1;
1878 1879
			break;
		case Opt_setuids:
L
Linus Torvalds 已提交
1880
			vol->setuids = 1;
1881 1882
			break;
		case Opt_nosetuids:
L
Linus Torvalds 已提交
1883
			vol->setuids = 0;
1884
			break;
1885 1886 1887
		case Opt_setuidfromacl:
			vol->setuidfromacl = 1;
			break;
1888
		case Opt_dynperm:
1889
			vol->dynperm = true;
1890 1891
			break;
		case Opt_nodynperm:
1892
			vol->dynperm = false;
1893 1894
			break;
		case Opt_nohard:
L
Linus Torvalds 已提交
1895
			vol->retry = 0;
1896 1897
			break;
		case Opt_nosoft:
L
Linus Torvalds 已提交
1898
			vol->retry = 1;
1899 1900
			break;
		case Opt_nointr:
L
Linus Torvalds 已提交
1901
			vol->intr = 0;
1902 1903
			break;
		case Opt_intr:
L
Linus Torvalds 已提交
1904
			vol->intr = 1;
1905 1906
			break;
		case Opt_nostrictsync:
1907
			vol->nostrictsync = 1;
1908 1909
			break;
		case Opt_strictsync:
1910
			vol->nostrictsync = 0;
1911 1912
			break;
		case Opt_serverino:
L
Linus Torvalds 已提交
1913
			vol->server_ino = 1;
1914 1915
			break;
		case Opt_noserverino:
L
Linus Torvalds 已提交
1916
			vol->server_ino = 0;
1917 1918
			break;
		case Opt_rwpidforward:
1919
			vol->rwpidforward = 1;
1920
			break;
1921 1922 1923
		case Opt_modesid:
			vol->mode_ace = 1;
			break;
1924
		case Opt_cifsacl:
1925
			vol->cifs_acl = 1;
1926 1927
			break;
		case Opt_nocifsacl:
1928
			vol->cifs_acl = 0;
1929 1930
			break;
		case Opt_acl:
L
Linus Torvalds 已提交
1931
			vol->no_psx_acl = 0;
1932 1933
			break;
		case Opt_noacl:
L
Linus Torvalds 已提交
1934
			vol->no_psx_acl = 1;
1935 1936
			break;
		case Opt_locallease:
S
Steve French 已提交
1937
			vol->local_lease = 1;
1938 1939
			break;
		case Opt_sign:
1940
			vol->sign = true;
1941
			break;
1942 1943 1944 1945
		case Opt_ignore_signature:
			vol->sign = true;
			vol->ignore_signature = true;
			break;
1946
		case Opt_seal:
1947
			/* we do not do the following in secFlags because seal
1948 1949 1950 1951
			 * is a per tree connection (mount) not a per socket
			 * or per-smb connection option in the protocol
			 * vol->secFlg |= CIFSSEC_MUST_SEAL;
			 */
1952
			vol->seal = 1;
1953 1954
			break;
		case Opt_noac:
1955
			pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1956 1957
			break;
		case Opt_fsc:
1958
#ifndef CONFIG_CIFS_FSCACHE
1959
			cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1960
			goto cifs_parse_mount_err;
1961
#endif
1962
			vol->fsc = true;
1963 1964
			break;
		case Opt_mfsymlinks:
1965
			vol->mfsymlinks = true;
1966 1967
			break;
		case Opt_multiuser:
J
Jeff Layton 已提交
1968
			vol->multiuser = true;
1969
			break;
1970 1971 1972
		case Opt_sloppy:
			sloppy = true;
			break;
1973 1974 1975
		case Opt_nosharesock:
			vol->nosharesock = true;
			break;
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
		case Opt_nopersistent:
			vol->nopersistent = true;
			if (vol->persistent) {
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_persistent:
			vol->persistent = true;
S
Steve French 已提交
1986
			if ((vol->nopersistent) || (vol->resilient)) {
1987 1988 1989 1990 1991
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
S
Steve French 已提交
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
		case Opt_resilient:
			vol->resilient = true;
			if (vol->persistent) {
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_noresilient:
			vol->resilient = false; /* already the default */
			break;
2003 2004 2005
		case Opt_domainauto:
			vol->domainauto = true;
			break;
L
Long Li 已提交
2006 2007 2008
		case Opt_rdma:
			vol->rdma = true;
			break;
2009 2010 2011 2012 2013 2014
		case Opt_multichannel:
			vol->multichannel = true;
			break;
		case Opt_nomultichannel:
			vol->multichannel = false;
			break;
2015 2016 2017 2018 2019
		case Opt_compress:
			vol->compression = UNKNOWN_TYPE;
			cifs_dbg(VFS,
				"SMB3 compression support is experimental\n");
			break;
2020 2021 2022

		/* Numeric Values */
		case Opt_backupuid:
2023
			if (get_option_uid(args, &vol->backupuid)) {
2024 2025
				cifs_dbg(VFS, "%s: Invalid backupuid value\n",
					 __func__);
2026 2027 2028
				goto cifs_parse_mount_err;
			}
			vol->backupuid_specified = true;
2029 2030
			break;
		case Opt_backupgid:
2031
			if (get_option_gid(args, &vol->backupgid)) {
2032 2033
				cifs_dbg(VFS, "%s: Invalid backupgid value\n",
					 __func__);
2034 2035 2036
				goto cifs_parse_mount_err;
			}
			vol->backupgid_specified = true;
2037 2038
			break;
		case Opt_uid:
2039
			if (get_option_uid(args, &vol->linux_uid)) {
2040 2041
				cifs_dbg(VFS, "%s: Invalid uid value\n",
					 __func__);
2042 2043 2044 2045 2046
				goto cifs_parse_mount_err;
			}
			uid_specified = true;
			break;
		case Opt_cruid:
2047
			if (get_option_uid(args, &vol->cred_uid)) {
2048 2049
				cifs_dbg(VFS, "%s: Invalid cruid value\n",
					 __func__);
2050 2051 2052 2053
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_gid:
2054
			if (get_option_gid(args, &vol->linux_gid)) {
2055 2056
				cifs_dbg(VFS, "%s: Invalid gid value\n",
					 __func__);
2057 2058 2059 2060 2061 2062
				goto cifs_parse_mount_err;
			}
			gid_specified = true;
			break;
		case Opt_file_mode:
			if (get_option_ul(args, &option)) {
2063 2064
				cifs_dbg(VFS, "%s: Invalid file_mode value\n",
					 __func__);
2065 2066 2067 2068 2069 2070
				goto cifs_parse_mount_err;
			}
			vol->file_mode = option;
			break;
		case Opt_dirmode:
			if (get_option_ul(args, &option)) {
2071 2072
				cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
					 __func__);
2073 2074 2075 2076 2077
				goto cifs_parse_mount_err;
			}
			vol->dir_mode = option;
			break;
		case Opt_port:
2078 2079
			if (get_option_ul(args, &option) ||
			    option > USHRT_MAX) {
2080 2081
				cifs_dbg(VFS, "%s: Invalid port value\n",
					 __func__);
2082 2083
				goto cifs_parse_mount_err;
			}
2084
			port = (unsigned short)option;
2085
			break;
2086 2087 2088 2089 2090 2091 2092
		case Opt_min_enc_offload:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
				goto cifs_parse_mount_err;
			}
			vol->min_offload = option;
			break;
2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112
		case Opt_blocksize:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid blocksize value\n",
					__func__);
				goto cifs_parse_mount_err;
			}
			/*
			 * inode blocksize realistically should never need to be
			 * less than 16K or greater than 16M and default is 1MB.
			 * Note that small inode block sizes (e.g. 64K) can lead
			 * to very poor performance of common tools like cp and scp
			 */
			if ((option < CIFS_MAX_MSGSIZE) ||
			   (option > (4 * SMB3_DEFAULT_IOSIZE))) {
				cifs_dbg(VFS, "%s: Invalid blocksize\n",
					__func__);
				goto cifs_parse_mount_err;
			}
			vol->bsize = option;
			break;
2113 2114
		case Opt_rsize:
			if (get_option_ul(args, &option)) {
2115 2116
				cifs_dbg(VFS, "%s: Invalid rsize value\n",
					 __func__);
2117
				goto cifs_parse_mount_err;
2118 2119 2120 2121 2122
			}
			vol->rsize = option;
			break;
		case Opt_wsize:
			if (get_option_ul(args, &option)) {
2123 2124
				cifs_dbg(VFS, "%s: Invalid wsize value\n",
					 __func__);
2125 2126 2127 2128 2129 2130
				goto cifs_parse_mount_err;
			}
			vol->wsize = option;
			break;
		case Opt_actimeo:
			if (get_option_ul(args, &option)) {
2131 2132
				cifs_dbg(VFS, "%s: Invalid actimeo value\n",
					 __func__);
2133 2134 2135 2136
				goto cifs_parse_mount_err;
			}
			vol->actimeo = HZ * option;
			if (vol->actimeo > CIFS_MAX_ACTIMEO) {
2137
				cifs_dbg(VFS, "attribute cache timeout too large\n");
2138 2139 2140
				goto cifs_parse_mount_err;
			}
			break;
2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152
		case Opt_handletimeout:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
			vol->handle_timeout = option;
			if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
				cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
				goto cifs_parse_mount_err;
			}
			break;
S
Steve French 已提交
2153 2154 2155 2156 2157 2158 2159 2160
		case Opt_echo_interval:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid echo interval value\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
			vol->echo_interval = option;
			break;
2161 2162 2163 2164 2165 2166 2167 2168
		case Opt_snapshot:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid snapshot time\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
			vol->snapshot_time = option;
			break;
2169 2170 2171 2172 2173 2174 2175 2176 2177
		case Opt_max_credits:
			if (get_option_ul(args, &option) || (option < 20) ||
			    (option > 60000)) {
				cifs_dbg(VFS, "%s: Invalid max_credits value\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
			vol->max_credits = option;
			break;
2178 2179 2180 2181 2182 2183 2184 2185 2186
		case Opt_max_channels:
			if (get_option_ul(args, &option) || option < 1 ||
				option > CIFS_MAX_CHANNELS) {
				cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
					 __func__, CIFS_MAX_CHANNELS);
				goto cifs_parse_mount_err;
			}
			vol->max_channels = option;
			break;
2187 2188 2189

		/* String Arguments */

2190 2191 2192 2193 2194
		case Opt_blank_user:
			/* null user, ie. anonymous authentication */
			vol->nullauth = 1;
			vol->username = NULL;
			break;
2195 2196 2197 2198 2199
		case Opt_user:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2200 2201
			if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
							CIFS_MAX_USERNAME_LEN) {
2202
				pr_warn("CIFS: username too long\n");
2203 2204
				goto cifs_parse_mount_err;
			}
2205 2206

			kfree(vol->username);
2207
			vol->username = kstrdup(string, GFP_KERNEL);
2208
			if (!vol->username)
2209 2210 2211 2212 2213 2214 2215 2216
				goto cifs_parse_mount_err;
			break;
		case Opt_blank_pass:
			/* passwords have to be handled differently
			 * to allow the character used for deliminator
			 * to be passed within them
			 */

2217 2218 2219 2220 2221 2222 2223 2224
			/*
			 * Check if this is a case where the  password
			 * starts with a delimiter
			 */
			tmp_end = strchr(data, '=');
			tmp_end++;
			if (!(tmp_end < end && tmp_end[1] == delim)) {
				/* No it is not. Set the password to NULL */
2225
				kzfree(vol->password);
2226 2227 2228
				vol->password = NULL;
				break;
			}
2229
			/* Fallthrough - to Opt_pass below.*/
2230
		case Opt_pass:
2231 2232
			/* Obtain the value string */
			value = strchr(data, '=');
2233
			value++;
2234 2235 2236 2237 2238 2239 2240 2241

			/* Set tmp_end to end of the string */
			tmp_end = (char *) value + strlen(value);

			/* Check if following character is the deliminator
			 * If yes, we have encountered a double deliminator
			 * reset the NULL character to the deliminator
			 */
2242
			if (tmp_end < end && tmp_end[1] == delim) {
2243 2244
				tmp_end[0] = delim;

2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260
				/* Keep iterating until we get to a single
				 * deliminator OR the end
				 */
				while ((tmp_end = strchr(tmp_end, delim))
					!= NULL && (tmp_end[1] == delim)) {
						tmp_end = (char *) &tmp_end[2];
				}

				/* Reset var options to point to next element */
				if (tmp_end) {
					tmp_end[0] = '\0';
					options = (char *) &tmp_end[1];
				} else
					/* Reached the end of the mount option
					 * string */
					options = end;
2261 2262
			}

2263
			kzfree(vol->password);
2264 2265 2266 2267
			/* Now build new password string */
			temp_len = strlen(value);
			vol->password = kzalloc(temp_len+1, GFP_KERNEL);
			if (vol->password == NULL) {
2268
				pr_warn("CIFS: no memory for password\n");
2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280
				goto cifs_parse_mount_err;
			}

			for (i = 0, j = 0; i < temp_len; i++, j++) {
				vol->password[j] = value[i];
				if ((value[i] == delim) &&
				     value[i+1] == delim)
					/* skip the second deliminator */
					i++;
			}
			vol->password[j] = '\0';
			break;
2281
		case Opt_blank_ip:
2282 2283
			/* FIXME: should this be an error instead? */
			got_ip = false;
2284
			break;
2285 2286 2287 2288 2289
		case Opt_ip:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2290 2291
			if (!cifs_convert_address(dstaddr, string,
					strlen(string))) {
2292
				pr_err("CIFS: bad ip= option (%s).\n", string);
2293 2294
				goto cifs_parse_mount_err;
			}
2295
			got_ip = true;
2296 2297 2298 2299 2300 2301
			break;
		case Opt_domain:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2302 2303
			if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
					== CIFS_MAX_DOMAINNAME_LEN) {
2304
				pr_warn("CIFS: domain name too long\n");
2305 2306 2307
				goto cifs_parse_mount_err;
			}

2308
			kfree(vol->domainname);
2309 2310
			vol->domainname = kstrdup(string, GFP_KERNEL);
			if (!vol->domainname) {
2311
				pr_warn("CIFS: no memory for domainname\n");
2312 2313
				goto cifs_parse_mount_err;
			}
2314
			cifs_dbg(FYI, "Domain name set\n");
2315 2316 2317 2318 2319 2320
			break;
		case Opt_srcaddr:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2321
			if (!cifs_convert_address(
2322 2323
					(struct sockaddr *)&vol->srcaddr,
					string, strlen(string))) {
2324 2325
				pr_warn("CIFS: Could not parse srcaddr: %s\n",
					string);
2326 2327 2328 2329 2330 2331 2332 2333
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_iocharset:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2334
			if (strnlen(string, 1024) >= 65) {
2335
				pr_warn("CIFS: iocharset name too long.\n");
2336 2337 2338
				goto cifs_parse_mount_err;
			}

2339
			 if (strncasecmp(string, "default", 7) != 0) {
2340
				kfree(vol->iocharset);
2341 2342 2343
				vol->iocharset = kstrdup(string,
							 GFP_KERNEL);
				if (!vol->iocharset) {
2344
					pr_warn("CIFS: no memory for charset\n");
2345 2346 2347 2348 2349 2350
					goto cifs_parse_mount_err;
				}
			}
			/* if iocharset not set then load_nls_default
			 * is used by caller
			 */
2351
			 cifs_dbg(FYI, "iocharset set to %s\n", string);
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374
			break;
		case Opt_netbiosname:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			memset(vol->source_rfc1001_name, 0x20,
				RFC1001_NAME_LEN);
			/*
			 * FIXME: are there cases in which a comma can
			 * be valid in workstation netbios name (and
			 * need special handling)?
			 */
			for (i = 0; i < RFC1001_NAME_LEN; i++) {
				/* don't ucase netbiosname for user */
				if (string[i] == 0)
					break;
				vol->source_rfc1001_name[i] = string[i];
			}
			/* The string has 16th byte zero still from
			 * set at top of the function
			 */
			if (i == RFC1001_NAME_LEN && string[i] != 0)
2375
				pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400
			break;
		case Opt_servern:
			/* servernetbiosname specified override *SMBSERVER */
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			/* last byte, type, is 0x20 for servr type */
			memset(vol->target_rfc1001_name, 0x20,
				RFC1001_NAME_LEN_WITH_NULL);

			/* BB are there cases in which a comma can be
			   valid in this workstation netbios name
			   (and need special handling)? */

			/* user or mount helper must uppercase the
			   netbios name */
			for (i = 0; i < 15; i++) {
				if (string[i] == 0)
					break;
				vol->target_rfc1001_name[i] = string[i];
			}
			/* The string has 16th byte zero still from
			   set at top of the function  */
			if (i == RFC1001_NAME_LEN && string[i] != 0)
2401
				pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
2402 2403
			break;
		case Opt_ver:
2404
			/* version of mount userspace tools, not dialect */
2405 2406 2407 2408
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2409
			/* If interface changes in mount.cifs bump to new ver */
2410
			if (strncasecmp(string, "1", 1) == 0) {
2411 2412 2413 2414 2415 2416 2417
				if (strlen(string) > 1) {
					pr_warn("Bad mount helper ver=%s. Did "
						"you want SMB1 (CIFS) dialect "
						"and mean to type vers=1.0 "
						"instead?\n", string);
					goto cifs_parse_mount_err;
				}
2418 2419 2420 2421
				/* This is the default */
				break;
			}
			/* For all other value, error */
2422
			pr_warn("CIFS: Invalid mount helper version specified\n");
2423
			goto cifs_parse_mount_err;
2424
		case Opt_vers:
2425
			/* protocol version (dialect) */
2426 2427 2428 2429
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2430
			if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
2431
				goto cifs_parse_mount_err;
2432
			got_version = true;
2433
			break;
2434 2435 2436 2437 2438 2439 2440 2441
		case Opt_sec:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			if (cifs_parse_security_flavors(string, vol) != 0)
				goto cifs_parse_mount_err;
			break;
2442 2443 2444 2445 2446 2447 2448 2449
		case Opt_cache:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			if (cifs_parse_cache_flavor(string, vol) != 0)
				goto cifs_parse_mount_err;
			break;
2450
		default:
2451 2452 2453 2454 2455 2456
			/*
			 * An option we don't recognize. Save it off for later
			 * if we haven't already found one
			 */
			if (!invalid)
				invalid = data;
2457
			break;
L
Linus Torvalds 已提交
2458
		}
2459 2460 2461
		/* Free up any allocated string */
		kfree(string);
		string = NULL;
L
Linus Torvalds 已提交
2462
	}
J
Jeff Layton 已提交
2463

2464
	if (!sloppy && invalid) {
2465
		pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
2466 2467 2468
		goto cifs_parse_mount_err;
	}

L
Long Li 已提交
2469 2470 2471 2472 2473
	if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
		cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
		goto cifs_parse_mount_err;
	}

2474 2475 2476
#ifndef CONFIG_KEYS
	/* Muliuser mounts require CONFIG_KEYS support */
	if (vol->multiuser) {
2477
		cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
2478
		goto cifs_parse_mount_err;
J
Jeff Layton 已提交
2479
	}
2480
#endif
2481
	if (!vol->UNC) {
2482
		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
2483 2484
		goto cifs_parse_mount_err;
	}
J
Jeff Layton 已提交
2485

2486 2487
	/* make sure UNC has a share name */
	if (!strchr(vol->UNC + 3, '\\')) {
2488
		cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
2489 2490 2491
		goto cifs_parse_mount_err;
	}

2492
	if (!got_ip) {
2493 2494 2495
		int len;
		const char *slash;

2496
		/* No ip= option specified? Try to get it from UNC */
2497 2498 2499 2500
		/* Use the address part of the UNC. */
		slash = strchr(&vol->UNC[2], '\\');
		len = slash - &vol->UNC[2];
		if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
2501
			pr_err("Unable to determine destination address.\n");
2502 2503 2504 2505 2506 2507
			goto cifs_parse_mount_err;
		}
	}

	/* set the port that we got earlier */
	cifs_set_port(dstaddr, port);
L
Linus Torvalds 已提交
2508

2509 2510 2511
	if (uid_specified)
		vol->override_uid = override_uid;
	else if (override_uid == 1)
2512
		pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
2513 2514 2515 2516

	if (gid_specified)
		vol->override_gid = override_gid;
	else if (override_gid == 1)
2517
		pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
2518

2519 2520
	if (got_version == false)
		pr_warn("No dialect specified on mount. Default has changed to "
2521
			"a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
2522
			"(SMB1). To use the less secure SMB1 dialect to access "
2523 2524
			"old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
			" on mount.\n");
2525

2526
	kfree(mountdata_copy);
L
Linus Torvalds 已提交
2527
	return 0;
2528

2529
out_nomem:
2530
	pr_warn("Could not allocate temporary buffer\n");
2531
cifs_parse_mount_err:
2532
	kfree(string);
2533 2534
	kfree(mountdata_copy);
	return 1;
L
Linus Torvalds 已提交
2535 2536
}

2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553
/** Returns true if srcaddr isn't specified and rhs isn't
 * specified, or if srcaddr is specified and
 * matches the IP address of the rhs argument.
 */
static bool
srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
{
	switch (srcaddr->sa_family) {
	case AF_UNSPEC:
		return (rhs->sa_family == AF_UNSPEC);
	case AF_INET: {
		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
	}
	case AF_INET6: {
		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
2554
		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
2555 2556 2557 2558 2559 2560 2561 2562
		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
	}
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
}

2563 2564 2565 2566 2567 2568 2569 2570
/*
 * If no port is specified in addr structure, we try to match with 445 port
 * and if it fails - with 139 ports. It should be called only if address
 * families of server and addr are equal.
 */
static bool
match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
{
2571
	__be16 port, *sport;
2572

2573 2574 2575 2576
	/* SMBDirect manages its own ports, don't match it here */
	if (server->rdma)
		return true;

2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600
	switch (addr->sa_family) {
	case AF_INET:
		sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
		port = ((struct sockaddr_in *) addr)->sin_port;
		break;
	case AF_INET6:
		sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
		port = ((struct sockaddr_in6 *) addr)->sin6_port;
		break;
	default:
		WARN_ON(1);
		return false;
	}

	if (!port) {
		port = htons(CIFS_PORT);
		if (port == *sport)
			return true;

		port = htons(RFC1001_PORT);
	}

	return port == *sport;
}
2601

2602
static bool
2603 2604
match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
	      struct sockaddr *srcaddr)
2605 2606
{
	switch (addr->sa_family) {
2607 2608 2609 2610 2611 2612
	case AF_INET: {
		struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
		struct sockaddr_in *srv_addr4 =
					(struct sockaddr_in *)&server->dstaddr;

		if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
2613 2614
			return false;
		break;
2615 2616 2617 2618 2619 2620
	}
	case AF_INET6: {
		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
		struct sockaddr_in6 *srv_addr6 =
					(struct sockaddr_in6 *)&server->dstaddr;

2621
		if (!ipv6_addr_equal(&addr6->sin6_addr,
2622
				     &srv_addr6->sin6_addr))
2623
			return false;
2624
		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
2625 2626 2627
			return false;
		break;
	}
2628 2629 2630 2631
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
2632

2633 2634 2635
	if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
		return false;

2636 2637 2638
	return true;
}

2639 2640 2641
static bool
match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
{
2642 2643 2644 2645 2646
	/*
	 * The select_sectype function should either return the vol->sectype
	 * that was specified, or "Unspecified" if that sectype was not
	 * compatible with the given NEGOTIATE request.
	 */
S
Sachin Prabhu 已提交
2647 2648
	if (server->ops->select_sectype(server, vol->sectype)
	     == Unspecified)
2649 2650
		return false;

2651 2652 2653 2654 2655
	/*
	 * Now check if signing mode is acceptable. No need to check
	 * global_secflags at this point since if MUST_SIGN is set then
	 * the server->sign had better be too.
	 */
2656 2657
	if (vol->sign && !server->sign)
		return false;
2658 2659 2660 2661

	return true;
}

2662
static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
2663
{
2664 2665
	struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;

2666 2667 2668
	if (vol->nosharesock)
		return 0;

2669 2670 2671 2672 2673 2674 2675 2676 2677
	/* If multidialect negotiation see if existing sessions match one */
	if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
		if (server->vals->protocol_id < SMB30_PROT_ID)
			return 0;
	} else if (strcmp(vol->vals->version_string,
		   SMBDEFAULT_VERSION_STRING) == 0) {
		if (server->vals->protocol_id < SMB21_PROT_ID)
			return 0;
	} else if ((server->vals != vol->vals) || (server->ops != vol->ops))
2678 2679
		return 0;

2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692
	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
		return 0;

	if (!match_address(server, addr,
			   (struct sockaddr *)&vol->srcaddr))
		return 0;

	if (!match_port(server, addr))
		return 0;

	if (!match_security(server, vol))
		return 0;

R
Rabin Vincent 已提交
2693
	if (server->echo_interval != vol->echo_interval * HZ)
S
Steve French 已提交
2694 2695
		return 0;

L
Long Li 已提交
2696 2697 2698
	if (server->rdma != vol->rdma)
		return 0;

2699 2700 2701
	if (server->ignore_signature != vol->ignore_signature)
		return 0;

2702 2703 2704
	if (server->min_offload != vol->min_offload)
		return 0;

2705 2706 2707
	return 1;
}

P
Paulo Alcantara 已提交
2708
struct TCP_Server_Info *
2709
cifs_find_tcp_session(struct smb_vol *vol)
L
Linus Torvalds 已提交
2710
{
2711 2712
	struct TCP_Server_Info *server;

2713
	spin_lock(&cifs_tcp_ses_lock);
2714
	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
2715 2716 2717 2718 2719
		/*
		 * Skip ses channels since they're only handled in lower layers
		 * (e.g. cifs_send_recv).
		 */
		if (server->is_channel || !match_server(server, vol))
2720 2721
			continue;

2722
		++server->srv_count;
2723
		spin_unlock(&cifs_tcp_ses_lock);
2724
		cifs_dbg(FYI, "Existing tcp session with server found\n");
2725
		return server;
L
Linus Torvalds 已提交
2726
	}
2727
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
2728 2729
	return NULL;
}
2730

2731 2732
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
L
Linus Torvalds 已提交
2733
{
2734 2735
	struct task_struct *task;

2736
	spin_lock(&cifs_tcp_ses_lock);
2737
	if (--server->srv_count > 0) {
2738
		spin_unlock(&cifs_tcp_ses_lock);
2739
		return;
L
Linus Torvalds 已提交
2740
	}
2741

2742 2743
	put_net(cifs_net_ns(server));

2744
	list_del_init(&server->tcp_ses_list);
2745
	spin_unlock(&cifs_tcp_ses_lock);
2746

2747 2748
	cancel_delayed_work_sync(&server->echo);

2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759
	if (from_reconnect)
		/*
		 * Avoid deadlock here: reconnect work calls
		 * cifs_put_tcp_session() at its end. Need to be sure
		 * that reconnect work does nothing with server pointer after
		 * that step.
		 */
		cancel_delayed_work(&server->reconnect);
	else
		cancel_delayed_work_sync(&server->reconnect);

2760 2761 2762
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
2763

2764
	cifs_crypto_secmech_release(server);
2765 2766
	cifs_fscache_release_client_cookie(server);

2767 2768 2769
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
2770 2771 2772

	task = xchg(&server->tsk, NULL);
	if (task)
2773
		send_sig(SIGKILL, task, 1);
L
Linus Torvalds 已提交
2774 2775
}

2776
struct TCP_Server_Info *
2777 2778 2779 2780 2781
cifs_get_tcp_session(struct smb_vol *volume_info)
{
	struct TCP_Server_Info *tcp_ses = NULL;
	int rc;

2782
	cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
2783 2784

	/* see if we already have a matching tcp_ses */
2785
	tcp_ses = cifs_find_tcp_session(volume_info);
2786 2787 2788 2789 2790 2791 2792 2793 2794
	if (tcp_ses)
		return tcp_ses;

	tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
	if (!tcp_ses) {
		rc = -ENOMEM;
		goto out_err;
	}

2795 2796
	tcp_ses->ops = volume_info->ops;
	tcp_ses->vals = volume_info->vals;
2797
	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
2798 2799 2800
	tcp_ses->hostname = extract_hostname(volume_info->UNC);
	if (IS_ERR(tcp_ses->hostname)) {
		rc = PTR_ERR(tcp_ses->hostname);
2801
		goto out_err_crypto_release;
2802 2803
	}

2804 2805
	tcp_ses->noblockcnt = volume_info->rootfs;
	tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
2806
	tcp_ses->noautotune = volume_info->noautotune;
2807
	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
L
Long Li 已提交
2808
	tcp_ses->rdma = volume_info->rdma;
P
Pavel Shilovsky 已提交
2809
	tcp_ses->in_flight = 0;
2810
	tcp_ses->max_in_flight = 0;
2811
	tcp_ses->credits = 1;
2812 2813 2814 2815 2816 2817 2818 2819
	init_waitqueue_head(&tcp_ses->response_q);
	init_waitqueue_head(&tcp_ses->request_q);
	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
	mutex_init(&tcp_ses->srv_mutex);
	memcpy(tcp_ses->workstation_RFC1001_name,
		volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
	memcpy(tcp_ses->server_RFC1001_name,
		volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2820
	tcp_ses->session_estab = false;
2821
	tcp_ses->sequence_number = 0;
2822
	tcp_ses->reconnect_instance = 1;
2823
	tcp_ses->lstrp = jiffies;
2824
	tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
2825
	spin_lock_init(&tcp_ses->req_lock);
2826 2827
	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
2828
	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
2829 2830
	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
	mutex_init(&tcp_ses->reconnect_mutex);
2831 2832 2833 2834
	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
	       sizeof(tcp_ses->srcaddr));
	memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
		sizeof(tcp_ses->dstaddr));
2835 2836 2837 2838 2839
	if (volume_info->use_client_guid)
		memcpy(tcp_ses->client_guid, volume_info->client_guid,
		       SMB2_CLIENT_GUID_SIZE);
	else
		generate_random_uuid(tcp_ses->client_guid);
2840 2841 2842 2843 2844 2845 2846 2847
	/*
	 * at this point we are the only ones with the pointer
	 * to the struct since the kernel thread not created yet
	 * no need to spinlock this init of tcpStatus or srv_count
	 */
	tcp_ses->tcpStatus = CifsNew;
	++tcp_ses->srv_count;

S
Steve French 已提交
2848 2849 2850 2851 2852
	if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
		volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
		tcp_ses->echo_interval = volume_info->echo_interval * HZ;
	else
		tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869
	if (tcp_ses->rdma) {
#ifndef CONFIG_CIFS_SMB_DIRECT
		cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
		rc = -ENOENT;
		goto out_err_crypto_release;
#endif
		tcp_ses->smbd_conn = smbd_get_connection(
			tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
		if (tcp_ses->smbd_conn) {
			cifs_dbg(VFS, "RDMA transport established\n");
			rc = 0;
			goto smbd_connected;
		} else {
			rc = -ENOENT;
			goto out_err_crypto_release;
		}
	}
2870
	rc = ip_connect(tcp_ses);
2871
	if (rc < 0) {
2872
		cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
2873
		goto out_err_crypto_release;
2874
	}
2875
smbd_connected:
2876 2877 2878 2879 2880
	/*
	 * since we're in a cifs function already, we know that
	 * this will succeed. No need for try_module_get().
	 */
	__module_get(THIS_MODULE);
2881
	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
2882 2883 2884
				  tcp_ses, "cifsd");
	if (IS_ERR(tcp_ses->tsk)) {
		rc = PTR_ERR(tcp_ses->tsk);
2885
		cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
2886
		module_put(THIS_MODULE);
2887
		goto out_err_crypto_release;
2888
	}
2889
	tcp_ses->min_offload = volume_info->min_offload;
2890
	tcp_ses->tcpStatus = CifsNeedNegotiate;
2891

2892
	tcp_ses->nr_targets = 1;
2893
	tcp_ses->ignore_signature = volume_info->ignore_signature;
2894
	/* thread spawned, put it on the list */
2895
	spin_lock(&cifs_tcp_ses_lock);
2896
	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
2897
	spin_unlock(&cifs_tcp_ses_lock);
2898

2899 2900
	cifs_fscache_get_client_cookie(tcp_ses);

2901
	/* queue echo request delayed work */
S
Steve French 已提交
2902
	queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
2903

2904 2905
	return tcp_ses;

2906
out_err_crypto_release:
2907
	cifs_crypto_secmech_release(tcp_ses);
2908

2909 2910
	put_net(cifs_net_ns(tcp_ses));

2911 2912
out_err:
	if (tcp_ses) {
2913 2914
		if (!IS_ERR(tcp_ses->hostname))
			kfree(tcp_ses->hostname);
2915 2916 2917 2918 2919 2920 2921
		if (tcp_ses->ssocket)
			sock_release(tcp_ses->ssocket);
		kfree(tcp_ses);
	}
	return ERR_PTR(rc);
}

2922
static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
2923
{
2924 2925 2926 2927
	if (vol->sectype != Unspecified &&
	    vol->sectype != ses->sectype)
		return 0;

2928 2929 2930 2931 2932 2933 2934
	/*
	 * If an existing session is limited to less channels than
	 * requested, it should not be reused
	 */
	if (ses->chan_max < vol->max_channels)
		return 0;

2935
	switch (ses->sectype) {
2936
	case Kerberos:
2937
		if (!uid_eq(vol->cred_uid, ses->cred_uid))
2938 2939 2940
			return 0;
		break;
	default:
J
Jeff Layton 已提交
2941 2942 2943 2944 2945 2946 2947
		/* NULL username means anonymous session */
		if (ses->user_name == NULL) {
			if (!vol->nullauth)
				return 0;
			break;
		}

2948
		/* anything else takes username/password */
J
Jeff Layton 已提交
2949 2950
		if (strncmp(ses->user_name,
			    vol->username ? vol->username : "",
2951
			    CIFS_MAX_USERNAME_LEN))
2952
			return 0;
2953
		if ((vol->username && strlen(vol->username) != 0) &&
2954 2955 2956
		    ses->password != NULL &&
		    strncmp(ses->password,
			    vol->password ? vol->password : "",
2957
			    CIFS_MAX_PASSWORD_LEN))
2958 2959 2960 2961 2962
			return 0;
	}
	return 1;
}

A
Aurelien Aptel 已提交
2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976
/**
 * cifs_setup_ipc - helper to setup the IPC tcon for the session
 *
 * A new IPC connection is made and stored in the session
 * tcon_ipc. The IPC tcon has the same lifetime as the session.
 */
static int
cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
{
	int rc = 0, xid;
	struct cifs_tcon *tcon;
	struct nls_table *nls_codepage;
	char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
	bool seal = false;
2977
	struct TCP_Server_Info *server = ses->server;
A
Aurelien Aptel 已提交
2978 2979 2980 2981 2982 2983

	/*
	 * If the mount request that resulted in the creation of the
	 * session requires encryption, force IPC to be encrypted too.
	 */
	if (volume_info->seal) {
2984
		if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
A
Aurelien Aptel 已提交
2985 2986
			seal = true;
		else {
2987
			cifs_server_dbg(VFS,
A
Aurelien Aptel 已提交
2988 2989 2990 2991 2992 2993 2994 2995 2996
				 "IPC: server doesn't support encryption\n");
			return -EOPNOTSUPP;
		}
	}

	tcon = tconInfoAlloc();
	if (tcon == NULL)
		return -ENOMEM;

2997
	scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
A
Aurelien Aptel 已提交
2998 2999 3000 3001 3002 3003 3004 3005

	/* cannot fail */
	nls_codepage = load_nls_default();

	xid = get_xid();
	tcon->ses = ses;
	tcon->ipc = true;
	tcon->seal = seal;
3006
	rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
A
Aurelien Aptel 已提交
3007 3008 3009
	free_xid(xid);

	if (rc) {
3010
		cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
A
Aurelien Aptel 已提交
3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050
		tconInfoFree(tcon);
		goto out;
	}

	cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);

	ses->tcon_ipc = tcon;
out:
	unload_nls(nls_codepage);
	return rc;
}

/**
 * cifs_free_ipc - helper to release the session IPC tcon
 *
 * Needs to be called everytime a session is destroyed
 */
static int
cifs_free_ipc(struct cifs_ses *ses)
{
	int rc = 0, xid;
	struct cifs_tcon *tcon = ses->tcon_ipc;

	if (tcon == NULL)
		return 0;

	if (ses->server->ops->tree_disconnect) {
		xid = get_xid();
		rc = ses->server->ops->tree_disconnect(xid, tcon);
		free_xid(xid);
	}

	if (rc)
		cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);

	tconInfoFree(tcon);
	ses->tcon_ipc = NULL;
	return rc;
}

3051
static struct cifs_ses *
3052
cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
L
Linus Torvalds 已提交
3053
{
3054
	struct cifs_ses *ses;
3055

3056
	spin_lock(&cifs_tcp_ses_lock);
3057
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
3058 3059
		if (ses->status == CifsExiting)
			continue;
3060 3061
		if (!match_session(ses, vol))
			continue;
3062
		++ses->ses_count;
3063
		spin_unlock(&cifs_tcp_ses_lock);
3064 3065
		return ses;
	}
3066
	spin_unlock(&cifs_tcp_ses_lock);
3067 3068
	return NULL;
}
3069

3070
void cifs_put_smb_ses(struct cifs_ses *ses)
3071
{
3072
	unsigned int rc, xid;
3073
	struct TCP_Server_Info *server = ses->server;
3074

3075
	cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
3076

3077
	spin_lock(&cifs_tcp_ses_lock);
3078 3079 3080 3081
	if (ses->status == CifsExiting) {
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}
3082
	if (--ses->ses_count > 0) {
3083
		spin_unlock(&cifs_tcp_ses_lock);
3084 3085
		return;
	}
3086 3087
	if (ses->status == CifsGood)
		ses->status = CifsExiting;
3088
	spin_unlock(&cifs_tcp_ses_lock);
3089

A
Aurelien Aptel 已提交
3090 3091
	cifs_free_ipc(ses);

3092
	if (ses->status == CifsExiting && server->ops->logoff) {
3093
		xid = get_xid();
3094 3095
		rc = server->ops->logoff(xid, ses);
		if (rc)
3096
			cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
3097
				__func__, rc);
3098
		_free_xid(xid);
3099
	}
3100 3101 3102 3103 3104

	spin_lock(&cifs_tcp_ses_lock);
	list_del_init(&ses->smb_ses_list);
	spin_unlock(&cifs_tcp_ses_lock);

3105 3106 3107 3108 3109 3110 3111 3112
	/* close any extra channels */
	if (ses->chan_count > 1) {
		int i;

		for (i = 1; i < ses->chan_count; i++)
			cifs_put_tcp_session(ses->chans[i].server, 0);
	}

3113
	sesInfoFree(ses);
3114
	cifs_put_tcp_session(server, 0);
3115
}
3116

3117 3118
#ifdef CONFIG_KEYS

3119 3120
/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
3121 3122 3123 3124 3125 3126

/* Populate username and pw fields from keyring if possible */
static int
cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
{
	int rc = 0;
3127
	int is_domain = 0;
3128 3129
	const char *delim, *payload;
	char *desc;
3130 3131 3132 3133 3134
	ssize_t len;
	struct key *key;
	struct TCP_Server_Info *server = ses->server;
	struct sockaddr_in *sa;
	struct sockaddr_in6 *sa6;
3135
	const struct user_key_payload *upayload;
3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151

	desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
	if (!desc)
		return -ENOMEM;

	/* try to find an address key first */
	switch (server->dstaddr.ss_family) {
	case AF_INET:
		sa = (struct sockaddr_in *)&server->dstaddr;
		sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
		break;
	case AF_INET6:
		sa6 = (struct sockaddr_in6 *)&server->dstaddr;
		sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
		break;
	default:
3152 3153
		cifs_dbg(FYI, "Bad ss_family (%hu)\n",
			 server->dstaddr.ss_family);
3154 3155 3156 3157
		rc = -EINVAL;
		goto out_err;
	}

3158
	cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
3159
	key = request_key(&key_type_logon, desc, "");
3160 3161
	if (IS_ERR(key)) {
		if (!ses->domainName) {
3162
			cifs_dbg(FYI, "domainName is NULL\n");
3163 3164 3165 3166 3167 3168
			rc = PTR_ERR(key);
			goto out_err;
		}

		/* didn't work, try to find a domain key */
		sprintf(desc, "cifs:d:%s", ses->domainName);
3169
		cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
3170
		key = request_key(&key_type_logon, desc, "");
3171 3172 3173 3174
		if (IS_ERR(key)) {
			rc = PTR_ERR(key);
			goto out_err;
		}
3175
		is_domain = 1;
3176 3177 3178
	}

	down_read(&key->sem);
3179
	upayload = user_key_payload_locked(key);
3180
	if (IS_ERR_OR_NULL(upayload)) {
3181
		rc = upayload ? PTR_ERR(upayload) : -EINVAL;
3182 3183 3184 3185
		goto out_key_put;
	}

	/* find first : in payload */
3186
	payload = upayload->data;
3187
	delim = strnchr(payload, upayload->datalen, ':');
3188
	cifs_dbg(FYI, "payload=%s\n", payload);
3189
	if (!delim) {
3190 3191
		cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
			 upayload->datalen);
3192 3193 3194 3195 3196
		rc = -EINVAL;
		goto out_key_put;
	}

	len = delim - payload;
3197
	if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
3198 3199
		cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
			 len);
3200 3201 3202 3203 3204 3205
		rc = -EINVAL;
		goto out_key_put;
	}

	vol->username = kstrndup(payload, len, GFP_KERNEL);
	if (!vol->username) {
3206 3207
		cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
			 len);
3208 3209 3210
		rc = -ENOMEM;
		goto out_key_put;
	}
3211
	cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
3212 3213

	len = key->datalen - (len + 1);
3214
	if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
3215
		cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
3216 3217 3218 3219 3220 3221 3222 3223 3224
		rc = -EINVAL;
		kfree(vol->username);
		vol->username = NULL;
		goto out_key_put;
	}

	++delim;
	vol->password = kstrndup(delim, len, GFP_KERNEL);
	if (!vol->password) {
3225 3226
		cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
			 len);
3227 3228 3229 3230 3231 3232
		rc = -ENOMEM;
		kfree(vol->username);
		vol->username = NULL;
		goto out_key_put;
	}

3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246
	/*
	 * If we have a domain key then we must set the domainName in the
	 * for the request.
	 */
	if (is_domain && ses->domainName) {
		vol->domainname = kstrndup(ses->domainName,
					   strlen(ses->domainName),
					   GFP_KERNEL);
		if (!vol->domainname) {
			cifs_dbg(FYI, "Unable to allocate %zd bytes for "
				 "domain\n", len);
			rc = -ENOMEM;
			kfree(vol->username);
			vol->username = NULL;
3247
			kzfree(vol->password);
3248 3249 3250 3251 3252
			vol->password = NULL;
			goto out_key_put;
		}
	}

3253 3254 3255 3256 3257
out_key_put:
	up_read(&key->sem);
	key_put(key);
out_err:
	kfree(desc);
3258
	cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269
	return rc;
}
#else /* ! CONFIG_KEYS */
static inline int
cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
		   struct cifs_ses *ses __attribute__((unused)))
{
	return -ENOSYS;
}
#endif /* CONFIG_KEYS */

3270 3271 3272 3273 3274 3275 3276
/**
 * cifs_get_smb_ses - get a session matching @volume_info data from @server
 *
 * This function assumes it is being called from cifs_mount() where we
 * already got a server reference (server refcount +1). See
 * cifs_get_tcon() for refcount explanations.
 */
3277
struct cifs_ses *
3278 3279
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
{
3280 3281
	int rc = -ENOMEM;
	unsigned int xid;
3282
	struct cifs_ses *ses;
3283 3284
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3285

3286
	xid = get_xid();
3287

3288
	ses = cifs_find_smb_ses(server, volume_info);
3289
	if (ses) {
3290 3291
		cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
			 ses->status);
3292 3293

		mutex_lock(&ses->session_mutex);
3294 3295 3296 3297 3298
		rc = cifs_negotiate_protocol(xid, ses);
		if (rc) {
			mutex_unlock(&ses->session_mutex);
			/* problem -- put our ses reference */
			cifs_put_smb_ses(ses);
3299
			free_xid(xid);
3300 3301
			return ERR_PTR(rc);
		}
3302
		if (ses->need_reconnect) {
3303
			cifs_dbg(FYI, "Session needs reconnect\n");
3304 3305 3306 3307 3308 3309
			rc = cifs_setup_session(xid, ses,
						volume_info->local_nls);
			if (rc) {
				mutex_unlock(&ses->session_mutex);
				/* problem -- put our reference */
				cifs_put_smb_ses(ses);
3310
				free_xid(xid);
3311 3312 3313 3314
				return ERR_PTR(rc);
			}
		}
		mutex_unlock(&ses->session_mutex);
3315 3316

		/* existing SMB ses has a server reference already */
3317
		cifs_put_tcp_session(server, 0);
3318
		free_xid(xid);
3319 3320 3321
		return ses;
	}

3322
	cifs_dbg(FYI, "Existing smb sess not found\n");
3323 3324 3325 3326 3327 3328
	ses = sesInfoAlloc();
	if (ses == NULL)
		goto get_ses_fail;

	/* new SMB session uses our server ref */
	ses->server = server;
3329 3330
	if (server->dstaddr.ss_family == AF_INET6)
		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
3331
	else
3332
		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
3333

3334 3335 3336 3337 3338
	if (volume_info->username) {
		ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
		if (!ses->user_name)
			goto get_ses_fail;
	}
3339 3340 3341 3342 3343 3344 3345 3346

	/* volume_info->password freed at unmount */
	if (volume_info->password) {
		ses->password = kstrdup(volume_info->password, GFP_KERNEL);
		if (!ses->password)
			goto get_ses_fail;
	}
	if (volume_info->domainname) {
3347 3348 3349
		ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
		if (!ses->domainName)
			goto get_ses_fail;
3350
	}
3351 3352
	if (volume_info->domainauto)
		ses->domainAuto = volume_info->domainauto;
3353
	ses->cred_uid = volume_info->cred_uid;
3354
	ses->linux_uid = volume_info->linux_uid;
3355

3356 3357
	ses->sectype = volume_info->sectype;
	ses->sign = volume_info->sign;
3358
	mutex_lock(&ses->session_mutex);
3359 3360 3361 3362 3363 3364

	/* add server as first channel */
	ses->chans[0].server = server;
	ses->chan_count = 1;
	ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;

3365 3366 3367
	rc = cifs_negotiate_protocol(xid, ses);
	if (!rc)
		rc = cifs_setup_session(xid, ses, volume_info->local_nls);
3368 3369 3370 3371 3372

	/* each channel uses a different signing key */
	memcpy(ses->chans[0].signkey, ses->smb3signingkey,
	       sizeof(ses->smb3signingkey));

3373
	mutex_unlock(&ses->session_mutex);
3374
	if (rc)
3375 3376
		goto get_ses_fail;

3377
	/* success, put it on the list and add it as first channel */
3378
	spin_lock(&cifs_tcp_ses_lock);
3379
	list_add(&ses->smb_ses_list, &server->smb_ses_list);
3380
	spin_unlock(&cifs_tcp_ses_lock);
3381

3382
	free_xid(xid);
A
Aurelien Aptel 已提交
3383 3384 3385

	cifs_setup_ipc(ses, volume_info);

3386 3387 3388 3389
	return ses;

get_ses_fail:
	sesInfoFree(ses);
3390
	free_xid(xid);
3391 3392 3393
	return ERR_PTR(rc);
}

3394
static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
3395 3396 3397
{
	if (tcon->tidStatus == CifsExiting)
		return 0;
3398
	if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
3399
		return 0;
3400 3401 3402 3403
	if (tcon->seal != volume_info->seal)
		return 0;
	if (tcon->snapshot_time != volume_info->snapshot_time)
		return 0;
3404 3405
	if (tcon->handle_timeout != volume_info->handle_timeout)
		return 0;
3406 3407
	if (tcon->no_lease != volume_info->no_lease)
		return 0;
3408 3409 3410
	return 1;
}

3411
static struct cifs_tcon *
3412
cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
3413 3414
{
	struct list_head *tmp;
3415
	struct cifs_tcon *tcon;
3416

3417
	spin_lock(&cifs_tcp_ses_lock);
3418
	list_for_each(tmp, &ses->tcon_list) {
3419
		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
3420
		if (!match_tcon(tcon, volume_info))
3421 3422
			continue;
		++tcon->tc_count;
3423
		spin_unlock(&cifs_tcp_ses_lock);
3424
		return tcon;
L
Linus Torvalds 已提交
3425
	}
3426
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
3427 3428 3429
	return NULL;
}

3430
void
3431
cifs_put_tcon(struct cifs_tcon *tcon)
3432
{
3433
	unsigned int xid;
A
Aurelien Aptel 已提交
3434
	struct cifs_ses *ses;
3435

A
Aurelien Aptel 已提交
3436 3437 3438 3439 3440 3441 3442 3443
	/*
	 * IPC tcon share the lifetime of their session and are
	 * destroyed in the session put function
	 */
	if (tcon == NULL || tcon->ipc)
		return;

	ses = tcon->ses;
3444
	cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
3445
	spin_lock(&cifs_tcp_ses_lock);
3446
	if (--tcon->tc_count > 0) {
3447
		spin_unlock(&cifs_tcp_ses_lock);
3448 3449 3450 3451
		return;
	}

	list_del_init(&tcon->tcon_list);
3452
	spin_unlock(&cifs_tcp_ses_lock);
3453

3454
	xid = get_xid();
3455 3456
	if (ses->server->ops->tree_disconnect)
		ses->server->ops->tree_disconnect(xid, tcon);
3457
	_free_xid(xid);
3458

3459
	cifs_fscache_release_super_cookie(tcon);
3460
	tconInfoFree(tcon);
3461 3462 3463
	cifs_put_smb_ses(ses);
}

3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483
/**
 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
 *
 * - tcon refcount is the number of mount points using the tcon.
 * - ses refcount is the number of tcon using the session.
 *
 * 1. This function assumes it is being called from cifs_mount() where
 *    we already got a session reference (ses refcount +1).
 *
 * 2. Since we're in the context of adding a mount point, the end
 *    result should be either:
 *
 * a) a new tcon already allocated with refcount=1 (1 mount point) and
 *    its session refcount incremented (1 new tcon). This +1 was
 *    already done in (1).
 *
 * b) an existing tcon with refcount+1 (add a mount point to it) and
 *    identical ses refcount (no new tcon). Because of (1) we need to
 *    decrement the ses refcount.
 */
3484 3485
static struct cifs_tcon *
cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
3486 3487
{
	int rc, xid;
3488
	struct cifs_tcon *tcon;
3489

3490
	tcon = cifs_find_tcon(ses, volume_info);
3491
	if (tcon) {
3492 3493 3494 3495
		/*
		 * tcon has refcount already incremented but we need to
		 * decrement extra ses reference gotten by caller (case b)
		 */
3496
		cifs_dbg(FYI, "Found match on UNC path\n");
3497 3498 3499 3500
		cifs_put_smb_ses(ses);
		return tcon;
	}

3501 3502 3503 3504 3505
	if (!ses->server->ops->tree_connect) {
		rc = -ENOSYS;
		goto out_fail;
	}

3506 3507 3508 3509 3510 3511
	tcon = tconInfoAlloc();
	if (tcon == NULL) {
		rc = -ENOMEM;
		goto out_fail;
	}

3512 3513 3514 3515 3516 3517 3518 3519 3520 3521
	if (volume_info->snapshot_time) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "Use SMB2 or later for snapshot mount option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
			tcon->snapshot_time = volume_info->snapshot_time;
	}

3522 3523 3524 3525 3526 3527 3528 3529 3530 3531
	if (volume_info->handle_timeout) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "Use SMB2.1 or later for handle timeout option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
			tcon->handle_timeout = volume_info->handle_timeout;
	}

3532 3533 3534 3535 3536 3537 3538 3539 3540
	tcon->ses = ses;
	if (volume_info->password) {
		tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
		if (!tcon->password) {
			rc = -ENOMEM;
			goto out_fail;
		}
	}

3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556
	if (volume_info->seal) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
				 "SMB3 or later required for encryption\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else if (tcon->ses->server->capabilities &
					SMB2_GLOBAL_CAP_ENCRYPTION)
			tcon->seal = true;
		else {
			cifs_dbg(VFS, "Encryption is not supported on share\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
	}

3557 3558
	if (volume_info->linux_ext) {
		if (ses->server->posix_ext_supported) {
3559
			tcon->posix_extensions = true;
3560 3561
			printk_once(KERN_WARNING
				"SMB3.11 POSIX Extensions are experimental\n");
3562 3563 3564 3565
		} else {
			cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
3566
		}
3567 3568
	}

3569 3570 3571 3572
	/*
	 * BB Do we need to wrap session_mutex around this TCon call and Unix
	 * SetFS as we do on SessSetup and reconnect?
	 */
3573
	xid = get_xid();
3574 3575
	rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
					    volume_info->local_nls);
3576
	free_xid(xid);
3577
	cifs_dbg(FYI, "Tcon rc = %d\n", rc);
3578 3579 3580
	if (rc)
		goto out_fail;

3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602
	tcon->use_persistent = false;
	/* check if SMB2 or later, CIFS does not support persistent handles */
	if (volume_info->persistent) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "SMB3 or later required for persistent handles\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else if (ses->server->capabilities &
			   SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
			tcon->use_persistent = true;
		else /* persistent handles requested but not supported */ {
			cifs_dbg(VFS,
				"Persistent handles not supported on share\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
	} else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
	     && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
	     && (volume_info->nopersistent == false)) {
		cifs_dbg(FYI, "enabling persistent handles\n");
		tcon->use_persistent = true;
S
Steve French 已提交
3603 3604 3605 3606 3607 3608 3609 3610
	} else if (volume_info->resilient) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "SMB2.1 or later required for resilient handles\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
		tcon->use_resilient = true;
3611 3612
	}

3613 3614 3615 3616 3617 3618 3619 3620
	/* If the user really knows what they are doing they can override */
	if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
		if (volume_info->cache_ro)
			cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
		else if (volume_info->cache_rw)
			cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
	}

3621 3622 3623 3624 3625
	/*
	 * We can have only one retry value for a connection to a share so for
	 * resources mounted more than once to the same server share the last
	 * value passed in for the retry flag is used.
	 */
3626 3627
	tcon->retry = volume_info->retry;
	tcon->nocase = volume_info->nocase;
S
Steve French 已提交
3628
	tcon->nohandlecache = volume_info->nohandlecache;
3629
	tcon->local_lease = volume_info->local_lease;
3630
	tcon->no_lease = volume_info->no_lease;
3631
	INIT_LIST_HEAD(&tcon->pending_opens);
3632

3633
	spin_lock(&cifs_tcp_ses_lock);
3634
	list_add(&tcon->tcon_list, &ses->tcon_list);
3635
	spin_unlock(&cifs_tcp_ses_lock);
3636

3637 3638
	cifs_fscache_get_super_cookie(tcon);

3639 3640 3641 3642 3643 3644 3645
	return tcon;

out_fail:
	tconInfoFree(tcon);
	return ERR_PTR(rc);
}

3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
void
cifs_put_tlink(struct tcon_link *tlink)
{
	if (!tlink || IS_ERR(tlink))
		return;

	if (!atomic_dec_and_test(&tlink->tl_count) ||
	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
		tlink->tl_time = jiffies;
		return;
	}

	if (!IS_ERR(tlink_tcon(tlink)))
		cifs_put_tcon(tlink_tcon(tlink));
	kfree(tlink);
	return;
}
3663

3664 3665 3666 3667 3668
static int
compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{
	struct cifs_sb_info *old = CIFS_SB(sb);
	struct cifs_sb_info *new = mnt_data->cifs_sb;
3669 3670
	unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
	unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
3671 3672 3673 3674

	if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
		return 0;

3675 3676 3677 3678
	if (old->mnt_cifs_serverino_autodisabled)
		newflags &= ~CIFS_MOUNT_SERVER_INUM;

	if (oldflags != newflags)
3679 3680 3681
		return 0;

	/*
3682 3683
	 * We want to share sb only if we don't specify an r/wsize or
	 * specified r/wsize is greater than or equal to existing one.
3684 3685 3686 3687
	 */
	if (new->wsize && new->wsize < old->wsize)
		return 0;

3688 3689 3690
	if (new->rsize && new->rsize < old->rsize)
		return 0;

3691
	if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706
		return 0;

	if (old->mnt_file_mode != new->mnt_file_mode ||
	    old->mnt_dir_mode != new->mnt_dir_mode)
		return 0;

	if (strcmp(old->local_nls->charset, new->local_nls->charset))
		return 0;

	if (old->actimeo != new->actimeo)
		return 0;

	return 1;
}

3707 3708 3709 3710 3711
static int
match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{
	struct cifs_sb_info *old = CIFS_SB(sb);
	struct cifs_sb_info *new = mnt_data->cifs_sb;
3712 3713 3714 3715
	bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
		old->prepath;
	bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
		new->prepath;
3716

S
Sachin Prabhu 已提交
3717
	if (old_set && new_set && !strcmp(new->prepath, old->prepath))
3718
		return 1;
S
Sachin Prabhu 已提交
3719 3720 3721
	else if (!old_set && !new_set)
		return 1;

3722 3723 3724
	return 0;
}

3725 3726 3727 3728 3729 3730 3731
int
cifs_match_super(struct super_block *sb, void *data)
{
	struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
	struct smb_vol *volume_info;
	struct cifs_sb_info *cifs_sb;
	struct TCP_Server_Info *tcp_srv;
3732 3733
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749
	struct tcon_link *tlink;
	int rc = 0;

	spin_lock(&cifs_tcp_ses_lock);
	cifs_sb = CIFS_SB(sb);
	tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
	if (IS_ERR(tlink)) {
		spin_unlock(&cifs_tcp_ses_lock);
		return rc;
	}
	tcon = tlink_tcon(tlink);
	ses = tcon->ses;
	tcp_srv = ses->server;

	volume_info = mnt_data->vol;

3750
	if (!match_server(tcp_srv, volume_info) ||
3751
	    !match_session(ses, volume_info) ||
3752
	    !match_tcon(tcon, volume_info) ||
3753
	    !match_prepath(sb, mnt_data)) {
3754 3755 3756 3757 3758 3759 3760
		rc = 0;
		goto out;
	}

	rc = compare_mount_options(sb, mnt_data);
out:
	spin_unlock(&cifs_tcp_ses_lock);
3761
	cifs_put_tlink(tlink);
3762 3763 3764
	return rc;
}

3765 3766 3767 3768 3769 3770 3771 3772
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key cifs_key[2];
static struct lock_class_key cifs_slock_key[2];

static inline void
cifs_reclassify_socket4(struct socket *sock)
{
	struct sock *sk = sock->sk;
3773
	BUG_ON(!sock_allow_reclassification(sk));
3774 3775 3776 3777 3778 3779 3780 3781
	sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
		&cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
}

static inline void
cifs_reclassify_socket6(struct socket *sock)
{
	struct sock *sk = sock->sk;
3782
	BUG_ON(!sock_allow_reclassification(sk));
3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797
	sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
		&cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
}
#else
static inline void
cifs_reclassify_socket4(struct socket *sock)
{
}

static inline void
cifs_reclassify_socket6(struct socket *sock)
{
}
#endif

L
Linus Torvalds 已提交
3798
/* See RFC1001 section 14 on representation of Netbios names */
3799
static void rfc1002mangle(char *target, char *source, unsigned int length)
L
Linus Torvalds 已提交
3800
{
3801
	unsigned int i, j;
L
Linus Torvalds 已提交
3802

3803
	for (i = 0, j = 0; i < (length); i++) {
L
Linus Torvalds 已提交
3804 3805 3806
		/* mask a nibble at a time and encode */
		target[j] = 'A' + (0x0F & (source[i] >> 4));
		target[j+1] = 'A' + (0x0F & source[i]);
3807
		j += 2;
L
Linus Torvalds 已提交
3808 3809 3810 3811
	}

}

3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827
static int
bind_socket(struct TCP_Server_Info *server)
{
	int rc = 0;
	if (server->srcaddr.ss_family != AF_UNSPEC) {
		/* Bind to the specified local IP address */
		struct socket *socket = server->ssocket;
		rc = socket->ops->bind(socket,
				       (struct sockaddr *) &server->srcaddr,
				       sizeof(server->srcaddr));
		if (rc < 0) {
			struct sockaddr_in *saddr4;
			struct sockaddr_in6 *saddr6;
			saddr4 = (struct sockaddr_in *)&server->srcaddr;
			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
			if (saddr6->sin6_family == AF_INET6)
3828
				cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3829
					 &saddr6->sin6_addr, rc);
3830
			else
3831
				cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3832
					 &saddr4->sin_addr.s_addr, rc);
3833 3834 3835 3836
		}
	}
	return rc;
}
L
Linus Torvalds 已提交
3837 3838

static int
3839
ip_rfc1001_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
3840 3841
{
	int rc = 0;
3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853
	/*
	 * some servers require RFC1001 sessinit before sending
	 * negprot - BB check reconnection in case where second
	 * sessinit is sent but no second negprot
	 */
	struct rfc1002_session_packet *ses_init_buf;
	struct smb_hdr *smb_buf;
	ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
			       GFP_KERNEL);
	if (ses_init_buf) {
		ses_init_buf->trailer.session_req.called_len = 32;

3854
		if (server->server_RFC1001_name[0] != 0)
3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.called_name,
				      server->server_RFC1001_name,
				      RFC1001_NAME_LEN_WITH_NULL);
		else
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.called_name,
				      DEFAULT_CIFS_CALLED_NAME,
				      RFC1001_NAME_LEN_WITH_NULL);

		ses_init_buf->trailer.session_req.calling_len = 32;

		/*
		 * calling name ends in null (byte 16) from old smb
		 * convention.
		 */
3871
		if (server->workstation_RFC1001_name[0] != 0)
3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.calling_name,
				      server->workstation_RFC1001_name,
				      RFC1001_NAME_LEN_WITH_NULL);
		else
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.calling_name,
				      "LINUX_CIFS_CLNT",
				      RFC1001_NAME_LEN_WITH_NULL);

		ses_init_buf->trailer.session_req.scope1 = 0;
		ses_init_buf->trailer.session_req.scope2 = 0;
		smb_buf = (struct smb_hdr *)ses_init_buf;

		/* sizeof RFC1002_SESSION_REQUEST with no scope */
3887
		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913
		rc = smb_send(server, smb_buf, 0x44);
		kfree(ses_init_buf);
		/*
		 * RFC1001 layer in at least one server
		 * requires very short break before negprot
		 * presumably because not expecting negprot
		 * to follow so fast.  This is a simple
		 * solution that works without
		 * complicating the code and causes no
		 * significant slowing down on mount
		 * for everyone else
		 */
		usleep_range(1000, 2000);
	}
	/*
	 * else the negprot may still work without this
	 * even though malloc failed
	 */

	return rc;
}

static int
generic_ip_connect(struct TCP_Server_Info *server)
{
	int rc = 0;
3914
	__be16 sport;
3915
	int slen, sfamily;
3916
	struct socket *socket = server->ssocket;
3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929
	struct sockaddr *saddr;

	saddr = (struct sockaddr *) &server->dstaddr;

	if (server->dstaddr.ss_family == AF_INET6) {
		sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
		slen = sizeof(struct sockaddr_in6);
		sfamily = AF_INET6;
	} else {
		sport = ((struct sockaddr_in *) saddr)->sin_port;
		slen = sizeof(struct sockaddr_in);
		sfamily = AF_INET;
	}
L
Linus Torvalds 已提交
3930

3931
	if (socket == NULL) {
3932 3933
		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
				   IPPROTO_TCP, &socket, 1);
L
Linus Torvalds 已提交
3934
		if (rc < 0) {
3935
			cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
3936
			server->ssocket = NULL;
L
Linus Torvalds 已提交
3937 3938
			return rc;
		}
3939 3940

		/* BB other socket options to set KEEPALIVE, NODELAY? */
3941
		cifs_dbg(FYI, "Socket created\n");
3942 3943
		server->ssocket = socket;
		socket->sk->sk_allocation = GFP_NOFS;
3944 3945 3946 3947
		if (sfamily == AF_INET6)
			cifs_reclassify_socket6(socket);
		else
			cifs_reclassify_socket4(socket);
L
Linus Torvalds 已提交
3948 3949
	}

3950 3951 3952 3953
	rc = bind_socket(server);
	if (rc < 0)
		return rc;

3954 3955
	/*
	 * Eventually check for other socket options to change from
3956 3957
	 * the default. sock_setsockopt not used because it expects
	 * user space buffer
3958 3959
	 */
	socket->sk->sk_rcvtimeo = 7 * HZ;
3960
	socket->sk->sk_sndtimeo = 5 * HZ;
3961

3962
	/* make the bufsizes depend on wsize/rsize and max requests */
3963 3964 3965 3966 3967
	if (server->noautotune) {
		if (socket->sk->sk_sndbuf < (200 * 1024))
			socket->sk->sk_sndbuf = 200 * 1024;
		if (socket->sk->sk_rcvbuf < (140 * 1024))
			socket->sk->sk_rcvbuf = 140 * 1024;
3968
	}
L
Linus Torvalds 已提交
3969

3970
	if (server->tcp_nodelay) {
3971
		int val = 1;
3972 3973 3974
		rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
				(char *)&val, sizeof(val));
		if (rc)
3975 3976
			cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
				 rc);
3977 3978
	}

3979
	cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
3980
		 socket->sk->sk_sndbuf,
3981
		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3982

3983 3984
	rc = socket->ops->connect(socket, saddr, slen,
				  server->noblockcnt ? O_NONBLOCK : 0);
3985 3986 3987 3988 3989 3990
	/*
	 * When mounting SMB root file systems, we do not want to block in
	 * connect. Otherwise bail out and then let cifs_reconnect() perform
	 * reconnect failover - if possible.
	 */
	if (server->noblockcnt && rc == -EINPROGRESS)
3991
		rc = 0;
3992
	if (rc < 0) {
3993
		cifs_dbg(FYI, "Error %d connecting to server\n", rc);
3994 3995 3996 3997 3998
		sock_release(socket);
		server->ssocket = NULL;
		return rc;
	}

3999 4000
	if (sport == htons(RFC1001_PORT))
		rc = ip_rfc1001_connect(server);
4001

L
Linus Torvalds 已提交
4002 4003 4004 4005
	return rc;
}

static int
4006
ip_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
4007
{
4008
	__be16 *sport;
4009 4010
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
L
Linus Torvalds 已提交
4011

4012 4013 4014 4015
	if (server->dstaddr.ss_family == AF_INET6)
		sport = &addr6->sin6_port;
	else
		sport = &addr->sin_port;
L
Linus Torvalds 已提交
4016

4017 4018
	if (*sport == 0) {
		int rc;
L
Linus Torvalds 已提交
4019

4020 4021
		/* try with 445 port at first */
		*sport = htons(CIFS_PORT);
4022

4023
		rc = generic_ip_connect(server);
L
Linus Torvalds 已提交
4024
		if (rc >= 0)
4025
			return rc;
4026

4027 4028
		/* if it failed, try with 139 port */
		*sport = htons(RFC1001_PORT);
4029 4030
	}

4031
	return generic_ip_connect(server);
L
Linus Torvalds 已提交
4032 4033
}

4034
void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
4035
			  struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046
{
	/* if we are reconnecting then should we check to see if
	 * any requested capabilities changed locally e.g. via
	 * remount but we can not do much about it here
	 * if they have (even if we could detect it by the following)
	 * Perhaps we could add a backpointer to array of sb from tcon
	 * or if we change to make all sb to same share the same
	 * sb as NFS - then we only have one backpointer to sb.
	 * What if we wanted to mount the server share twice once with
	 * and once without posixacls or posix paths? */
	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
4047

4048 4049 4050
	if (vol_info && vol_info->no_linux_ext) {
		tcon->fsUnixInfo.Capability = 0;
		tcon->unix_ext = 0; /* Unix Extensions disabled */
4051
		cifs_dbg(FYI, "Linux protocol extensions disabled\n");
4052 4053 4054 4055 4056
		return;
	} else if (vol_info)
		tcon->unix_ext = 1; /* Unix Extensions supported */

	if (tcon->unix_ext == 0) {
4057
		cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
4058 4059
		return;
	}
4060

S
Steve French 已提交
4061
	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
4062
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
4063
		cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
4064 4065
		/* check for reconnect case in which we do not
		   want to change the mount behavior if we can avoid it */
S
Steve French 已提交
4066
		if (vol_info == NULL) {
4067
			/* turn off POSIX ACL and PATHNAMES if not set
4068 4069 4070
			   originally at mount time */
			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
4071 4072
			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
4073
					cifs_dbg(VFS, "POSIXPATH support change\n");
4074
				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
4075
			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
4076 4077
				cifs_dbg(VFS, "possible reconnect error\n");
				cifs_dbg(VFS, "server disabled POSIX path support\n");
4078
			}
4079
		}
4080

4081
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
4082
			cifs_dbg(VFS, "per-share encryption not supported yet\n");
4083

4084
		cap &= CIFS_UNIX_CAP_MASK;
4085
		if (vol_info && vol_info->no_psx_acl)
4086
			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
4087
		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
4088
			cifs_dbg(FYI, "negotiated posix acl support\n");
4089 4090 4091
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
					CIFS_MOUNT_POSIXACL;
4092 4093
		}

4094
		if (vol_info && vol_info->posix_paths == 0)
4095
			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
4096
		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4097
			cifs_dbg(FYI, "negotiate posix pathnames\n");
4098 4099
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
4100 4101
					CIFS_MOUNT_POSIX_PATHS;
		}
4102

4103
		cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
4104
#ifdef CONFIG_CIFS_DEBUG2
4105
		if (cap & CIFS_UNIX_FCNTL_CAP)
4106
			cifs_dbg(FYI, "FCNTL cap\n");
4107
		if (cap & CIFS_UNIX_EXTATTR_CAP)
4108
			cifs_dbg(FYI, "EXTATTR cap\n");
4109
		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
4110
			cifs_dbg(FYI, "POSIX path cap\n");
4111
		if (cap & CIFS_UNIX_XATTR_CAP)
4112
			cifs_dbg(FYI, "XATTR cap\n");
4113
		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
4114
			cifs_dbg(FYI, "POSIX ACL cap\n");
4115
		if (cap & CIFS_UNIX_LARGE_READ_CAP)
4116
			cifs_dbg(FYI, "very large read cap\n");
4117
		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
4118
			cifs_dbg(FYI, "very large write cap\n");
4119
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
4120
			cifs_dbg(FYI, "transport encryption cap\n");
4121
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
4122
			cifs_dbg(FYI, "mandatory transport encryption cap\n");
4123 4124
#endif /* CIFS_DEBUG2 */
		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
4125
			if (vol_info == NULL) {
4126
				cifs_dbg(FYI, "resetting capabilities failed\n");
4127
			} else
4128
				cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.\n");
4129

4130 4131 4132 4133
		}
	}
}

4134
int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
4135
			struct cifs_sb_info *cifs_sb)
4136
{
4137 4138
	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);

4139 4140 4141
	spin_lock_init(&cifs_sb->tlink_tree_lock);
	cifs_sb->tlink_tree = RB_ROOT;

4142
	cifs_sb->bsize = pvolume_info->bsize;
4143
	/*
4144 4145
	 * Temporarily set r/wsize for matching superblock. If we end up using
	 * new sb then client will later negotiate it downward if needed.
4146
	 */
4147
	cifs_sb->rsize = pvolume_info->rsize;
4148 4149
	cifs_sb->wsize = pvolume_info->wsize;

S
Steve French 已提交
4150 4151 4152 4153
	cifs_sb->mnt_uid = pvolume_info->linux_uid;
	cifs_sb->mnt_gid = pvolume_info->linux_gid;
	cifs_sb->mnt_file_mode = pvolume_info->file_mode;
	cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
4154 4155
	cifs_dbg(FYI, "file mode: 0x%hx  dir mode: 0x%hx\n",
		 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
S
Steve French 已提交
4156

4157
	cifs_sb->actimeo = pvolume_info->actimeo;
4158
	cifs_sb->local_nls = pvolume_info->local_nls;
4159

4160 4161
	if (pvolume_info->nodfs)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
S
Steve French 已提交
4162 4163 4164 4165
	if (pvolume_info->noperm)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
	if (pvolume_info->setuids)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
4166 4167
	if (pvolume_info->setuidfromacl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
S
Steve French 已提交
4168 4169 4170
	if (pvolume_info->server_ino)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
	if (pvolume_info->remap)
4171 4172
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
	if (pvolume_info->sfu_remap)
S
Steve French 已提交
4173 4174 4175 4176 4177 4178 4179
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
	if (pvolume_info->no_xattr)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
	if (pvolume_info->sfu_emul)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
	if (pvolume_info->nobrl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
S
Steve French 已提交
4180 4181
	if (pvolume_info->nohandlecache)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
4182
	if (pvolume_info->nostrictsync)
S
Steve French 已提交
4183
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
4184 4185
	if (pvolume_info->mand_lock)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
4186 4187
	if (pvolume_info->rwpidforward)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
4188 4189
	if (pvolume_info->mode_ace)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
S
Steve French 已提交
4190 4191
	if (pvolume_info->cifs_acl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
4192
	if (pvolume_info->backupuid_specified) {
4193
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
4194 4195 4196
		cifs_sb->mnt_backupuid = pvolume_info->backupuid;
	}
	if (pvolume_info->backupgid_specified) {
4197
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
4198 4199
		cifs_sb->mnt_backupgid = pvolume_info->backupgid;
	}
S
Steve French 已提交
4200 4201 4202 4203 4204 4205
	if (pvolume_info->override_uid)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
	if (pvolume_info->override_gid)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
	if (pvolume_info->dynperm)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
4206 4207
	if (pvolume_info->fsc)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
J
Jeff Layton 已提交
4208 4209 4210
	if (pvolume_info->multiuser)
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
					    CIFS_MOUNT_NO_PERM);
4211 4212
	if (pvolume_info->strict_io)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
S
Steve French 已提交
4213
	if (pvolume_info->direct_io) {
4214
		cifs_dbg(FYI, "mounting share using direct i/o\n");
S
Steve French 已提交
4215 4216
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
	}
4217 4218 4219
	if (pvolume_info->cache_ro) {
		cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
4220 4221 4222 4223
	} else if (pvolume_info->cache_rw) {
		cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
					    CIFS_MOUNT_RW_CACHE);
4224
	}
4225 4226
	if (pvolume_info->mfsymlinks) {
		if (pvolume_info->sfu_emul) {
4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238
			/*
			 * Our SFU ("Services for Unix" emulation does not allow
			 * creating symlinks but does allow reading existing SFU
			 * symlinks (it does allow both creating and reading SFU
			 * style mknod and FIFOs though). When "mfsymlinks" and
			 * "sfu" are both enabled at the same time, it allows
			 * reading both types of symlinks, but will only create
			 * them with mfsymlinks format. This allows better
			 * Apple compatibility (probably better for Samba too)
			 * while still recognizing old Windows style symlinks.
			 */
			cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
4239
		}
4240
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
4241
	}
S
Steve French 已提交
4242 4243

	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
4244
		cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
4245 4246 4247 4248 4249 4250 4251 4252

	if (pvolume_info->prepath) {
		cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
		if (cifs_sb->prepath == NULL)
			return -ENOMEM;
	}

	return 0;
4253 4254
}

P
Paulo Alcantara 已提交
4255 4256
void
cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
I
Igor Mammedov 已提交
4257
{
4258
	kfree(volume_info->username);
I
Igor Mammedov 已提交
4259
	kzfree(volume_info->password);
4260
	kfree(volume_info->UNC);
4261 4262
	kfree(volume_info->domainname);
	kfree(volume_info->iocharset);
I
Igor Mammedov 已提交
4263
	kfree(volume_info->prepath);
J
Jeff Layton 已提交
4264 4265 4266 4267 4268 4269 4270
}

void
cifs_cleanup_volume_info(struct smb_vol *volume_info)
{
	if (!volume_info)
		return;
P
Paulo Alcantara 已提交
4271
	cifs_cleanup_volume_info_contents(volume_info);
I
Igor Mammedov 已提交
4272 4273 4274
	kfree(volume_info);
}

P
Paulo Alcantara 已提交
4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334
/* Release all succeed connections */
static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
				   unsigned int xid,
				   struct TCP_Server_Info *server,
				   struct cifs_ses *ses, struct cifs_tcon *tcon)
{
	int rc = 0;

	if (tcon)
		cifs_put_tcon(tcon);
	else if (ses)
		cifs_put_smb_ses(ses);
	else if (server)
		cifs_put_tcp_session(server, 0);
	cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
	free_xid(xid);
}

/* Get connections for tcp, ses and tcon */
static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
			   unsigned int *xid,
			   struct TCP_Server_Info **nserver,
			   struct cifs_ses **nses, struct cifs_tcon **ntcon)
{
	int rc = 0;
	struct TCP_Server_Info *server;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;

	*nserver = NULL;
	*nses = NULL;
	*ntcon = NULL;

	*xid = get_xid();

	/* get a reference to a tcp session */
	server = cifs_get_tcp_session(vol);
	if (IS_ERR(server)) {
		rc = PTR_ERR(server);
		return rc;
	}

	*nserver = server;

	if ((vol->max_credits < 20) || (vol->max_credits > 60000))
		server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
	else
		server->max_credits = vol->max_credits;

	/* get a reference to a SMB session */
	ses = cifs_get_smb_ses(server, vol);
	if (IS_ERR(ses)) {
		rc = PTR_ERR(ses);
		return rc;
	}

	*nses = ses;

	if ((vol->persistent == true) && (!(ses->server->capabilities &
					    SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
4335
		cifs_server_dbg(VFS, "persistent handles not supported by server\n");
P
Paulo Alcantara 已提交
4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366
		return -EOPNOTSUPP;
	}

	/* search for existing tcon to this server share */
	tcon = cifs_get_tcon(ses, vol);
	if (IS_ERR(tcon)) {
		rc = PTR_ERR(tcon);
		return rc;
	}

	*ntcon = tcon;

	/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
	if (tcon->posix_extensions)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;

	/* tell server which Unix caps we support */
	if (cap_unix(tcon->ses)) {
		/*
		 * reset of caps checks mount to see if unix extensions disabled
		 * for just this mount.
		 */
		reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
		if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
		    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
		     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
			return -EACCES;
	} else
		tcon->unix_ext = 0; /* server does not support them */

	/* do not care if a following call succeed - informational */
4367
	if (!tcon->pipe && server->ops->qfs_tcon) {
P
Paulo Alcantara 已提交
4368
		server->ops->qfs_tcon(*xid, tcon);
4369 4370
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
			if (tcon->fsDevInfo.DeviceCharacteristics &
4371
			    cpu_to_le32(FILE_READ_ONLY_DEVICE))
4372
				cifs_dbg(VFS, "mounted to read only share\n");
4373 4374
			else if ((cifs_sb->mnt_cifs_flags &
				  CIFS_MOUNT_RW_CACHE) == 0)
4375
				cifs_dbg(VFS, "read only mount of RW share\n");
4376
			/* no need to log a RW mount of a typical RW share */
4377 4378
		}
	}
P
Paulo Alcantara 已提交
4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410

	cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
	cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);

	return 0;
}

static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
			     struct cifs_tcon *tcon)
{
	struct tcon_link *tlink;

	/* hang the tcon off of the superblock */
	tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
	if (tlink == NULL)
		return -ENOMEM;

	tlink->tl_uid = ses->linux_uid;
	tlink->tl_tcon = tcon;
	tlink->tl_time = jiffies;
	set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
	set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);

	cifs_sb->master_tlink = tlink;
	spin_lock(&cifs_sb->tlink_tree_lock);
	tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
	spin_unlock(&cifs_sb->tlink_tree_lock);

	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
				TLINK_IDLE_EXPIRE);
	return 0;
}
J
Jeff Layton 已提交
4411

S
Steve French 已提交
4412
#ifdef CONFIG_CIFS_DFS_UPCALL
4413 4414 4415 4416
/*
 * cifs_build_path_to_root returns full path to root when we do not have an
 * exiting connection (tcon)
 */
I
Igor Mammedov 已提交
4417
static char *
4418
build_unc_path_to_root(const struct smb_vol *vol,
4419
		       const struct cifs_sb_info *cifs_sb, bool useppath)
I
Igor Mammedov 已提交
4420
{
4421
	char *full_path, *pos;
4422 4423
	unsigned int pplen = useppath && vol->prepath ?
		strlen(vol->prepath) + 1 : 0;
4424
	unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
I
Igor Mammedov 已提交
4425

4426 4427 4428
	if (unc_len > MAX_TREE_SIZE)
		return ERR_PTR(-EINVAL);

4429
	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
I
Igor Mammedov 已提交
4430 4431 4432
	if (full_path == NULL)
		return ERR_PTR(-ENOMEM);

4433
	memcpy(full_path, vol->UNC, unc_len);
4434 4435 4436
	pos = full_path + unc_len;

	if (pplen) {
4437
		*pos = CIFS_DIR_SEP(cifs_sb);
4438
		memcpy(pos + 1, vol->prepath, pplen);
4439 4440 4441 4442
		pos += pplen;
	}

	*pos = '\0'; /* add trailing null */
4443
	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
4444
	cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
I
Igor Mammedov 已提交
4445 4446
	return full_path;
}
4447

4448 4449 4450
/**
 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
 *
4451
 *
4452 4453 4454
 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
 * to a string containing updated options for the submount.  Otherwise it
 * will be left untouched.
4455 4456 4457 4458 4459
 *
 * Returns the rc from get_dfs_path to the caller, which can be used to
 * determine whether there were referrals.
 */
static int
4460
expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
4461
		    struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
4462
		    int check_prefix)
4463 4464
{
	int rc;
4465
	struct dfs_info3_param referral = {0};
4466 4467
	char *full_path = NULL, *ref_path = NULL, *mdata = NULL;

4468 4469 4470
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
		return -EREMOTE;

4471
	full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
4472 4473 4474 4475 4476 4477
	if (IS_ERR(full_path))
		return PTR_ERR(full_path);

	/* For DFS paths, skip the first '\' of the UNC */
	ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;

4478 4479 4480
	rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
			    ref_path, &referral, NULL);
	if (!rc) {
4481 4482 4483
		char *fake_devname = NULL;

		mdata = cifs_compose_mount_options(cifs_sb->mountdata,
4484
						   full_path + 1, &referral,
4485
						   &fake_devname);
4486
		free_dfs_info_param(&referral);
4487

4488 4489 4490
		if (IS_ERR(mdata)) {
			rc = PTR_ERR(mdata);
			mdata = NULL;
J
Jeff Layton 已提交
4491
		} else {
P
Paulo Alcantara 已提交
4492
			cifs_cleanup_volume_info_contents(volume_info);
J
Jeff Layton 已提交
4493
			rc = cifs_setup_volume_info(volume_info, mdata,
4494
						    fake_devname, false);
4495
		}
J
Jeff Layton 已提交
4496 4497
		kfree(fake_devname);
		kfree(cifs_sb->mountdata);
4498
		cifs_sb->mountdata = mdata;
4499 4500 4501 4502
	}
	kfree(full_path);
	return rc;
}
4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524

static inline int get_next_dfs_tgt(const char *path,
				   struct dfs_cache_tgt_list *tgt_list,
				   struct dfs_cache_tgt_iterator **tgt_it)
{
	if (!*tgt_it)
		*tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
	else
		*tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
	return !*tgt_it ? -EHOSTDOWN : 0;
}

static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
			   struct smb_vol *fake_vol, struct smb_vol *vol)
{
	const char *tgt = dfs_cache_get_tgt_name(tgt_it);
	int len = strlen(tgt) + 2;
	char *new_unc;

	new_unc = kmalloc(len, GFP_KERNEL);
	if (!new_unc)
		return -ENOMEM;
4525
	scnprintf(new_unc, len, "\\%s", tgt);
4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551

	kfree(vol->UNC);
	vol->UNC = new_unc;

	if (fake_vol->prepath) {
		kfree(vol->prepath);
		vol->prepath = fake_vol->prepath;
		fake_vol->prepath = NULL;
	}
	memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));

	return 0;
}

static int setup_dfs_tgt_conn(const char *path,
			      const struct dfs_cache_tgt_iterator *tgt_it,
			      struct cifs_sb_info *cifs_sb,
			      struct smb_vol *vol,
			      unsigned int *xid,
			      struct TCP_Server_Info **server,
			      struct cifs_ses **ses,
			      struct cifs_tcon **tcon)
{
	int rc;
	struct dfs_info3_param ref = {0};
	char *mdata = NULL, *fake_devname = NULL;
4552
	struct smb_vol fake_vol = {NULL};
4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639

	cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);

	rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
	if (rc)
		return rc;

	mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
					   &fake_devname);
	free_dfs_info_param(&ref);

	if (IS_ERR(mdata)) {
		rc = PTR_ERR(mdata);
		mdata = NULL;
	} else {
		cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
		rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
					    false);
	}
	kfree(mdata);
	kfree(fake_devname);

	if (!rc) {
		/*
		 * We use a 'fake_vol' here because we need pass it down to the
		 * mount_{get,put} functions to test connection against new DFS
		 * targets.
		 */
		mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
		rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
				     tcon);
		if (!rc) {
			/*
			 * We were able to connect to new target server.
			 * Update current volume info with new target server.
			 */
			rc = update_vol_info(tgt_it, &fake_vol, vol);
		}
	}
	cifs_cleanup_volume_info_contents(&fake_vol);
	return rc;
}

static int mount_do_dfs_failover(const char *path,
				 struct cifs_sb_info *cifs_sb,
				 struct smb_vol *vol,
				 struct cifs_ses *root_ses,
				 unsigned int *xid,
				 struct TCP_Server_Info **server,
				 struct cifs_ses **ses,
				 struct cifs_tcon **tcon)
{
	int rc;
	struct dfs_cache_tgt_list tgt_list;
	struct dfs_cache_tgt_iterator *tgt_it = NULL;

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
		return -EOPNOTSUPP;

	rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
	if (rc)
		return rc;

	for (;;) {
		/* Get next DFS target server - if any */
		rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
		if (rc)
			break;
		/* Connect to next DFS target */
		rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
					ses, tcon);
		if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
			break;
	}
	if (!rc) {
		/*
		 * Update DFS target hint in DFS referral cache with the target
		 * server we successfully reconnected to.
		 */
		rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
					      cifs_sb->local_nls,
					      cifs_remap(cifs_sb), path,
					      tgt_it);
	}
	dfs_cache_free_tgts(&tgt_list);
	return rc;
}
S
Steve French 已提交
4640
#endif
I
Igor Mammedov 已提交
4641

4642
int
4643
cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
4644
			const char *devname, bool is_smb3)
L
Linus Torvalds 已提交
4645
{
4646
	int rc = 0;
L
Linus Torvalds 已提交
4647

4648
	if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
4649
		return -EINVAL;
L
Linus Torvalds 已提交
4650

4651
	if (volume_info->nullauth) {
4652
		cifs_dbg(FYI, "Anonymous login\n");
J
Jeff Layton 已提交
4653 4654
		kfree(volume_info->username);
		volume_info->username = NULL;
4655
	} else if (volume_info->username) {
L
Linus Torvalds 已提交
4656
		/* BB fixme parse for domain name here */
4657
		cifs_dbg(FYI, "Username: %s\n", volume_info->username);
L
Linus Torvalds 已提交
4658
	} else {
4659
		cifs_dbg(VFS, "No username specified\n");
4660 4661
	/* In userspace mount helper we can get user name from alternate
	   locations such as env variables and files on disk */
4662
		return -EINVAL;
L
Linus Torvalds 已提交
4663 4664 4665
	}

	/* this is needed for ASCII cp to Unicode converts */
4666
	if (volume_info->iocharset == NULL) {
4667 4668
		/* load_nls_default cannot return null */
		volume_info->local_nls = load_nls_default();
L
Linus Torvalds 已提交
4669
	} else {
4670 4671
		volume_info->local_nls = load_nls(volume_info->iocharset);
		if (volume_info->local_nls == NULL) {
4672
			cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
4673
				 volume_info->iocharset);
4674
			return -ELIBACC;
L
Linus Torvalds 已提交
4675 4676
		}
	}
4677 4678 4679 4680

	return rc;
}

4681
struct smb_vol *
4682
cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
4683 4684 4685 4686
{
	int rc;
	struct smb_vol *volume_info;

4687
	volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
4688 4689 4690
	if (!volume_info)
		return ERR_PTR(-ENOMEM);

4691
	rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
4692 4693 4694 4695 4696 4697 4698 4699
	if (rc) {
		cifs_cleanup_volume_info(volume_info);
		volume_info = ERR_PTR(rc);
	}

	return volume_info;
}

4700 4701 4702 4703 4704
static int
cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
					unsigned int xid,
					struct cifs_tcon *tcon,
					struct cifs_sb_info *cifs_sb,
4705 4706
					char *full_path,
					int added_treename)
4707 4708 4709 4710
{
	int rc;
	char *s;
	char sep, tmp;
4711
	int skip = added_treename ? 1 : 0;
4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725

	sep = CIFS_DIR_SEP(cifs_sb);
	s = full_path;

	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
	while (rc == 0) {
		/* skip separators */
		while (*s == sep)
			s++;
		if (!*s)
			break;
		/* next separator */
		while (*s && *s != sep)
			s++;
4726 4727 4728 4729 4730 4731 4732 4733
		/*
		 * if the treename is added, we then have to skip the first
		 * part within the separators
		 */
		if (skip) {
			skip = 0;
			continue;
		}
4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746
		/*
		 * temporarily null-terminate the path at the end of
		 * the current component
		 */
		tmp = *s;
		*s = 0;
		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
						     full_path);
		*s = tmp;
	}
	return rc;
}

P
Paulo Alcantara 已提交
4747 4748 4749 4750 4751 4752 4753 4754
/*
 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
 * otherwise 0.
 */
static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
			  const unsigned int xid,
			  struct TCP_Server_Info *server,
			  struct cifs_tcon *tcon)
4755
{
4756
	int rc;
P
Paulo Alcantara 已提交
4757
	char *full_path;
4758

P
Paulo Alcantara 已提交
4759 4760
	if (!server->ops->is_path_accessible)
		return -EOPNOTSUPP;
4761

P
Paulo Alcantara 已提交
4762 4763 4764 4765 4766 4767 4768
	/*
	 * cifs_build_path_to_root works only when we have a valid tcon
	 */
	full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
					    tcon->Flags & SMB_SHARE_IS_IN_DFS);
	if (full_path == NULL)
		return -ENOMEM;
4769

P
Paulo Alcantara 已提交
4770
	cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
L
Linus Torvalds 已提交
4771

P
Paulo Alcantara 已提交
4772 4773 4774 4775 4776
	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
					     full_path);
	if (rc != 0 && rc != -EREMOTE) {
		kfree(full_path);
		return rc;
4777
	}
S
Steve French 已提交
4778

P
Paulo Alcantara 已提交
4779 4780
	if (rc != -EREMOTE) {
		rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4781
			cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
P
Paulo Alcantara 已提交
4782
		if (rc != 0) {
4783
			cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
P
Paulo Alcantara 已提交
4784 4785 4786 4787
				 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
			rc = 0;
		}
4788
	}
I
Igor Mammedov 已提交
4789

P
Paulo Alcantara 已提交
4790 4791 4792
	kfree(full_path);
	return rc;
}
4793

P
Paulo Alcantara 已提交
4794
#ifdef CONFIG_CIFS_DFS_UPCALL
4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805
static inline void set_root_tcon(struct cifs_sb_info *cifs_sb,
				 struct cifs_tcon *tcon,
				 struct cifs_tcon **root)
{
	spin_lock(&cifs_tcp_ses_lock);
	tcon->tc_count++;
	tcon->remap = cifs_remap(cifs_sb);
	spin_unlock(&cifs_tcp_ses_lock);
	*root = tcon;
}

P
Paulo Alcantara 已提交
4806 4807 4808 4809 4810
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
{
	int rc = 0;
	unsigned int xid;
	struct cifs_ses *ses;
4811
	struct cifs_tcon *root_tcon = NULL;
P
Paulo Alcantara 已提交
4812 4813
	struct cifs_tcon *tcon = NULL;
	struct TCP_Server_Info *server;
4814
	char *root_path = NULL, *full_path = NULL;
4815
	char *old_mountdata, *origin_mountdata = NULL;
P
Paulo Alcantara 已提交
4816
	int count;
4817

P
Paulo Alcantara 已提交
4818 4819
	rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
	if (!rc && tcon) {
4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830
		/* If not a standalone DFS root, then check if path is remote */
		rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
				    cifs_remap(cifs_sb), vol->UNC + 1, NULL,
				    NULL);
		if (rc) {
			rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
			if (!rc)
				goto out;
			if (rc != -EREMOTE)
				goto error;
		}
P
Paulo Alcantara 已提交
4831
	}
4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843
	/*
	 * If first DFS target server went offline and we failed to connect it,
	 * server and ses pointers are NULL at this point, though we still have
	 * chance to get a cached DFS referral in expand_dfs_referral() and
	 * retry next target available in it.
	 *
	 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
	 * performed against DFS path and *no* requests will be sent to server
	 * for any new DFS referrals. Hence it's safe to skip checking whether
	 * server or ses ptr is NULL.
	 */
	if (rc == -EACCES || rc == -EOPNOTSUPP)
P
Paulo Alcantara 已提交
4844
		goto error;
4845

4846 4847 4848 4849 4850 4851
	root_path = build_unc_path_to_root(vol, cifs_sb, false);
	if (IS_ERR(root_path)) {
		rc = PTR_ERR(root_path);
		root_path = NULL;
		goto error;
	}
4852

4853 4854 4855 4856 4857 4858
	full_path = build_unc_path_to_root(vol, cifs_sb, true);
	if (IS_ERR(full_path)) {
		rc = PTR_ERR(full_path);
		full_path = NULL;
		goto error;
	}
4859 4860 4861 4862 4863 4864 4865
	/*
	 * Perform an unconditional check for whether there are DFS
	 * referrals for this path without prefix, to provide support
	 * for DFS referrals from w2k8 servers which don't seem to respond
	 * with PATH_NOT_COVERED to requests that include the prefix.
	 * Chase the referral if found, otherwise continue normally.
	 */
P
Paulo Alcantara 已提交
4866 4867 4868 4869 4870 4871
	old_mountdata = cifs_sb->mountdata;
	(void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);

	if (cifs_sb->mountdata == NULL) {
		rc = -ENOENT;
		goto error;
4872 4873
	}

4874 4875 4876 4877 4878 4879 4880 4881
	/* Save DFS root volume information for DFS refresh worker */
	origin_mountdata = kstrndup(cifs_sb->mountdata,
				    strlen(cifs_sb->mountdata), GFP_KERNEL);
	if (!origin_mountdata) {
		rc = -ENOMEM;
		goto error;
	}

P
Paulo Alcantara 已提交
4882 4883 4884 4885 4886 4887 4888 4889
	if (cifs_sb->mountdata != old_mountdata) {
		/* If we were redirected, reconnect to new target server */
		mount_put_conns(cifs_sb, xid, server, ses, tcon);
		rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
	}
	if (rc) {
		if (rc == -EACCES || rc == -EOPNOTSUPP)
			goto error;
4890 4891 4892 4893 4894
		/* Perform DFS failover to any other DFS targets */
		rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
					   &xid, &server, &ses, &tcon);
		if (rc)
			goto error;
P
Paulo Alcantara 已提交
4895 4896
	}

4897 4898 4899 4900 4901 4902 4903 4904 4905 4906
	kfree(root_path);
	root_path = build_unc_path_to_root(vol, cifs_sb, false);
	if (IS_ERR(root_path)) {
		rc = PTR_ERR(root_path);
		root_path = NULL;
		goto error;
	}
	/* Cache out resolved root server */
	(void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
			     root_path + 1, NULL, NULL);
4907
	kfree(root_path);
4908 4909
	root_path = NULL;

4910
	set_root_tcon(cifs_sb, tcon, &root_tcon);
4911

P
Paulo Alcantara 已提交
4912 4913 4914 4915 4916
	for (count = 1; ;) {
		if (!rc && tcon) {
			rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
			if (!rc || rc != -EREMOTE)
				break;
4917
		}
4918
		/*
P
Paulo Alcantara 已提交
4919 4920 4921 4922
		 * BB: when we implement proper loop detection,
		 *     we will remove this check. But now we need it
		 *     to prevent an indefinite loop if 'DFS tree' is
		 *     misconfigured (i.e. has loops).
4923
		 */
P
Paulo Alcantara 已提交
4924
		if (count++ > MAX_NESTED_LINKS) {
4925
			rc = -ELOOP;
P
Paulo Alcantara 已提交
4926
			break;
4927
		}
I
Igor Mammedov 已提交
4928

4929 4930 4931 4932 4933 4934 4935 4936
		kfree(full_path);
		full_path = build_unc_path_to_root(vol, cifs_sb, true);
		if (IS_ERR(full_path)) {
			rc = PTR_ERR(full_path);
			full_path = NULL;
			break;
		}

P
Paulo Alcantara 已提交
4937
		old_mountdata = cifs_sb->mountdata;
4938
		rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
P
Paulo Alcantara 已提交
4939 4940 4941
					 true);
		if (rc)
			break;
4942

P
Paulo Alcantara 已提交
4943 4944 4945 4946
		if (cifs_sb->mountdata != old_mountdata) {
			mount_put_conns(cifs_sb, xid, server, ses, tcon);
			rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
					     &tcon);
4947 4948 4949 4950 4951 4952 4953 4954 4955
			/*
			 * Ensure that DFS referrals go through new root server.
			 */
			if (!rc && tcon &&
			    (tcon->share_flags & (SHI1005_FLAGS_DFS |
						  SHI1005_FLAGS_DFS_ROOT))) {
				cifs_put_tcon(root_tcon);
				set_root_tcon(cifs_sb, tcon, &root_tcon);
			}
P
Paulo Alcantara 已提交
4956 4957
		}
		if (rc) {
4958 4959 4960 4961 4962 4963
			if (rc == -EACCES || rc == -EOPNOTSUPP)
				break;
			/* Perform DFS failover to any other DFS targets */
			rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
						   root_tcon->ses, &xid,
						   &server, &ses, &tcon);
P
Paulo Alcantara 已提交
4964 4965 4966
			if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
			    !ses)
				goto error;
I
Igor Mammedov 已提交
4967 4968
		}
	}
4969
	cifs_put_tcon(root_tcon);
I
Igor Mammedov 已提交
4970

4971
	if (rc)
P
Paulo Alcantara 已提交
4972
		goto error;
4973

4974 4975 4976 4977 4978 4979 4980 4981
	spin_lock(&cifs_tcp_ses_lock);
	if (!tcon->dfs_path) {
		/* Save full path in new tcon to do failover when reconnecting tcons */
		tcon->dfs_path = full_path;
		full_path = NULL;
		tcon->remap = cifs_remap(cifs_sb);
	}
	cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
4982 4983
					    strlen(tcon->dfs_path),
					    GFP_ATOMIC);
4984 4985 4986 4987 4988 4989 4990
	if (!cifs_sb->origin_fullpath) {
		spin_unlock(&cifs_tcp_ses_lock);
		rc = -ENOMEM;
		goto error;
	}
	spin_unlock(&cifs_tcp_ses_lock);

4991
	rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
4992 4993 4994 4995
	if (rc) {
		kfree(cifs_sb->origin_fullpath);
		goto error;
	}
4996 4997 4998 4999 5000 5001
	/*
	 * After reconnecting to a different server, unique ids won't
	 * match anymore, so we disable serverino. This prevents
	 * dentry revalidation to think the dentry are stale (ESTALE).
	 */
	cifs_autodisable_serverino(cifs_sb);
P
Paulo Alcantara 已提交
5002 5003
out:
	free_xid(xid);
5004
	cifs_try_adding_channels(ses);
P
Paulo Alcantara 已提交
5005
	return mount_setup_tlink(cifs_sb, ses, tcon);
5006

P
Paulo Alcantara 已提交
5007
error:
5008 5009
	kfree(full_path);
	kfree(root_path);
5010
	kfree(origin_mountdata);
P
Paulo Alcantara 已提交
5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021
	mount_put_conns(cifs_sb, xid, server, ses, tcon);
	return rc;
}
#else
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
{
	int rc = 0;
	unsigned int xid;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
5022

P
Paulo Alcantara 已提交
5023 5024 5025
	rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
	if (rc)
		goto error;
5026

P
Paulo Alcantara 已提交
5027 5028 5029 5030 5031 5032
	if (tcon) {
		rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
		if (rc == -EREMOTE)
			rc = -EOPNOTSUPP;
		if (rc)
			goto error;
I
Igor Mammedov 已提交
5033 5034
	}

5035
	free_xid(xid);
P
Paulo Alcantara 已提交
5036 5037 5038 5039 5040

	return mount_setup_tlink(cifs_sb, ses, tcon);

error:
	mount_put_conns(cifs_sb, xid, server, ses, tcon);
L
Linus Torvalds 已提交
5041 5042
	return rc;
}
P
Paulo Alcantara 已提交
5043
#endif
L
Linus Torvalds 已提交
5044

5045
/*
A
Aurelien Aptel 已提交
5046
 * Issue a TREE_CONNECT request.
5047
 */
L
Linus Torvalds 已提交
5048
int
5049
CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
5050
	 const char *tree, struct cifs_tcon *tcon,
L
Linus Torvalds 已提交
5051 5052 5053 5054 5055 5056 5057 5058
	 const struct nls_table *nls_codepage)
{
	struct smb_hdr *smb_buffer;
	struct smb_hdr *smb_buffer_response;
	TCONX_REQ *pSMB;
	TCONX_RSP *pSMBr;
	unsigned char *bcc_ptr;
	int rc = 0;
5059 5060
	int length;
	__u16 bytes_left, count;
L
Linus Torvalds 已提交
5061 5062 5063 5064 5065

	if (ses == NULL)
		return -EIO;

	smb_buffer = cifs_buf_get();
S
Steve French 已提交
5066
	if (smb_buffer == NULL)
L
Linus Torvalds 已提交
5067
		return -ENOMEM;
S
Steve French 已提交
5068

L
Linus Torvalds 已提交
5069 5070 5071 5072
	smb_buffer_response = smb_buffer;

	header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
			NULL /*no tid */ , 4 /*wct */ );
5073

5074
	smb_buffer->Mid = get_next_mid(ses->server);
L
Linus Torvalds 已提交
5075 5076 5077 5078 5079 5080 5081
	smb_buffer->Uid = ses->Suid;
	pSMB = (TCONX_REQ *) smb_buffer;
	pSMBr = (TCONX_RSP *) smb_buffer_response;

	pSMB->AndXCommand = 0xFF;
	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
	bcc_ptr = &pSMB->Password[0];
A
Aurelien Aptel 已提交
5082
	if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
5083
		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
5084
		*bcc_ptr = 0; /* password is null byte */
5085
		bcc_ptr++;              /* skip password */
5086
		/* already aligned so no need to do it below */
5087
	} else {
5088
		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
5089 5090 5091
		/* BB FIXME add code to fail this if NTLMv2 or Kerberos
		   specified as required (when that support is added to
		   the vfs in the future) as only NTLM or the much
5092
		   weaker LANMAN (which we do not send by default) is accepted
5093 5094
		   by Samba (not sure whether other servers allow
		   NTLMv2 password here) */
5095
#ifdef CONFIG_CIFS_WEAK_PW_HASH
5096
		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
5097
		    (ses->sectype == LANMAN))
5098
			calc_lanman_hash(tcon->password, ses->server->cryptkey,
5099
					 ses->server->sec_mode &
5100 5101
					    SECMODE_PW_ENCRYPT ? true : false,
					 bcc_ptr);
5102 5103
		else
#endif /* CIFS_WEAK_PW_HASH */
5104
		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
5105
					bcc_ptr, nls_codepage);
5106 5107 5108 5109 5110 5111
		if (rc) {
			cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
				 __func__, rc);
			cifs_buf_release(smb_buffer);
			return rc;
		}
5112

5113
		bcc_ptr += CIFS_AUTH_RESP_SIZE;
S
Steve French 已提交
5114
		if (ses->capabilities & CAP_UNICODE) {
5115 5116 5117 5118
			/* must align unicode strings */
			*bcc_ptr = 0; /* null byte password */
			bcc_ptr++;
		}
5119
	}
L
Linus Torvalds 已提交
5120

5121
	if (ses->server->sign)
L
Linus Torvalds 已提交
5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132
		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;

	if (ses->capabilities & CAP_STATUS32) {
		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
	}
	if (ses->capabilities & CAP_DFS) {
		smb_buffer->Flags2 |= SMBFLG2_DFS;
	}
	if (ses->capabilities & CAP_UNICODE) {
		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
		length =
5133
		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
5134
			6 /* max utf8 char length in bytes */ *
5135 5136
			(/* server len*/ + 256 /* share len */), nls_codepage);
		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
L
Linus Torvalds 已提交
5137 5138 5139 5140 5141 5142 5143 5144 5145
		bcc_ptr += 2;	/* skip trailing null */
	} else {		/* ASCII */
		strcpy(bcc_ptr, tree);
		bcc_ptr += strlen(tree) + 1;
	}
	strcpy(bcc_ptr, "?????");
	bcc_ptr += strlen("?????");
	bcc_ptr += 1;
	count = bcc_ptr - &pSMB->Password[0];
5146 5147
	pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
					pSMB->hdr.smb_buf_length) + count);
L
Linus Torvalds 已提交
5148 5149
	pSMB->ByteCount = cpu_to_le16(count);

5150
	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
5151
			 0);
L
Linus Torvalds 已提交
5152 5153

	/* above now done in SendReceive */
A
Aurelien Aptel 已提交
5154
	if (rc == 0) {
5155 5156
		bool is_unicode;

L
Linus Torvalds 已提交
5157
		tcon->tidStatus = CifsGood;
S
Steve French 已提交
5158
		tcon->need_reconnect = false;
L
Linus Torvalds 已提交
5159 5160
		tcon->tid = smb_buffer_response->Tid;
		bcc_ptr = pByteArea(smb_buffer_response);
5161
		bytes_left = get_bcc(smb_buffer_response);
5162
		length = strnlen(bcc_ptr, bytes_left - 2);
5163 5164 5165 5166 5167
		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
			is_unicode = true;
		else
			is_unicode = false;

5168

5169
		/* skip service field (NB: this field is always ASCII) */
5170 5171 5172
		if (length == 3) {
			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
			    (bcc_ptr[2] == 'C')) {
5173
				cifs_dbg(FYI, "IPC connection\n");
A
Aurelien Aptel 已提交
5174 5175
				tcon->ipc = true;
				tcon->pipe = true;
5176 5177 5178 5179
			}
		} else if (length == 2) {
			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
				/* the most common case */
5180
				cifs_dbg(FYI, "disk share connection\n");
5181 5182
			}
		}
5183
		bcc_ptr += length + 1;
5184
		bytes_left -= (length + 1);
5185
		strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
5186 5187

		/* mostly informational -- no need to fail on error here */
5188
		kfree(tcon->nativeFileSystem);
5189
		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
5190
						      bytes_left, is_unicode,
5191 5192
						      nls_codepage);

5193
		cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
5194

S
Steve French 已提交
5195
		if ((smb_buffer_response->WordCount == 3) ||
S
Steve French 已提交
5196 5197
			 (smb_buffer_response->WordCount == 7))
			/* field is in same location */
5198 5199 5200
			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
		else
			tcon->Flags = 0;
5201
		cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
L
Linus Torvalds 已提交
5202 5203
	}

5204
	cifs_buf_release(smb_buffer);
L
Linus Torvalds 已提交
5205 5206 5207
	return rc;
}

5208 5209 5210 5211 5212 5213 5214
static void delayed_free(struct rcu_head *p)
{
	struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
	unload_nls(sbi->local_nls);
	kfree(sbi);
}

A
Al Viro 已提交
5215 5216
void
cifs_umount(struct cifs_sb_info *cifs_sb)
L
Linus Torvalds 已提交
5217
{
J
Jeff Layton 已提交
5218 5219 5220
	struct rb_root *root = &cifs_sb->tlink_tree;
	struct rb_node *node;
	struct tcon_link *tlink;
5221

5222 5223
	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);

J
Jeff Layton 已提交
5224 5225 5226 5227 5228 5229
	spin_lock(&cifs_sb->tlink_tree_lock);
	while ((node = rb_first(root))) {
		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
		cifs_get_tlink(tlink);
		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
		rb_erase(node, root);
L
Linus Torvalds 已提交
5230

J
Jeff Layton 已提交
5231 5232 5233 5234 5235
		spin_unlock(&cifs_sb->tlink_tree_lock);
		cifs_put_tlink(tlink);
		spin_lock(&cifs_sb->tlink_tree_lock);
	}
	spin_unlock(&cifs_sb->tlink_tree_lock);
5236

5237
	kfree(cifs_sb->mountdata);
5238
	kfree(cifs_sb->prepath);
5239
#ifdef CONFIG_CIFS_DFS_UPCALL
5240
	dfs_cache_del_vol(cifs_sb->origin_fullpath);
5241 5242
	kfree(cifs_sb->origin_fullpath);
#endif
5243
	call_rcu(&cifs_sb->rcu, delayed_free);
5244
}
L
Linus Torvalds 已提交
5245

5246 5247
int
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
L
Linus Torvalds 已提交
5248 5249
{
	int rc = 0;
5250
	struct TCP_Server_Info *server = cifs_ses_server(ses);
L
Linus Torvalds 已提交
5251

5252 5253 5254
	if (!server->ops->need_neg || !server->ops->negotiate)
		return -ENOSYS;

5255
	/* only send once per connect */
5256
	if (!server->ops->need_neg(server))
5257 5258
		return 0;

5259
	rc = server->ops->negotiate(xid, ses);
5260 5261
	if (rc == 0) {
		spin_lock(&GlobalMid_Lock);
5262
		if (server->tcpStatus == CifsNeedNegotiate)
5263 5264 5265 5266 5267 5268 5269 5270 5271
			server->tcpStatus = CifsGood;
		else
			rc = -EHOSTDOWN;
		spin_unlock(&GlobalMid_Lock);
	}

	return rc;
}

5272 5273 5274
int
cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
		   struct nls_table *nls_info)
5275
{
5276
	int rc = -ENOSYS;
5277
	struct TCP_Server_Info *server = cifs_ses_server(ses);
5278

5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291
	if (!ses->binding) {
		ses->capabilities = server->capabilities;
		if (linuxExtEnabled == 0)
			ses->capabilities &= (~server->vals->cap_unix);

		if (ses->auth_key.response) {
			cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
				 ses->auth_key.response);
			kfree(ses->auth_key.response);
			ses->auth_key.response = NULL;
			ses->auth_key.len = 0;
		}
	}
5292

5293
	cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
5294
		 server->sec_mode, server->capabilities, server->timeAdj);
5295

5296 5297 5298
	if (server->ops->sess_setup)
		rc = server->ops->sess_setup(xid, ses, nls_info);

5299
	if (rc)
5300
		cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
5301

L
Linus Torvalds 已提交
5302 5303 5304
	return rc;
}

5305 5306 5307
static int
cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
{
5308 5309 5310 5311
	vol->sectype = ses->sectype;

	/* krb5 is special, since we don't need username or pw */
	if (vol->sectype == Kerberos)
5312 5313 5314 5315 5316
		return 0;

	return cifs_set_cifscreds(vol, ses);
}

5317
static struct cifs_tcon *
5318
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
5319
{
5320
	int rc;
5321 5322 5323
	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
	struct cifs_ses *ses;
	struct cifs_tcon *tcon = NULL;
5324 5325 5326
	struct smb_vol *vol_info;

	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
5327 5328
	if (vol_info == NULL)
		return ERR_PTR(-ENOMEM);
5329 5330 5331 5332 5333 5334 5335

	vol_info->local_nls = cifs_sb->local_nls;
	vol_info->linux_uid = fsuid;
	vol_info->cred_uid = fsuid;
	vol_info->UNC = master_tcon->treeName;
	vol_info->retry = master_tcon->retry;
	vol_info->nocase = master_tcon->nocase;
S
Steve French 已提交
5336
	vol_info->nohandlecache = master_tcon->nohandlecache;
5337 5338
	vol_info->local_lease = master_tcon->local_lease;
	vol_info->no_linux_ext = !master_tcon->unix_ext;
5339 5340
	vol_info->sectype = master_tcon->ses->sectype;
	vol_info->sign = master_tcon->ses->sign;
5341

5342 5343 5344 5345 5346
	rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
	if (rc) {
		tcon = ERR_PTR(rc);
		goto out;
	}
5347 5348

	/* get a reference for the same TCP session */
5349
	spin_lock(&cifs_tcp_ses_lock);
5350
	++master_tcon->ses->server->srv_count;
5351
	spin_unlock(&cifs_tcp_ses_lock);
5352 5353 5354

	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
	if (IS_ERR(ses)) {
5355
		tcon = (struct cifs_tcon *)ses;
5356
		cifs_put_tcp_session(master_tcon->ses->server, 0);
5357 5358 5359 5360 5361 5362 5363 5364 5365
		goto out;
	}

	tcon = cifs_get_tcon(ses, vol_info);
	if (IS_ERR(tcon)) {
		cifs_put_smb_ses(ses);
		goto out;
	}

5366 5367 5368
	/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
	if (tcon->posix_extensions)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
5369

5370
	if (cap_unix(ses))
5371
		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
5372

5373
out:
5374
	kfree(vol_info->username);
5375
	kzfree(vol_info->password);
5376 5377 5378 5379 5380
	kfree(vol_info);

	return tcon;
}

5381
struct cifs_tcon *
5382 5383 5384 5385 5386
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{
	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
}

J
Jeff Layton 已提交
5387 5388
/* find and return a tlink with given uid */
static struct tcon_link *
5389
tlink_rb_search(struct rb_root *root, kuid_t uid)
J
Jeff Layton 已提交
5390 5391 5392 5393 5394 5395 5396
{
	struct rb_node *node = root->rb_node;
	struct tcon_link *tlink;

	while (node) {
		tlink = rb_entry(node, struct tcon_link, tl_rbnode);

5397
		if (uid_gt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
5398
			node = node->rb_left;
5399
		else if (uid_lt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417
			node = node->rb_right;
		else
			return tlink;
	}
	return NULL;
}

/* insert a tcon_link into the tree */
static void
tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
{
	struct rb_node **new = &(root->rb_node), *parent = NULL;
	struct tcon_link *tlink;

	while (*new) {
		tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
		parent = *new;

5418
		if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
J
Jeff Layton 已提交
5419 5420 5421 5422 5423 5424 5425 5426 5427
			new = &((*new)->rb_left);
		else
			new = &((*new)->rb_right);
	}

	rb_link_node(&new_tlink->tl_rbnode, parent, new);
	rb_insert_color(&new_tlink->tl_rbnode, root);
}

5428 5429 5430 5431 5432 5433 5434
/*
 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
 * current task.
 *
 * If the superblock doesn't refer to a multiuser mount, then just return
 * the master tcon for the mount.
 *
5435
 * First, search the rbtree for an existing tcon for this fsuid. If one
5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447
 * exists, then check to see if it's pending construction. If it is then wait
 * for construction to complete. Once it's no longer pending, check to see if
 * it failed and either return an error or retry construction, depending on
 * the timeout.
 *
 * If one doesn't exist then insert a new tcon_link struct into the tree and
 * try to construct a new one.
 */
struct tcon_link *
cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
{
	int ret;
5448
	kuid_t fsuid = current_fsuid();
5449 5450 5451 5452 5453 5454
	struct tcon_link *tlink, *newtlink;

	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
		return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));

	spin_lock(&cifs_sb->tlink_tree_lock);
J
Jeff Layton 已提交
5455
	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5456 5457 5458 5459 5460 5461 5462 5463
	if (tlink)
		cifs_get_tlink(tlink);
	spin_unlock(&cifs_sb->tlink_tree_lock);

	if (tlink == NULL) {
		newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
		if (newtlink == NULL)
			return ERR_PTR(-ENOMEM);
J
Jeff Layton 已提交
5464
		newtlink->tl_uid = fsuid;
5465 5466 5467 5468 5469 5470 5471
		newtlink->tl_tcon = ERR_PTR(-EACCES);
		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
		cifs_get_tlink(newtlink);

		spin_lock(&cifs_sb->tlink_tree_lock);
		/* was one inserted after previous search? */
J
Jeff Layton 已提交
5472
		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5473 5474 5475 5476 5477 5478 5479
		if (tlink) {
			cifs_get_tlink(tlink);
			spin_unlock(&cifs_sb->tlink_tree_lock);
			kfree(newtlink);
			goto wait_for_construction;
		}
		tlink = newtlink;
J
Jeff Layton 已提交
5480 5481
		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
		spin_unlock(&cifs_sb->tlink_tree_lock);
5482 5483 5484 5485 5486 5487
	} else {
wait_for_construction:
		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
				  TASK_INTERRUPTIBLE);
		if (ret) {
			cifs_put_tlink(tlink);
5488
			return ERR_PTR(-ERESTARTSYS);
5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515
		}

		/* if it's good, return it */
		if (!IS_ERR(tlink->tl_tcon))
			return tlink;

		/* return error if we tried this already recently */
		if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
			cifs_put_tlink(tlink);
			return ERR_PTR(-EACCES);
		}

		if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
			goto wait_for_construction;
	}

	tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
	clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
	wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);

	if (IS_ERR(tlink->tl_tcon)) {
		cifs_put_tlink(tlink);
		return ERR_PTR(-EACCES);
	}

	return tlink;
}
5516 5517 5518 5519 5520 5521 5522 5523 5524 5525

/*
 * periodic workqueue job that scans tcon_tree for a superblock and closes
 * out tcons.
 */
static void
cifs_prune_tlinks(struct work_struct *work)
{
	struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
						    prune_tlinks.work);
J
Jeff Layton 已提交
5526
	struct rb_root *root = &cifs_sb->tlink_tree;
5527
	struct rb_node *node;
J
Jeff Layton 已提交
5528 5529
	struct rb_node *tmp;
	struct tcon_link *tlink;
5530

J
Jeff Layton 已提交
5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548
	/*
	 * Because we drop the spinlock in the loop in order to put the tlink
	 * it's not guarded against removal of links from the tree. The only
	 * places that remove entries from the tree are this function and
	 * umounts. Because this function is non-reentrant and is canceled
	 * before umount can proceed, this is safe.
	 */
	spin_lock(&cifs_sb->tlink_tree_lock);
	node = rb_first(root);
	while (node != NULL) {
		tmp = node;
		node = rb_next(tmp);
		tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);

		if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
		    atomic_read(&tlink->tl_count) != 0 ||
		    time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
			continue;
5549

J
Jeff Layton 已提交
5550 5551 5552 5553 5554 5555 5556 5557 5558
		cifs_get_tlink(tlink);
		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
		rb_erase(tmp, root);

		spin_unlock(&cifs_sb->tlink_tree_lock);
		cifs_put_tlink(tlink);
		spin_lock(&cifs_sb->tlink_tree_lock);
	}
	spin_unlock(&cifs_sb->tlink_tree_lock);
5559

J
Jeff Layton 已提交
5560
	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
5561 5562
				TLINK_IDLE_EXPIRE);
}