connect.c 142.8 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/mm.h>
25
#include <linux/sched/signal.h>
L
Linus Torvalds 已提交
26 27
#include <linux/list.h>
#include <linux/wait.h>
28
#include <linux/slab.h>
L
Linus Torvalds 已提交
29 30 31 32
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
#include <linux/mempool.h>
33
#include <linux/delay.h>
34
#include <linux/completion.h>
35
#include <linux/kthread.h>
36
#include <linux/pagevec.h>
37
#include <linux/freezer.h>
38
#include <linux/namei.h>
39
#include <linux/uuid.h>
40
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
41
#include <asm/processor.h>
42
#include <linux/inet.h>
43
#include <linux/module.h>
44
#include <keys/user-type.h>
45
#include <net/ipv6.h>
46
#include <linux/parser.h>
47
#include <linux/bvec.h>
L
Linus Torvalds 已提交
48 49 50 51 52 53 54 55 56
#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"
57
#include "fscache.h"
58
#include "smb2proto.h"
59
#include "smbdirect.h"
60 61 62 63
#include "dns_resolve.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
64
#include "fs_context.h"
L
Linus Torvalds 已提交
65 66

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

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

73 74 75
/* Drop the connection to not overload the server */
#define NUM_STATUS_IO_TIMEOUT   5

76 77 78 79
enum {
	/* Mount options that take no arguments */
	Opt_user_xattr, Opt_nouser_xattr,
	Opt_forceuid, Opt_noforceuid,
J
Jeff Layton 已提交
80
	Opt_forcegid, Opt_noforcegid,
81
	Opt_noblocksend, Opt_noautotune, Opt_nolease,
S
Steve French 已提交
82
	Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete,
83
	Opt_mapposix, Opt_nomapposix,
84 85
	Opt_mapchars, Opt_nomapchars, Opt_sfu,
	Opt_nosfu, Opt_nodfs, Opt_posixpaths,
86
	Opt_noposixpaths, Opt_nounix, Opt_unix,
87 88
	Opt_nocase,
	Opt_brl, Opt_nobrl,
S
Steve French 已提交
89
	Opt_handlecache, Opt_nohandlecache,
90
	Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
91 92 93 94 95 96 97
	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,
98
	Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
99
	Opt_fsc, Opt_mfsymlinks,
100
	Opt_multiuser, Opt_sloppy, Opt_nosharesock,
101
	Opt_persistent, Opt_nopersistent,
S
Steve French 已提交
102
	Opt_resilient, Opt_noresilient,
103
	Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
104
	Opt_multichannel, Opt_nomultichannel,
105
	Opt_compress,
106 107 108 109 110

	/* Mount options which take numeric value */
	Opt_backupuid, Opt_backupgid, Opt_uid,
	Opt_cruid, Opt_gid, Opt_file_mode,
	Opt_dirmode, Opt_port,
111
	Opt_min_enc_offload,
112
	Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
113
	Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
114
	Opt_snapshot, Opt_max_channels,
115 116 117

	/* Mount options which take string value */
	Opt_user, Opt_pass, Opt_ip,
118
	Opt_domain, Opt_srcaddr, Opt_iocharset,
119
	Opt_netbiosname, Opt_servern,
120
	Opt_ver, Opt_vers, Opt_sec, Opt_cache,
121 122 123 124 125 126

	/* Mount options to be ignored */
	Opt_ignore,

	/* Options which could be blank */
	Opt_blank_pass,
127 128
	Opt_blank_user,
	Opt_blank_ip,
129 130 131 132 133 134 135 136 137 138

	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 已提交
139 140
	{ Opt_forcegid, "forcegid" },
	{ Opt_noforcegid, "noforcegid" },
141 142
	{ Opt_noblocksend, "noblocksend" },
	{ Opt_noautotune, "noautotune" },
143
	{ Opt_nolease, "nolease" },
144 145 146 147
	{ Opt_hard, "hard" },
	{ Opt_soft, "soft" },
	{ Opt_perm, "perm" },
	{ Opt_noperm, "noperm" },
S
Steve French 已提交
148
	{ Opt_nodelete, "nodelete" },
149
	{ Opt_mapchars, "mapchars" }, /* SFU style */
150
	{ Opt_nomapchars, "nomapchars" },
151 152
	{ Opt_mapposix, "mapposix" }, /* SFM style */
	{ Opt_nomapposix, "nomapposix" },
153 154 155 156 157 158 159
	{ Opt_sfu, "sfu" },
	{ Opt_nosfu, "nosfu" },
	{ Opt_nodfs, "nodfs" },
	{ Opt_posixpaths, "posixpaths" },
	{ Opt_noposixpaths, "noposixpaths" },
	{ Opt_nounix, "nounix" },
	{ Opt_nounix, "nolinux" },
160 161 162 163
	{ Opt_nounix, "noposix" },
	{ Opt_unix, "unix" },
	{ Opt_unix, "linux" },
	{ Opt_unix, "posix" },
164 165 166 167
	{ Opt_nocase, "nocase" },
	{ Opt_nocase, "ignorecase" },
	{ Opt_brl, "brl" },
	{ Opt_nobrl, "nobrl" },
S
Steve French 已提交
168 169
	{ Opt_handlecache, "handlecache" },
	{ Opt_nohandlecache, "nohandlecache" },
170 171
	{ Opt_nobrl, "nolock" },
	{ Opt_forcemandatorylock, "forcemandatorylock" },
172
	{ Opt_forcemandatorylock, "forcemand" },
173 174
	{ Opt_setuids, "setuids" },
	{ Opt_nosetuids, "nosetuids" },
175
	{ Opt_setuidfromacl, "idsfromsid" },
176 177 178 179 180 181 182 183 184 185 186
	{ 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" },
187
	{ Opt_modesid, "modefromsid" },
188 189 190 191 192 193
	{ Opt_cifsacl, "cifsacl" },
	{ Opt_nocifsacl, "nocifsacl" },
	{ Opt_acl, "acl" },
	{ Opt_noacl, "noacl" },
	{ Opt_locallease, "locallease" },
	{ Opt_sign, "sign" },
194
	{ Opt_ignore_signature, "signloosely" },
195 196 197 198 199
	{ Opt_seal, "seal" },
	{ Opt_noac, "noac" },
	{ Opt_fsc, "fsc" },
	{ Opt_mfsymlinks, "mfsymlinks" },
	{ Opt_multiuser, "multiuser" },
200
	{ Opt_sloppy, "sloppy" },
201
	{ Opt_nosharesock, "nosharesock" },
202 203
	{ Opt_persistent, "persistenthandles"},
	{ Opt_nopersistent, "nopersistenthandles"},
S
Steve French 已提交
204 205
	{ Opt_resilient, "resilienthandles"},
	{ Opt_noresilient, "noresilienthandles"},
206
	{ Opt_domainauto, "domainauto"},
L
Long Li 已提交
207
	{ Opt_rdma, "rdma"},
208 209
	{ Opt_multichannel, "multichannel" },
	{ Opt_nomultichannel, "nomultichannel" },
210 211 212 213 214 215 216 217 218 219

	{ 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" },
220
	{ Opt_min_enc_offload, "esize=%s" },
221
	{ Opt_blocksize, "bsize=%s" },
222 223 224
	{ Opt_rsize, "rsize=%s" },
	{ Opt_wsize, "wsize=%s" },
	{ Opt_actimeo, "actimeo=%s" },
225
	{ Opt_handletimeout, "handletimeout=%s" },
S
Steve French 已提交
226
	{ Opt_echo_interval, "echo_interval=%s" },
227
	{ Opt_max_credits, "max_credits=%s" },
228
	{ Opt_snapshot, "snapshot=%s" },
229
	{ Opt_max_channels, "max_channels=%s" },
230
	{ Opt_compress, "compress=%s" },
231

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

	{ Opt_ignore, "cred" },
	{ Opt_ignore, "credentials" },
262 263
	{ Opt_ignore, "cred=%s" },
	{ Opt_ignore, "credentials=%s" },
264 265 266 267 268 269 270 271 272 273 274 275
	{ 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" },
276
	{ Opt_ignore, "relatime" },
277
	{ Opt_ignore, "_netdev" },
278
	{ Opt_rootfs, "rootfs" },
279 280 281 282

	{ Opt_err, NULL }
};

283 284
static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
J
Jeff Layton 已提交
285
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
286
static void cifs_prune_tlinks(struct work_struct *work);
287 288
static char *extract_hostname(const char *unc);

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
/*
 * 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;
	}
312
	scnprintf(unc, len, "\\\\%s", server->hostname);
313 314 315 316 317 318 319 320 321 322

	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;
	}

323
	spin_lock(&cifs_tcp_ses_lock);
324 325
	rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
				  strlen(ipaddr));
326
	spin_unlock(&cifs_tcp_ses_lock);
327 328 329 330 331 332 333 334 335 336 337
	kfree(ipaddr);

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

338 339
#ifdef CONFIG_CIFS_DFS_UPCALL
/* These functions must be called with server->srv_mutex held */
340 341 342 343
static void reconn_set_next_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)
344 345 346
{
	const char *name;

347
	if (!cifs_sb || !cifs_sb->origin_fullpath)
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
		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 已提交
365 366 367 368
	if (IS_ERR(server->hostname)) {
		cifs_dbg(FYI,
			 "%s: failed to extract hostname from target: %ld\n",
			 __func__, PTR_ERR(server->hostname));
369 370 371 372
	}
}

static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
373
					   struct dfs_cache_tgt_list *tl)
374 375 376 377 378 379
{
	if (!cifs_sb->origin_fullpath)
		return -EOPNOTSUPP;
	return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
}
#endif
L
Linus Torvalds 已提交
380

381 382 383 384 385 386 387 388
/*
 * 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 已提交
389
int
L
Linus Torvalds 已提交
390 391 392
cifs_reconnect(struct TCP_Server_Info *server)
{
	int rc = 0;
393
	struct list_head *tmp, *tmp2;
394 395
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
S
Steve French 已提交
396
	struct mid_q_entry *mid_entry;
397
	struct list_head retry_list;
398
#ifdef CONFIG_CIFS_DFS_UPCALL
399
	struct super_block *sb = NULL;
400 401
	struct cifs_sb_info *cifs_sb = NULL;
	struct dfs_cache_tgt_list tgt_list = {0};
402 403
	struct dfs_cache_tgt_iterator *tgt_it = NULL;
#endif
404

L
Linus Torvalds 已提交
405
	spin_lock(&GlobalMid_Lock);
406 407
	server->nr_targets = 1;
#ifdef CONFIG_CIFS_DFS_UPCALL
408
	spin_unlock(&GlobalMid_Lock);
409
	sb = cifs_get_tcp_super(server);
410 411
	if (IS_ERR(sb)) {
		rc = PTR_ERR(sb);
412 413
		cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
			 __func__, rc);
414
		sb = NULL;
415
	} else {
416
		cifs_sb = CIFS_SB(sb);
417
		rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list);
418 419 420 421 422 423
		if (rc) {
			cifs_sb = NULL;
			if (rc != -EOPNOTSUPP) {
				cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
						__func__);
			}
424 425 426 427 428 429
		} 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);
430
	spin_lock(&GlobalMid_Lock);
431
#endif
432
	if (server->tcpStatus == CifsExiting) {
S
Steve French 已提交
433
		/* the demux thread will exit normally
L
Linus Torvalds 已提交
434 435
		next time through the loop */
		spin_unlock(&GlobalMid_Lock);
436 437
#ifdef CONFIG_CIFS_DFS_UPCALL
		dfs_cache_free_tgts(&tgt_list);
438
		cifs_put_tcp_super(sb);
439
#endif
440
		wake_up(&server->response_q);
L
Linus Torvalds 已提交
441 442 443 444 445
		return rc;
	} else
		server->tcpStatus = CifsNeedReconnect;
	spin_unlock(&GlobalMid_Lock);
	server->maxBuf = 0;
446
	server->max_read = 0;
L
Linus Torvalds 已提交
447

448
	cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
S
Steve French 已提交
449
	trace_smb3_reconnect(server->CurrentMid, server->hostname);
L
Linus Torvalds 已提交
450 451 452

	/* before reconnecting the tcp session, mark the smb session (uid)
		and the tid bad so they are not used until reconnected */
453 454
	cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
		 __func__);
455
	spin_lock(&cifs_tcp_ses_lock);
456
	list_for_each(tmp, &server->smb_ses_list) {
457
		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
458
		ses->need_reconnect = true;
459
		list_for_each(tmp2, &ses->tcon_list) {
460
			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
S
Steve French 已提交
461
			tcon->need_reconnect = true;
L
Linus Torvalds 已提交
462
		}
A
Aurelien Aptel 已提交
463 464
		if (ses->tcon_ipc)
			ses->tcon_ipc->need_reconnect = true;
L
Linus Torvalds 已提交
465
	}
466
	spin_unlock(&cifs_tcp_ses_lock);
467

L
Linus Torvalds 已提交
468
	/* do not want to be sending data on a socket we are freeing */
469
	cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
J
Jeff Layton 已提交
470
	mutex_lock(&server->srv_mutex);
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
	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 已提交
486

487
	/* mark submitted MIDs for retry and issue callback */
488
	INIT_LIST_HEAD(&retry_list);
489
	cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
L
Linus Torvalds 已提交
490
	spin_lock(&GlobalMid_Lock);
491 492
	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
493
		kref_get(&mid_entry->refcount);
494 495
		if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
			mid_entry->mid_state = MID_RETRY_NEEDED;
496
		list_move(&mid_entry->qhead, &retry_list);
497
		mid_entry->mid_flags |= MID_DELETED;
498 499
	}
	spin_unlock(&GlobalMid_Lock);
500
	mutex_unlock(&server->srv_mutex);
501

502
	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
503 504
	list_for_each_safe(tmp, tmp2, &retry_list) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
505 506
		list_del_init(&mid_entry->qhead);
		mid_entry->callback(mid_entry);
507
		cifs_mid_q_entry_release(mid_entry);
L
Linus Torvalds 已提交
508 509
	}

510 511
	if (cifs_rdma_enabled(server)) {
		mutex_lock(&server->srv_mutex);
512
		smbd_destroy(server);
513 514
		mutex_unlock(&server->srv_mutex);
	}
515

516
	do {
517
		try_to_freeze();
518

519
		mutex_lock(&server->srv_mutex);
520
#ifdef CONFIG_CIFS_DFS_UPCALL
521 522 523 524 525
		/*
		 * 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.
		 */
526
		reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
527 528 529 530 531 532 533
#endif
		rc = reconn_set_ipaddr(server);
		if (rc) {
			cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
				 __func__, rc);
		}

534 535 536 537
		if (cifs_rdma_enabled(server))
			rc = smbd_reconnect(server);
		else
			rc = generic_ip_connect(server);
S
Steve French 已提交
538
		if (rc) {
539
			cifs_dbg(FYI, "reconnect error %d\n", rc);
540
			mutex_unlock(&server->srv_mutex);
541
			msleep(3000);
L
Linus Torvalds 已提交
542 543
		} else {
			atomic_inc(&tcpSesReconnectCount);
544
			set_credits(server, 1);
L
Linus Torvalds 已提交
545
			spin_lock(&GlobalMid_Lock);
546
			if (server->tcpStatus != CifsExiting)
547
				server->tcpStatus = CifsNeedNegotiate;
S
Steve French 已提交
548
			spin_unlock(&GlobalMid_Lock);
549
			mutex_unlock(&server->srv_mutex);
L
Linus Torvalds 已提交
550
		}
551
	} while (server->tcpStatus == CifsNeedReconnect);
552

553 554 555 556 557
#ifdef CONFIG_CIFS_DFS_UPCALL
	if (tgt_it) {
		rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
						    tgt_it);
		if (rc) {
558
			cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
559 560 561 562
				 __func__, rc);
		}
		rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
		if (rc) {
563
			cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
564 565
				 __func__, rc);
		}
566
		dfs_cache_free_tgts(&tgt_list);
567

568
	}
569

570
	cifs_put_tcp_super(sb);
571
#endif
572 573 574
	if (server->tcpStatus == CifsNeedNegotiate)
		mod_delayed_work(cifsiod_wq, &server->echo, 0);

575
	wake_up(&server->response_q);
L
Linus Torvalds 已提交
576 577 578
	return rc;
}

579 580 581 582 583 584
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);
585 586 587 588 589 590 591 592 593 594
	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;
595

596
	/*
597 598
	 * We cannot send an echo if it is disabled.
	 * Also, no need to ping if we got a response recently.
599
	 */
600 601

	if (server->tcpStatus == CifsNeedReconnect ||
602 603
	    server->tcpStatus == CifsExiting ||
	    server->tcpStatus == CifsNew ||
604
	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
S
Steve French 已提交
605
	    time_before(jiffies, server->lstrp + echo_interval - HZ))
606 607
		goto requeue_echo;

608
	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
609
	if (rc)
610 611
		cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
			 server->hostname);
612 613

requeue_echo:
614
	queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
615 616
}

617
static bool
618
allocate_buffers(struct TCP_Server_Info *server)
619
{
620 621 622
	if (!server->bigbuf) {
		server->bigbuf = (char *)cifs_buf_get();
		if (!server->bigbuf) {
623
			cifs_server_dbg(VFS, "No memory for large SMB response\n");
624 625 626 627
			msleep(3000);
			/* retry will check if exiting */
			return false;
		}
628
	} else if (server->large_buf) {
629
		/* we are reusing a dirty large buf, clear its start */
630
		memset(server->bigbuf, 0, HEADER_SIZE(server));
631 632
	}

633 634 635
	if (!server->smallbuf) {
		server->smallbuf = (char *)cifs_small_buf_get();
		if (!server->smallbuf) {
636
			cifs_server_dbg(VFS, "No memory for SMB response\n");
637 638 639 640 641 642 643
			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 */
644
		memset(server->smallbuf, 0, HEADER_SIZE(server));
645 646 647 648 649
	}

	return true;
}

650 651 652
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
653
	/*
654
	 * We need to wait 3 echo intervals to make sure we handle such
655 656
	 * situations right:
	 * 1s  client sends a normal SMB request
657
	 * 2s  client gets a response
658 659 660 661 662 663
	 * 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.
	 */
664 665
	if ((server->tcpStatus == CifsGood ||
	    server->tcpStatus == CifsNeedNegotiate) &&
666
	    time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
667 668
		cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
			 (3 * server->echo_interval) / HZ);
669 670 671 672 673 674 675
		cifs_reconnect(server);
		return true;
	}

	return false;
}

676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
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;
}

691 692
static int
cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
693
{
J
Jeff Layton 已提交
694 695
	int length = 0;
	int total_read;
696

697 698
	smb_msg->msg_control = NULL;
	smb_msg->msg_controllen = 0;
699

700
	for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
701 702
		try_to_freeze();

703 704 705 706 707 708
		/* reconnect if no credits and no requests in flight */
		if (zero_credits(server)) {
			cifs_reconnect(server);
			return -ECONNABORTED;
		}

709 710
		if (server_unresponsive(server))
			return -ECONNABORTED;
711 712 713 714
		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);
715

716 717
		if (server->tcpStatus == CifsExiting)
			return -ESHUTDOWN;
718

719
		if (server->tcpStatus == CifsNeedReconnect) {
720
			cifs_reconnect(server);
721 722 723 724 725 726
			return -ECONNABORTED;
		}

		if (length == -ERESTARTSYS ||
		    length == -EAGAIN ||
		    length == -EINTR) {
727 728 729 730 731 732 733
			/*
			 * 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 已提交
734
			continue;
735 736 737
		}

		if (length <= 0) {
738
			cifs_dbg(FYI, "Received no data or error: %d\n", length);
739
			cifs_reconnect(server);
740
			return -ECONNABORTED;
741 742
		}
	}
J
Jeff Layton 已提交
743
	return total_read;
744 745
}

J
Jeff Layton 已提交
746 747 748
int
cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
		      unsigned int to_read)
749
{
750 751
	struct msghdr smb_msg;
	struct kvec iov = {.iov_base = buf, .iov_len = to_read};
752
	iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
753

754 755
	return cifs_readv_from_socket(server, &smb_msg);
}
756

757 758
int
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
L
Long Li 已提交
759
	unsigned int page_offset, unsigned int to_read)
760 761
{
	struct msghdr smb_msg;
L
Long Li 已提交
762 763
	struct bio_vec bv = {
		.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
764
	iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
765
	return cifs_readv_from_socket(server, &smb_msg);
766 767
}

768
static bool
J
Jeff Layton 已提交
769
is_smb_response(struct TCP_Server_Info *server, unsigned char type)
770 771 772 773 774 775
{
	/*
	 * 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 已提交
776 777 778 779 780
	switch (type) {
	case RFC1002_SESSION_MESSAGE:
		/* Regular SMB response */
		return true;
	case RFC1002_SESSION_KEEP_ALIVE:
781
		cifs_dbg(FYI, "RFC 1002 session keep alive\n");
J
Jeff Layton 已提交
782 783
		break;
	case RFC1002_POSITIVE_SESSION_RESPONSE:
784
		cifs_dbg(FYI, "RFC 1002 positive session response\n");
J
Jeff Layton 已提交
785 786
		break;
	case RFC1002_NEGATIVE_SESSION_RESPONSE:
787 788 789 790
		/*
		 * We get this from Windows 98 instead of an error on
		 * SMB negprot response.
		 */
791
		cifs_dbg(FYI, "RFC 1002 negative session response\n");
792 793 794 795 796 797 798 799
		/* 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 已提交
800
		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
801
		cifs_reconnect(server);
J
Jeff Layton 已提交
802 803
		break;
	default:
804
		cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
805 806 807
		cifs_reconnect(server);
	}

J
Jeff Layton 已提交
808
	return false;
809 810
}

J
Jeff Layton 已提交
811 812
void
dequeue_mid(struct mid_q_entry *mid, bool malformed)
813
{
814
#ifdef CONFIG_CIFS_STATS2
815
	mid->when_received = jiffies;
816
#endif
817 818
	spin_lock(&GlobalMid_Lock);
	if (!malformed)
819
		mid->mid_state = MID_RESPONSE_RECEIVED;
820
	else
821
		mid->mid_state = MID_RESPONSE_MALFORMED;
822 823 824 825 826
	/*
	 * Trying to handle/dequeue a mid after the send_recv()
	 * function has finished processing it is a bug.
	 */
	if (mid->mid_flags & MID_DELETED)
J
Joe Perches 已提交
827
		pr_warn_once("trying to dequeue a deleted mid\n");
828
	else {
829
		list_del_init(&mid->qhead);
830 831
		mid->mid_flags |= MID_DELETED;
	}
832
	spin_unlock(&GlobalMid_Lock);
833
}
834

835 836 837 838 839 840 841 842 843 844 845 846 847 848
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);
}

849 850
static void
handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
851
	   char *buf, int malformed)
852
{
853 854
	if (server->ops->check_trans2 &&
	    server->ops->check_trans2(mid, server, buf, malformed))
855
		return;
856
	mid->credits_received = smb2_get_credits_from_hdr(buf, server);
857
	mid->resp_buf = buf;
858
	mid->large_buf = server->large_buf;
859 860 861 862 863 864 865 866
	/* 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;
	}
867
	dequeue_mid(mid, malformed);
868 869
}

870 871 872 873 874 875 876 877 878
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);

879 880
	cancel_delayed_work_sync(&server->echo);

881 882 883 884 885
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
	wake_up_all(&server->response_q);

886
	/* check if we have blocked requests that need to free */
P
Pavel Shilovsky 已提交
887
	spin_lock(&server->req_lock);
888 889
	if (server->credits <= 0)
		server->credits = 1;
P
Pavel Shilovsky 已提交
890
	spin_unlock(&server->req_lock);
891 892 893 894 895 896 897 898 899 900
	/*
	 * 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);
901 902
	if (cifs_rdma_enabled(server))
		smbd_destroy(server);
903 904 905 906 907 908 909 910 911 912 913 914 915 916
	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);
917
			cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
918
			kref_get(&mid_entry->refcount);
919
			mid_entry->mid_state = MID_SHUTDOWN;
920
			list_move(&mid_entry->qhead, &dispose_list);
921
			mid_entry->mid_flags |= MID_DELETED;
922 923 924 925 926 927
		}
		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);
928
			cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
929 930
			list_del_init(&mid_entry->qhead);
			mid_entry->callback(mid_entry);
931
			cifs_mid_q_entry_release(mid_entry);
932 933 934 935 936 937 938 939 940 941 942 943 944 945
		}
		/* 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.
		 */
946
		cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
947 948 949 950 951 952 953 954 955 956 957 958
		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)
959
		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
960 961
}

962 963 964 965 966
static int
standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
	int length;
	char *buf = server->smallbuf;
967
	unsigned int pdu_length = server->pdu_size;
968 969

	/* make sure this will fit in a large buffer */
970 971
	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
		server->vals->header_preamble_size) {
972
		cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
973
		cifs_reconnect(server);
974
		return -ECONNABORTED;
975 976 977 978 979
	}

	/* switch to large buffer if too big for a small one */
	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
		server->large_buf = true;
980
		memcpy(server->bigbuf, buf, server->total_read);
981 982 983 984
		buf = server->bigbuf;
	}

	/* now read the rest */
985
	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
986 987 988
				       pdu_length - HEADER_SIZE(server) + 1
				       + server->vals->header_preamble_size);

989 990 991 992
	if (length < 0)
		return length;
	server->total_read += length;

993
	dump_smb(buf, server->total_read);
994

995 996 997 998 999 1000 1001 1002 1003
	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;

1004 1005 1006 1007 1008 1009 1010 1011 1012
	/*
	 * 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.
	 */
1013
	length = server->ops->check_message(buf, server->total_read, server);
1014 1015 1016 1017
	if (length != 0)
		cifs_dump_mem("Bad SMB: ", buf,
			min_t(unsigned int, server->total_read, 48));

1018 1019 1020 1021 1022 1023
	if (server->ops->is_session_expired &&
	    server->ops->is_session_expired(buf)) {
		cifs_reconnect(server);
		return -1;
	}

P
Pavel Shilovsky 已提交
1024
	if (server->ops->is_status_pending &&
1025
	    server->ops->is_status_pending(buf, server))
P
Pavel Shilovsky 已提交
1026 1027
		return -1;

1028 1029
	if (!mid)
		return length;
1030

1031
	handle_mid(mid, server, buf, length);
1032
	return 0;
1033 1034
}

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
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 已提交
1055
static int
1056
cifs_demultiplex_thread(void *p)
L
Linus Torvalds 已提交
1057
{
1058
	int i, num_mids, length;
1059
	struct TCP_Server_Info *server = p;
1060
	unsigned int pdu_length;
1061
	unsigned int next_offset;
1062
	char *buf = NULL;
1063
	struct task_struct *task_to_wake = NULL;
1064 1065
	struct mid_q_entry *mids[MAX_COMPOUND];
	char *bufs[MAX_COMPOUND];
1066
	unsigned int noreclaim_flag, num_io_timeout = 0;
L
Linus Torvalds 已提交
1067

1068
	noreclaim_flag = memalloc_noreclaim_save();
1069
	cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
1070 1071 1072

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

1075
	set_freezable();
1076
	allow_kernel_signal(SIGKILL);
1077
	while (server->tcpStatus != CifsExiting) {
1078 1079
		if (try_to_freeze())
			continue;
1080

1081
		if (!allocate_buffers(server))
1082
			continue;
1083

1084 1085
		server->large_buf = false;
		buf = server->smallbuf;
1086
		pdu_length = 4; /* enough to get RFC1001 header */
1087

J
Jeff Layton 已提交
1088
		length = cifs_read_from_socket(server, buf, pdu_length);
J
Jeff Layton 已提交
1089
		if (length < 0)
L
Linus Torvalds 已提交
1090
			continue;
1091 1092 1093 1094 1095

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

1097 1098 1099 1100
		/*
		 * The right amount was read from socket - 4 bytes,
		 * so we can now interpret the length field.
		 */
1101
		pdu_length = get_rfc1002_length(buf);
1102

1103
		cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
J
Jeff Layton 已提交
1104
		if (!is_smb_response(server, buf[0]))
S
Steve French 已提交
1105
			continue;
1106 1107
next_pdu:
		server->pdu_size = pdu_length;
1108

1109
		/* make sure we have enough to get to the MID */
1110
		if (server->pdu_size < HEADER_SIZE(server) - 1 -
1111
		    server->vals->header_preamble_size) {
1112
			cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
1113
				 server->pdu_size);
1114 1115
			cifs_reconnect(server);
			continue;
1116
		}
1117

1118
		/* read down to the MID */
1119 1120 1121 1122
		length = cifs_read_from_socket(server,
			     buf + server->vals->header_preamble_size,
			     HEADER_SIZE(server) - 1
			     - server->vals->header_preamble_size);
1123
		if (length < 0)
1124
			continue;
1125
		server->total_read += length;
L
Linus Torvalds 已提交
1126

1127 1128 1129 1130 1131 1132
		if (server->ops->next_header) {
			next_offset = server->ops->next_header(buf);
			if (next_offset)
				server->pdu_size = next_offset;
		}

1133 1134 1135 1136
		memset(mids, 0, sizeof(mids));
		memset(bufs, 0, sizeof(bufs));
		num_mids = 0;

1137 1138 1139 1140
		if (server->ops->is_transform_hdr &&
		    server->ops->receive_transform &&
		    server->ops->is_transform_hdr(buf)) {
			length = server->ops->receive_transform(server,
1141 1142 1143
								mids,
								bufs,
								&num_mids);
1144
		} else {
1145 1146
			mids[0] = server->ops->find_mid(server, buf);
			bufs[0] = buf;
1147
			num_mids = 1;
1148

1149 1150
			if (!mids[0] || !mids[0]->receive)
				length = standard_receive3(server, mids[0]);
1151
			else
1152
				length = mids[0]->receive(server, mids[0]);
1153
		}
1154

1155
		if (length < 0) {
1156 1157 1158
			for (i = 0; i < num_mids; i++)
				if (mids[i])
					cifs_mid_q_entry_release(mids[i]);
J
Jeff Layton 已提交
1159
			continue;
1160
		}
L
Linus Torvalds 已提交
1161

1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
		if (server->ops->is_status_io_timeout &&
		    server->ops->is_status_io_timeout(buf)) {
			num_io_timeout++;
			if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
				cifs_reconnect(server);
				num_io_timeout = 0;
				continue;
			}
		}

1172
		server->lstrp = jiffies;
S
Sachin Prabhu 已提交
1173

1174 1175 1176
		for (i = 0; i < num_mids; i++) {
			if (mids[i] != NULL) {
				mids[i]->resp_buf_size = server->pdu_size;
1177

1178 1179 1180 1181 1182 1183 1184
				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)) {
1185
				smb2_add_credits_from_hdr(bufs[i], server);
1186 1187
				cifs_dbg(FYI, "Received oplock break\n");
			} else {
J
Joe Perches 已提交
1188 1189
				cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
						atomic_read(&midCount));
1190 1191
				cifs_dump_mem("Received Data is: ", bufs[i],
					      HEADER_SIZE(server));
1192
				smb2_add_credits_from_hdr(bufs[i], server);
1193
#ifdef CONFIG_CIFS_DEBUG2
1194 1195 1196 1197
				if (server->ops->dump_detail)
					server->ops->dump_detail(bufs[i],
								 server);
				cifs_dump_mids(server);
1198
#endif /* CIFS_DEBUG2 */
1199
			}
1200
		}
1201

1202 1203 1204 1205 1206 1207 1208 1209
		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;
1210 1211 1212
		}
	} /* end while !EXITING */

1213
	/* buffer usually freed in free_mid - need to free it here on exit */
1214 1215 1216
	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 已提交
1217

1218
	task_to_wake = xchg(&server->tsk, NULL);
1219
	clean_demultiplex_info(server);
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230

	/* 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);
	}

1231
	memalloc_noreclaim_restore(noreclaim_flag);
1232
	module_put_and_exit(0);
L
Linus Torvalds 已提交
1233 1234
}

1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
/* 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? */
1245 1246 1247 1248 1249 1250
	if (strlen(unc) < 3)
		return ERR_PTR(-EINVAL);
	for (src = unc; *src && *src == '\\'; src++)
		;
	if (!*src)
		return ERR_PTR(-EINVAL);
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267

	/* 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;
}

1268 1269 1270 1271 1272 1273 1274 1275
static int get_option_ul(substring_t args[], unsigned long *option)
{
	int rc;
	char *string;

	string = match_strdup(args);
	if (string == NULL)
		return -ENOMEM;
1276
	rc = kstrtoul(string, 0, option);
1277 1278 1279 1280 1281
	kfree(string);

	return rc;
}

1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
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;
}
1317

1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
/*
 * 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;

1329
	if (unlikely(!devname || !*devname)) {
J
Joe Perches 已提交
1330
		cifs_dbg(VFS, "Device name not specified\n");
1331 1332 1333
		return -EINVAL;
	}

1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
	/* 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, '\\');

1358 1359 1360 1361 1362 1363
	/* skip any delimiter */
	if (*pos == '/' || *pos == '\\')
		pos++;

	/* If pos is NULL then no prepath */
	if (!*pos)
1364 1365 1366 1367 1368 1369 1370 1371 1372
		return 0;

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

	return 0;
}

L
Linus Torvalds 已提交
1373
static int
1374
cifs_parse_mount_options(const char *mountdata, const char *devname,
1375
			 struct smb_vol *vol, bool is_smb3)
L
Linus Torvalds 已提交
1376
{
1377
	char *data, *end;
1378
	char *mountdata_copy = NULL, *options;
L
Linus Torvalds 已提交
1379 1380
	unsigned int  temp_len, i, j;
	char separator[2];
1381 1382 1383 1384
	short int override_uid = -1;
	short int override_gid = -1;
	bool uid_specified = false;
	bool gid_specified = false;
1385 1386
	bool sloppy = false;
	char *invalid = NULL;
J
Jeff Layton 已提交
1387
	char *nodename = utsname()->nodename;
1388 1389 1390
	char *string = NULL;
	char *tmp_end, *value;
	char delim;
1391
	bool got_ip = false;
1392
	bool got_version = false;
1393 1394
	unsigned short port = 0;
	struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
L
Linus Torvalds 已提交
1395 1396

	separator[0] = ',';
1397
	separator[1] = 0;
1398
	delim = separator[0];
L
Linus Torvalds 已提交
1399

1400 1401 1402
	/* ensure we always start with zeroed-out smb_vol */
	memset(vol, 0, sizeof(*vol));

J
Jeff Layton 已提交
1403 1404 1405 1406 1407
	/*
	 * 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
	 */
1408 1409
	memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
	for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
J
Jeff Layton 已提交
1410 1411
		vol->source_rfc1001_name[i] = toupper(nodename[i]);

1412
	vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1413 1414 1415
	/* null target name indicates to use *SMBSERVR default called name
	   if we end up sending RFC1001 session initialize */
	vol->target_rfc1001_name[0] = 0;
1416 1417
	vol->cred_uid = current_uid();
	vol->linux_uid = current_uid();
1418
	vol->linux_gid = current_gid();
1419
	vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
1420 1421 1422 1423 1424 1425 1426 1427
	/*
	 * 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;

1428 1429
	/* 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 已提交
1430 1431

	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1432 1433
	/* default is always to request posix paths. */
	vol->posix_paths = 1;
1434 1435
	/* default to using server inode numbers where available */
	vol->server_ino = 1;
1436

1437 1438 1439
	/* default is to use strict cifs caching semantics */
	vol->strict_io = true;

1440 1441
	vol->actimeo = CIFS_DEF_ACTIMEO;

1442 1443 1444
	/* 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 */

1445 1446 1447
	/* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
	vol->ops = &smb30_operations;
	vol->vals = &smbdefault_values;
1448

R
Rabin Vincent 已提交
1449 1450
	vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;

1451 1452 1453 1454
	/* default to no multichannel (single server connection) */
	vol->multichannel = false;
	vol->max_channels = 1;

1455 1456 1457 1458 1459 1460
	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 已提交
1461

1462
	options = mountdata_copy;
1463
	end = options + strlen(options);
1464

1465
	if (strncmp(options, "sep=", 4) == 0) {
S
Steve French 已提交
1466
		if (options[4] != 0) {
L
Linus Torvalds 已提交
1467 1468 1469
			separator[0] = options[4];
			options += 5;
		} else {
1470
			cifs_dbg(FYI, "Null separator not allowed\n");
L
Linus Torvalds 已提交
1471 1472
		}
	}
1473 1474
	vol->backupuid_specified = false; /* no backup intent for a user */
	vol->backupgid_specified = false; /* no backup intent for a group */
1475

1476 1477 1478 1479
	switch (cifs_parse_devname(devname, vol)) {
	case 0:
		break;
	case -ENOMEM:
J
Joe Perches 已提交
1480
		cifs_dbg(VFS, "Unable to allocate memory for devname\n");
1481 1482
		goto cifs_parse_mount_err;
	case -EINVAL:
J
Joe Perches 已提交
1483
		cifs_dbg(VFS, "Malformed UNC in devname\n");
1484 1485
		goto cifs_parse_mount_err;
	default:
J
Joe Perches 已提交
1486
		cifs_dbg(VFS, "Unknown error parsing devname\n");
1487
		goto cifs_parse_mount_err;
1488 1489
	}

L
Linus Torvalds 已提交
1490
	while ((data = strsep(&options, separator)) != NULL) {
1491 1492 1493 1494
		substring_t args[MAX_OPT_ARGS];
		unsigned long option;
		int token;

L
Linus Torvalds 已提交
1495 1496 1497
		if (!*data)
			continue;

1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
		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 已提交
1508
			vol->no_xattr = 0;
1509 1510
			break;
		case Opt_nouser_xattr:
L
Linus Torvalds 已提交
1511
			vol->no_xattr = 1;
1512 1513
			break;
		case Opt_forceuid:
1514
			override_uid = 1;
1515 1516
			break;
		case Opt_noforceuid:
1517
			override_uid = 0;
1518
			break;
J
Jeff Layton 已提交
1519 1520 1521 1522 1523 1524
		case Opt_forcegid:
			override_gid = 1;
			break;
		case Opt_noforcegid:
			override_gid = 0;
			break;
1525
		case Opt_noblocksend:
1526
			vol->noblocksnd = 1;
1527 1528
			break;
		case Opt_noautotune:
1529
			vol->noautotune = 1;
1530
			break;
1531 1532 1533
		case Opt_nolease:
			vol->no_lease = 1;
			break;
1534
		case Opt_hard:
L
Linus Torvalds 已提交
1535
			vol->retry = 1;
1536 1537
			break;
		case Opt_soft:
L
Linus Torvalds 已提交
1538
			vol->retry = 0;
1539 1540
			break;
		case Opt_perm:
L
Linus Torvalds 已提交
1541
			vol->noperm = 0;
1542 1543
			break;
		case Opt_noperm:
L
Linus Torvalds 已提交
1544
			vol->noperm = 1;
1545
			break;
S
Steve French 已提交
1546 1547 1548
		case Opt_nodelete:
			vol->nodelete = 1;
			break;
1549
		case Opt_mapchars:
1550 1551
			vol->sfu_remap = true;
			vol->remap = false; /* disable SFM mapping */
1552 1553
			break;
		case Opt_nomapchars:
1554 1555 1556 1557 1558 1559 1560 1561
			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;
1562 1563
			break;
		case Opt_sfu:
1564
			vol->sfu_emul = 1;
1565 1566
			break;
		case Opt_nosfu:
1567
			vol->sfu_emul = 0;
1568 1569
			break;
		case Opt_nodfs:
S
Steve French 已提交
1570
			vol->nodfs = 1;
1571
			break;
1572 1573 1574 1575 1576
		case Opt_rootfs:
#ifdef CONFIG_CIFS_ROOT
			vol->rootfs = true;
#endif
			break;
1577
		case Opt_posixpaths:
1578
			vol->posix_paths = 1;
1579 1580
			break;
		case Opt_noposixpaths:
1581
			vol->posix_paths = 0;
1582 1583
			break;
		case Opt_nounix:
1584 1585 1586
			if (vol->linux_ext)
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
1587
			vol->no_linux_ext = 1;
1588
			break;
1589 1590 1591 1592 1593 1594
		case Opt_unix:
			if (vol->no_linux_ext)
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
			vol->linux_ext = 1;
			break;
1595
		case Opt_nocase:
1596
			vol->nocase = 1;
1597 1598
			break;
		case Opt_brl:
1599
			vol->nobrl =  0;
1600 1601
			break;
		case Opt_nobrl:
1602
			vol->nobrl =  1;
1603 1604
			/*
			 * turn off mandatory locking in mode
1605
			 * if remote locking is turned off since the
1606 1607
			 * local vfs will do advisory
			 */
1608 1609
			if (vol->file_mode ==
				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1610
				vol->file_mode = S_IALLUGO;
1611
			break;
S
Steve French 已提交
1612 1613 1614 1615 1616 1617
		case Opt_nohandlecache:
			vol->nohandlecache = 1;
			break;
		case Opt_handlecache:
			vol->nohandlecache = 0;
			break;
1618
		case Opt_forcemandatorylock:
1619
			vol->mand_lock = 1;
1620 1621
			break;
		case Opt_setuids:
L
Linus Torvalds 已提交
1622
			vol->setuids = 1;
1623 1624
			break;
		case Opt_nosetuids:
L
Linus Torvalds 已提交
1625
			vol->setuids = 0;
1626
			break;
1627 1628 1629
		case Opt_setuidfromacl:
			vol->setuidfromacl = 1;
			break;
1630
		case Opt_dynperm:
1631
			vol->dynperm = true;
1632 1633
			break;
		case Opt_nodynperm:
1634
			vol->dynperm = false;
1635 1636
			break;
		case Opt_nohard:
L
Linus Torvalds 已提交
1637
			vol->retry = 0;
1638 1639
			break;
		case Opt_nosoft:
L
Linus Torvalds 已提交
1640
			vol->retry = 1;
1641 1642
			break;
		case Opt_nointr:
L
Linus Torvalds 已提交
1643
			vol->intr = 0;
1644 1645
			break;
		case Opt_intr:
L
Linus Torvalds 已提交
1646
			vol->intr = 1;
1647 1648
			break;
		case Opt_nostrictsync:
1649
			vol->nostrictsync = 1;
1650 1651
			break;
		case Opt_strictsync:
1652
			vol->nostrictsync = 0;
1653 1654
			break;
		case Opt_serverino:
L
Linus Torvalds 已提交
1655
			vol->server_ino = 1;
1656 1657
			break;
		case Opt_noserverino:
L
Linus Torvalds 已提交
1658
			vol->server_ino = 0;
1659 1660
			break;
		case Opt_rwpidforward:
1661
			vol->rwpidforward = 1;
1662
			break;
1663 1664 1665
		case Opt_modesid:
			vol->mode_ace = 1;
			break;
1666
		case Opt_cifsacl:
1667
			vol->cifs_acl = 1;
1668 1669
			break;
		case Opt_nocifsacl:
1670
			vol->cifs_acl = 0;
1671 1672
			break;
		case Opt_acl:
L
Linus Torvalds 已提交
1673
			vol->no_psx_acl = 0;
1674 1675
			break;
		case Opt_noacl:
L
Linus Torvalds 已提交
1676
			vol->no_psx_acl = 1;
1677 1678
			break;
		case Opt_locallease:
S
Steve French 已提交
1679
			vol->local_lease = 1;
1680 1681
			break;
		case Opt_sign:
1682
			vol->sign = true;
1683
			break;
1684 1685 1686 1687
		case Opt_ignore_signature:
			vol->sign = true;
			vol->ignore_signature = true;
			break;
1688
		case Opt_seal:
1689
			/* we do not do the following in secFlags because seal
1690 1691 1692 1693
			 * is a per tree connection (mount) not a per socket
			 * or per-smb connection option in the protocol
			 * vol->secFlg |= CIFSSEC_MUST_SEAL;
			 */
1694
			vol->seal = 1;
1695 1696
			break;
		case Opt_noac:
J
Joe Perches 已提交
1697
			pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1698 1699
			break;
		case Opt_fsc:
1700
#ifndef CONFIG_CIFS_FSCACHE
1701
			cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1702
			goto cifs_parse_mount_err;
1703
#endif
1704
			vol->fsc = true;
1705 1706
			break;
		case Opt_mfsymlinks:
1707
			vol->mfsymlinks = true;
1708 1709
			break;
		case Opt_multiuser:
J
Jeff Layton 已提交
1710
			vol->multiuser = true;
1711
			break;
1712 1713 1714
		case Opt_sloppy:
			sloppy = true;
			break;
1715 1716 1717
		case Opt_nosharesock:
			vol->nosharesock = true;
			break;
1718 1719 1720 1721 1722 1723 1724 1725 1726 1727
		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 已提交
1728
			if ((vol->nopersistent) || (vol->resilient)) {
1729 1730 1731 1732 1733
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
S
Steve French 已提交
1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
		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;
1745 1746 1747
		case Opt_domainauto:
			vol->domainauto = true;
			break;
L
Long Li 已提交
1748 1749 1750
		case Opt_rdma:
			vol->rdma = true;
			break;
1751 1752
		case Opt_multichannel:
			vol->multichannel = true;
1753 1754 1755
			/* if number of channels not specified, default to 2 */
			if (vol->max_channels < 2)
				vol->max_channels = 2;
1756 1757 1758
			break;
		case Opt_nomultichannel:
			vol->multichannel = false;
1759
			vol->max_channels = 1;
1760
			break;
1761 1762 1763 1764 1765
		case Opt_compress:
			vol->compression = UNKNOWN_TYPE;
			cifs_dbg(VFS,
				"SMB3 compression support is experimental\n");
			break;
1766 1767 1768

		/* Numeric Values */
		case Opt_backupuid:
1769
			if (get_option_uid(args, &vol->backupuid)) {
1770 1771
				cifs_dbg(VFS, "%s: Invalid backupuid value\n",
					 __func__);
1772 1773 1774
				goto cifs_parse_mount_err;
			}
			vol->backupuid_specified = true;
1775 1776
			break;
		case Opt_backupgid:
1777
			if (get_option_gid(args, &vol->backupgid)) {
1778 1779
				cifs_dbg(VFS, "%s: Invalid backupgid value\n",
					 __func__);
1780 1781 1782
				goto cifs_parse_mount_err;
			}
			vol->backupgid_specified = true;
1783 1784
			break;
		case Opt_uid:
1785
			if (get_option_uid(args, &vol->linux_uid)) {
1786 1787
				cifs_dbg(VFS, "%s: Invalid uid value\n",
					 __func__);
1788 1789 1790 1791 1792
				goto cifs_parse_mount_err;
			}
			uid_specified = true;
			break;
		case Opt_cruid:
1793
			if (get_option_uid(args, &vol->cred_uid)) {
1794 1795
				cifs_dbg(VFS, "%s: Invalid cruid value\n",
					 __func__);
1796 1797 1798 1799
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_gid:
1800
			if (get_option_gid(args, &vol->linux_gid)) {
1801 1802
				cifs_dbg(VFS, "%s: Invalid gid value\n",
					 __func__);
1803 1804 1805 1806 1807 1808
				goto cifs_parse_mount_err;
			}
			gid_specified = true;
			break;
		case Opt_file_mode:
			if (get_option_ul(args, &option)) {
1809 1810
				cifs_dbg(VFS, "%s: Invalid file_mode value\n",
					 __func__);
1811 1812 1813 1814 1815 1816
				goto cifs_parse_mount_err;
			}
			vol->file_mode = option;
			break;
		case Opt_dirmode:
			if (get_option_ul(args, &option)) {
1817 1818
				cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
					 __func__);
1819 1820 1821 1822 1823
				goto cifs_parse_mount_err;
			}
			vol->dir_mode = option;
			break;
		case Opt_port:
1824 1825
			if (get_option_ul(args, &option) ||
			    option > USHRT_MAX) {
1826 1827
				cifs_dbg(VFS, "%s: Invalid port value\n",
					 __func__);
1828 1829
				goto cifs_parse_mount_err;
			}
1830
			port = (unsigned short)option;
1831
			break;
1832 1833 1834 1835 1836 1837 1838
		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;
1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858
		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;
1859 1860
		case Opt_rsize:
			if (get_option_ul(args, &option)) {
1861 1862
				cifs_dbg(VFS, "%s: Invalid rsize value\n",
					 __func__);
1863
				goto cifs_parse_mount_err;
1864 1865 1866 1867 1868
			}
			vol->rsize = option;
			break;
		case Opt_wsize:
			if (get_option_ul(args, &option)) {
1869 1870
				cifs_dbg(VFS, "%s: Invalid wsize value\n",
					 __func__);
1871 1872 1873 1874 1875 1876
				goto cifs_parse_mount_err;
			}
			vol->wsize = option;
			break;
		case Opt_actimeo:
			if (get_option_ul(args, &option)) {
1877 1878
				cifs_dbg(VFS, "%s: Invalid actimeo value\n",
					 __func__);
1879 1880 1881 1882
				goto cifs_parse_mount_err;
			}
			vol->actimeo = HZ * option;
			if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1883
				cifs_dbg(VFS, "attribute cache timeout too large\n");
1884 1885 1886
				goto cifs_parse_mount_err;
			}
			break;
1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898
		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 已提交
1899 1900 1901 1902 1903 1904 1905 1906
		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;
1907 1908 1909 1910 1911 1912 1913 1914
		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;
1915 1916 1917 1918 1919 1920 1921 1922 1923
		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;
1924 1925 1926 1927 1928 1929 1930 1931 1932
		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;
1933 1934 1935

		/* String Arguments */

1936 1937 1938 1939 1940
		case Opt_blank_user:
			/* null user, ie. anonymous authentication */
			vol->nullauth = 1;
			vol->username = NULL;
			break;
1941 1942 1943 1944 1945
		case Opt_user:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1946 1947
			if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
							CIFS_MAX_USERNAME_LEN) {
J
Joe Perches 已提交
1948
				pr_warn("username too long\n");
1949 1950
				goto cifs_parse_mount_err;
			}
1951 1952

			kfree(vol->username);
1953
			vol->username = kstrdup(string, GFP_KERNEL);
1954
			if (!vol->username)
1955 1956 1957 1958 1959 1960 1961 1962
				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
			 */

1963 1964 1965 1966 1967 1968 1969 1970
			/*
			 * 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 */
1971
				kfree_sensitive(vol->password);
1972 1973 1974
				vol->password = NULL;
				break;
			}
1975
			fallthrough;	/* to Opt_pass below */
1976
		case Opt_pass:
1977 1978
			/* Obtain the value string */
			value = strchr(data, '=');
1979
			value++;
1980 1981 1982 1983 1984 1985 1986 1987

			/* 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
			 */
1988
			if (tmp_end < end && tmp_end[1] == delim) {
1989 1990
				tmp_end[0] = delim;

1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
				/* 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;
2007 2008
			}

2009
			kfree_sensitive(vol->password);
2010 2011 2012 2013
			/* Now build new password string */
			temp_len = strlen(value);
			vol->password = kzalloc(temp_len+1, GFP_KERNEL);
			if (vol->password == NULL) {
J
Joe Perches 已提交
2014
				pr_warn("no memory for password\n");
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
				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;
2027
		case Opt_blank_ip:
2028 2029
			/* FIXME: should this be an error instead? */
			got_ip = false;
2030
			break;
2031 2032 2033 2034 2035
		case Opt_ip:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2036 2037
			if (!cifs_convert_address(dstaddr, string,
					strlen(string))) {
J
Joe Perches 已提交
2038
				pr_err("bad ip= option (%s)\n", string);
2039 2040
				goto cifs_parse_mount_err;
			}
2041
			got_ip = true;
2042 2043 2044 2045 2046 2047
			break;
		case Opt_domain:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2048 2049
			if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
					== CIFS_MAX_DOMAINNAME_LEN) {
J
Joe Perches 已提交
2050
				pr_warn("domain name too long\n");
2051 2052 2053
				goto cifs_parse_mount_err;
			}

2054
			kfree(vol->domainname);
2055 2056
			vol->domainname = kstrdup(string, GFP_KERNEL);
			if (!vol->domainname) {
J
Joe Perches 已提交
2057
				pr_warn("no memory for domainname\n");
2058 2059
				goto cifs_parse_mount_err;
			}
2060
			cifs_dbg(FYI, "Domain name set\n");
2061 2062 2063 2064 2065 2066
			break;
		case Opt_srcaddr:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2067
			if (!cifs_convert_address(
2068 2069
					(struct sockaddr *)&vol->srcaddr,
					string, strlen(string))) {
J
Joe Perches 已提交
2070
				pr_warn("Could not parse srcaddr: %s\n",
2071
					string);
2072 2073 2074 2075 2076 2077 2078 2079
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_iocharset:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2080
			if (strnlen(string, 1024) >= 65) {
J
Joe Perches 已提交
2081
				pr_warn("iocharset name too long\n");
2082 2083 2084
				goto cifs_parse_mount_err;
			}

2085
			 if (strncasecmp(string, "default", 7) != 0) {
2086
				kfree(vol->iocharset);
2087 2088 2089
				vol->iocharset = kstrdup(string,
							 GFP_KERNEL);
				if (!vol->iocharset) {
J
Joe Perches 已提交
2090
					pr_warn("no memory for charset\n");
2091 2092 2093 2094 2095 2096
					goto cifs_parse_mount_err;
				}
			}
			/* if iocharset not set then load_nls_default
			 * is used by caller
			 */
2097
			 cifs_dbg(FYI, "iocharset set to %s\n", string);
2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120
			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)
J
Joe Perches 已提交
2121
				pr_warn("netbiosname longer than 15 truncated\n");
2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146
			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)
J
Joe Perches 已提交
2147
				pr_warn("server netbiosname longer than 15 truncated\n");
2148 2149
			break;
		case Opt_ver:
2150
			/* version of mount userspace tools, not dialect */
2151 2152 2153 2154
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2155
			/* If interface changes in mount.cifs bump to new ver */
2156
			if (strncasecmp(string, "1", 1) == 0) {
2157
				if (strlen(string) > 1) {
J
Joe Perches 已提交
2158 2159
					pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
						string);
2160 2161
					goto cifs_parse_mount_err;
				}
2162 2163 2164 2165
				/* This is the default */
				break;
			}
			/* For all other value, error */
J
Joe Perches 已提交
2166
			pr_warn("Invalid mount helper version specified\n");
2167
			goto cifs_parse_mount_err;
2168
		case Opt_vers:
2169
			/* protocol version (dialect) */
2170 2171 2172 2173
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2174
			if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
2175
				goto cifs_parse_mount_err;
2176
			got_version = true;
2177
			break;
2178 2179 2180 2181 2182 2183 2184 2185
		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;
2186 2187 2188 2189 2190 2191 2192 2193
		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;
2194
		default:
2195 2196 2197 2198 2199 2200
			/*
			 * An option we don't recognize. Save it off for later
			 * if we haven't already found one
			 */
			if (!invalid)
				invalid = data;
2201
			break;
L
Linus Torvalds 已提交
2202
		}
2203 2204 2205
		/* Free up any allocated string */
		kfree(string);
		string = NULL;
L
Linus Torvalds 已提交
2206
	}
J
Jeff Layton 已提交
2207

2208
	if (!sloppy && invalid) {
J
Joe Perches 已提交
2209
		pr_err("Unknown mount option \"%s\"\n", invalid);
2210 2211 2212
		goto cifs_parse_mount_err;
	}

L
Long Li 已提交
2213 2214 2215 2216 2217
	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;
	}

2218 2219 2220
#ifndef CONFIG_KEYS
	/* Muliuser mounts require CONFIG_KEYS support */
	if (vol->multiuser) {
2221
		cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
2222
		goto cifs_parse_mount_err;
J
Jeff Layton 已提交
2223
	}
2224
#endif
2225
	if (!vol->UNC) {
2226
		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
2227 2228
		goto cifs_parse_mount_err;
	}
J
Jeff Layton 已提交
2229

2230 2231
	/* make sure UNC has a share name */
	if (!strchr(vol->UNC + 3, '\\')) {
2232
		cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
2233 2234 2235
		goto cifs_parse_mount_err;
	}

2236
	if (!got_ip) {
2237 2238 2239
		int len;
		const char *slash;

2240
		/* No ip= option specified? Try to get it from UNC */
2241 2242 2243 2244
		/* 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)) {
J
Joe Perches 已提交
2245
			pr_err("Unable to determine destination address\n");
2246 2247 2248 2249 2250 2251
			goto cifs_parse_mount_err;
		}
	}

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

2253 2254 2255
	if (uid_specified)
		vol->override_uid = override_uid;
	else if (override_uid == 1)
J
Joe Perches 已提交
2256
		pr_notice("ignoring forceuid mount option specified with no uid= option\n");
2257 2258 2259 2260

	if (gid_specified)
		vol->override_gid = override_gid;
	else if (override_gid == 1)
J
Joe Perches 已提交
2261
		pr_notice("ignoring forcegid mount option specified with no gid= option\n");
2262

2263
	if (got_version == false)
J
Joe Perches 已提交
2264
		pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
2265

2266
	kfree(mountdata_copy);
L
Linus Torvalds 已提交
2267
	return 0;
2268

2269
out_nomem:
2270
	pr_warn("Could not allocate temporary buffer\n");
2271
cifs_parse_mount_err:
2272
	kfree(string);
2273 2274
	kfree(mountdata_copy);
	return 1;
L
Linus Torvalds 已提交
2275 2276
}

2277 2278 2279 2280
/** 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.
 */
2281 2282
bool
cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
{
	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;
2294
		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
2295 2296 2297 2298 2299 2300 2301 2302
		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
	}
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
}

2303 2304 2305 2306 2307 2308 2309 2310
/*
 * 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)
{
2311
	__be16 port, *sport;
2312

2313 2314 2315 2316
	/* SMBDirect manages its own ports, don't match it here */
	if (server->rdma)
		return true;

2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340
	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;
}
2341

2342
static bool
2343 2344
match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
	      struct sockaddr *srcaddr)
2345 2346
{
	switch (addr->sa_family) {
2347 2348 2349 2350 2351 2352
	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)
2353 2354
			return false;
		break;
2355 2356 2357 2358 2359 2360
	}
	case AF_INET6: {
		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
		struct sockaddr_in6 *srv_addr6 =
					(struct sockaddr_in6 *)&server->dstaddr;

2361
		if (!ipv6_addr_equal(&addr6->sin6_addr,
2362
				     &srv_addr6->sin6_addr))
2363
			return false;
2364
		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
2365 2366 2367
			return false;
		break;
	}
2368 2369 2370 2371
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
2372

2373
	if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
2374 2375
		return false;

2376 2377 2378
	return true;
}

2379 2380 2381
static bool
match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
{
2382 2383 2384 2385 2386
	/*
	 * 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 已提交
2387 2388
	if (server->ops->select_sectype(server, vol->sectype)
	     == Unspecified)
2389 2390
		return false;

2391 2392 2393 2394 2395
	/*
	 * 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.
	 */
2396 2397
	if (vol->sign && !server->sign)
		return false;
2398 2399 2400 2401

	return true;
}

2402
static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
2403
{
2404 2405
	struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;

2406 2407 2408
	if (vol->nosharesock)
		return 0;

2409 2410 2411 2412 2413 2414 2415 2416 2417
	/* 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))
2418 2419
		return 0;

2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432
	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 已提交
2433
	if (server->echo_interval != vol->echo_interval * HZ)
S
Steve French 已提交
2434 2435
		return 0;

L
Long Li 已提交
2436 2437 2438
	if (server->rdma != vol->rdma)
		return 0;

2439 2440 2441
	if (server->ignore_signature != vol->ignore_signature)
		return 0;

2442 2443 2444
	if (server->min_offload != vol->min_offload)
		return 0;

2445 2446 2447
	return 1;
}

P
Paulo Alcantara 已提交
2448
struct TCP_Server_Info *
2449
cifs_find_tcp_session(struct smb_vol *vol)
L
Linus Torvalds 已提交
2450
{
2451 2452
	struct TCP_Server_Info *server;

2453
	spin_lock(&cifs_tcp_ses_lock);
2454
	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
2455 2456 2457 2458 2459
		/*
		 * Skip ses channels since they're only handled in lower layers
		 * (e.g. cifs_send_recv).
		 */
		if (server->is_channel || !match_server(server, vol))
2460 2461
			continue;

2462
		++server->srv_count;
2463
		spin_unlock(&cifs_tcp_ses_lock);
2464
		cifs_dbg(FYI, "Existing tcp session with server found\n");
2465
		return server;
L
Linus Torvalds 已提交
2466
	}
2467
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
2468 2469
	return NULL;
}
2470

2471 2472
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
L
Linus Torvalds 已提交
2473
{
2474 2475
	struct task_struct *task;

2476
	spin_lock(&cifs_tcp_ses_lock);
2477
	if (--server->srv_count > 0) {
2478
		spin_unlock(&cifs_tcp_ses_lock);
2479
		return;
L
Linus Torvalds 已提交
2480
	}
2481

2482 2483
	put_net(cifs_net_ns(server));

2484
	list_del_init(&server->tcp_ses_list);
2485
	spin_unlock(&cifs_tcp_ses_lock);
2486

2487 2488
	cancel_delayed_work_sync(&server->echo);

2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499
	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);

2500 2501 2502
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
2503

2504
	cifs_crypto_secmech_release(server);
2505 2506
	cifs_fscache_release_client_cookie(server);

2507 2508 2509
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
2510 2511 2512

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

2516
struct TCP_Server_Info *
2517 2518 2519 2520 2521
cifs_get_tcp_session(struct smb_vol *volume_info)
{
	struct TCP_Server_Info *tcp_ses = NULL;
	int rc;

2522
	cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
2523 2524

	/* see if we already have a matching tcp_ses */
2525
	tcp_ses = cifs_find_tcp_session(volume_info);
2526 2527 2528 2529 2530 2531 2532 2533 2534
	if (tcp_ses)
		return tcp_ses;

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

2535 2536
	tcp_ses->ops = volume_info->ops;
	tcp_ses->vals = volume_info->vals;
2537
	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
2538 2539 2540
	tcp_ses->hostname = extract_hostname(volume_info->UNC);
	if (IS_ERR(tcp_ses->hostname)) {
		rc = PTR_ERR(tcp_ses->hostname);
2541
		goto out_err_crypto_release;
2542 2543
	}

2544 2545
	tcp_ses->noblockcnt = volume_info->rootfs;
	tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
2546
	tcp_ses->noautotune = volume_info->noautotune;
2547
	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
L
Long Li 已提交
2548
	tcp_ses->rdma = volume_info->rdma;
P
Pavel Shilovsky 已提交
2549
	tcp_ses->in_flight = 0;
2550
	tcp_ses->max_in_flight = 0;
2551
	tcp_ses->credits = 1;
2552 2553 2554 2555 2556 2557 2558 2559
	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);
2560
	tcp_ses->session_estab = false;
2561
	tcp_ses->sequence_number = 0;
2562
	tcp_ses->reconnect_instance = 1;
2563
	tcp_ses->lstrp = jiffies;
2564
	tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
2565
	spin_lock_init(&tcp_ses->req_lock);
2566 2567
	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
2568
	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
2569 2570
	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
	mutex_init(&tcp_ses->reconnect_mutex);
2571 2572 2573 2574
	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
	       sizeof(tcp_ses->srcaddr));
	memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
		sizeof(tcp_ses->dstaddr));
2575 2576 2577 2578 2579
	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);
2580 2581 2582 2583 2584 2585 2586 2587
	/*
	 * 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 已提交
2588 2589 2590 2591 2592
	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;
2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609
	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;
		}
	}
2610
	rc = ip_connect(tcp_ses);
2611
	if (rc < 0) {
2612
		cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
2613
		goto out_err_crypto_release;
2614
	}
2615
smbd_connected:
2616 2617 2618 2619 2620
	/*
	 * since we're in a cifs function already, we know that
	 * this will succeed. No need for try_module_get().
	 */
	__module_get(THIS_MODULE);
2621
	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
2622 2623 2624
				  tcp_ses, "cifsd");
	if (IS_ERR(tcp_ses->tsk)) {
		rc = PTR_ERR(tcp_ses->tsk);
2625
		cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
2626
		module_put(THIS_MODULE);
2627
		goto out_err_crypto_release;
2628
	}
2629
	tcp_ses->min_offload = volume_info->min_offload;
2630
	tcp_ses->tcpStatus = CifsNeedNegotiate;
2631

2632
	tcp_ses->nr_targets = 1;
2633
	tcp_ses->ignore_signature = volume_info->ignore_signature;
2634
	/* thread spawned, put it on the list */
2635
	spin_lock(&cifs_tcp_ses_lock);
2636
	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
2637
	spin_unlock(&cifs_tcp_ses_lock);
2638

2639 2640
	cifs_fscache_get_client_cookie(tcp_ses);

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

2644 2645
	return tcp_ses;

2646
out_err_crypto_release:
2647
	cifs_crypto_secmech_release(tcp_ses);
2648

2649 2650
	put_net(cifs_net_ns(tcp_ses));

2651 2652
out_err:
	if (tcp_ses) {
2653 2654
		if (!IS_ERR(tcp_ses->hostname))
			kfree(tcp_ses->hostname);
2655 2656 2657 2658 2659 2660 2661
		if (tcp_ses->ssocket)
			sock_release(tcp_ses->ssocket);
		kfree(tcp_ses);
	}
	return ERR_PTR(rc);
}

2662
static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
2663
{
2664 2665 2666 2667
	if (vol->sectype != Unspecified &&
	    vol->sectype != ses->sectype)
		return 0;

2668 2669 2670 2671 2672 2673 2674
	/*
	 * 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;

2675
	switch (ses->sectype) {
2676
	case Kerberos:
2677
		if (!uid_eq(vol->cred_uid, ses->cred_uid))
2678 2679 2680
			return 0;
		break;
	default:
J
Jeff Layton 已提交
2681 2682 2683 2684 2685 2686 2687
		/* NULL username means anonymous session */
		if (ses->user_name == NULL) {
			if (!vol->nullauth)
				return 0;
			break;
		}

2688
		/* anything else takes username/password */
J
Jeff Layton 已提交
2689 2690
		if (strncmp(ses->user_name,
			    vol->username ? vol->username : "",
2691
			    CIFS_MAX_USERNAME_LEN))
2692
			return 0;
2693
		if ((vol->username && strlen(vol->username) != 0) &&
2694 2695 2696
		    ses->password != NULL &&
		    strncmp(ses->password,
			    vol->password ? vol->password : "",
2697
			    CIFS_MAX_PASSWORD_LEN))
2698 2699 2700 2701 2702
			return 0;
	}
	return 1;
}

A
Aurelien Aptel 已提交
2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716
/**
 * 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;
2717
	struct TCP_Server_Info *server = ses->server;
A
Aurelien Aptel 已提交
2718 2719 2720 2721 2722 2723

	/*
	 * If the mount request that resulted in the creation of the
	 * session requires encryption, force IPC to be encrypted too.
	 */
	if (volume_info->seal) {
2724
		if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
A
Aurelien Aptel 已提交
2725 2726
			seal = true;
		else {
2727
			cifs_server_dbg(VFS,
A
Aurelien Aptel 已提交
2728 2729 2730 2731 2732 2733 2734 2735 2736
				 "IPC: server doesn't support encryption\n");
			return -EOPNOTSUPP;
		}
	}

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

2737
	scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
A
Aurelien Aptel 已提交
2738 2739 2740 2741 2742 2743 2744 2745

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

	xid = get_xid();
	tcon->ses = ses;
	tcon->ipc = true;
	tcon->seal = seal;
2746
	rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
A
Aurelien Aptel 已提交
2747 2748 2749
	free_xid(xid);

	if (rc) {
2750
		cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
A
Aurelien Aptel 已提交
2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790
		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;
}

2791
static struct cifs_ses *
2792
cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
L
Linus Torvalds 已提交
2793
{
2794
	struct cifs_ses *ses;
2795

2796
	spin_lock(&cifs_tcp_ses_lock);
2797
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
2798 2799
		if (ses->status == CifsExiting)
			continue;
2800 2801
		if (!match_session(ses, vol))
			continue;
2802
		++ses->ses_count;
2803
		spin_unlock(&cifs_tcp_ses_lock);
2804 2805
		return ses;
	}
2806
	spin_unlock(&cifs_tcp_ses_lock);
2807 2808
	return NULL;
}
2809

2810
void cifs_put_smb_ses(struct cifs_ses *ses)
2811
{
2812
	unsigned int rc, xid;
2813
	struct TCP_Server_Info *server = ses->server;
2814

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

2817
	spin_lock(&cifs_tcp_ses_lock);
2818 2819 2820 2821
	if (ses->status == CifsExiting) {
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}
2822
	if (--ses->ses_count > 0) {
2823
		spin_unlock(&cifs_tcp_ses_lock);
2824 2825
		return;
	}
2826 2827
	if (ses->status == CifsGood)
		ses->status = CifsExiting;
2828
	spin_unlock(&cifs_tcp_ses_lock);
2829

A
Aurelien Aptel 已提交
2830 2831
	cifs_free_ipc(ses);

2832
	if (ses->status == CifsExiting && server->ops->logoff) {
2833
		xid = get_xid();
2834 2835
		rc = server->ops->logoff(xid, ses);
		if (rc)
2836
			cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2837
				__func__, rc);
2838
		_free_xid(xid);
2839
	}
2840 2841 2842 2843 2844

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

2845 2846 2847 2848 2849 2850 2851 2852
	/* 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);
	}

2853
	sesInfoFree(ses);
2854
	cifs_put_tcp_session(server, 0);
2855
}
2856

2857 2858
#ifdef CONFIG_KEYS

2859 2860
/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
2861 2862 2863 2864 2865 2866

/* 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;
2867
	int is_domain = 0;
2868 2869
	const char *delim, *payload;
	char *desc;
2870 2871 2872 2873 2874
	ssize_t len;
	struct key *key;
	struct TCP_Server_Info *server = ses->server;
	struct sockaddr_in *sa;
	struct sockaddr_in6 *sa6;
2875
	const struct user_key_payload *upayload;
2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891

	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:
2892 2893
		cifs_dbg(FYI, "Bad ss_family (%hu)\n",
			 server->dstaddr.ss_family);
2894 2895 2896 2897
		rc = -EINVAL;
		goto out_err;
	}

2898
	cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
2899
	key = request_key(&key_type_logon, desc, "");
2900 2901
	if (IS_ERR(key)) {
		if (!ses->domainName) {
2902
			cifs_dbg(FYI, "domainName is NULL\n");
2903 2904 2905 2906 2907 2908
			rc = PTR_ERR(key);
			goto out_err;
		}

		/* didn't work, try to find a domain key */
		sprintf(desc, "cifs:d:%s", ses->domainName);
2909
		cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
2910
		key = request_key(&key_type_logon, desc, "");
2911 2912 2913 2914
		if (IS_ERR(key)) {
			rc = PTR_ERR(key);
			goto out_err;
		}
2915
		is_domain = 1;
2916 2917 2918
	}

	down_read(&key->sem);
2919
	upayload = user_key_payload_locked(key);
2920
	if (IS_ERR_OR_NULL(upayload)) {
2921
		rc = upayload ? PTR_ERR(upayload) : -EINVAL;
2922 2923 2924 2925
		goto out_key_put;
	}

	/* find first : in payload */
2926
	payload = upayload->data;
2927
	delim = strnchr(payload, upayload->datalen, ':');
2928
	cifs_dbg(FYI, "payload=%s\n", payload);
2929
	if (!delim) {
2930 2931
		cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
			 upayload->datalen);
2932 2933 2934 2935 2936
		rc = -EINVAL;
		goto out_key_put;
	}

	len = delim - payload;
2937
	if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
2938 2939
		cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
			 len);
2940 2941 2942 2943 2944 2945
		rc = -EINVAL;
		goto out_key_put;
	}

	vol->username = kstrndup(payload, len, GFP_KERNEL);
	if (!vol->username) {
2946 2947
		cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
			 len);
2948 2949 2950
		rc = -ENOMEM;
		goto out_key_put;
	}
2951
	cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
2952 2953

	len = key->datalen - (len + 1);
2954
	if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
2955
		cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
2956 2957 2958 2959 2960 2961 2962 2963 2964
		rc = -EINVAL;
		kfree(vol->username);
		vol->username = NULL;
		goto out_key_put;
	}

	++delim;
	vol->password = kstrndup(delim, len, GFP_KERNEL);
	if (!vol->password) {
2965 2966
		cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
			 len);
2967 2968 2969 2970 2971 2972
		rc = -ENOMEM;
		kfree(vol->username);
		vol->username = NULL;
		goto out_key_put;
	}

2973 2974 2975 2976 2977 2978 2979 2980 2981
	/*
	 * 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) {
J
Joe Perches 已提交
2982 2983
			cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
				 len);
2984 2985 2986
			rc = -ENOMEM;
			kfree(vol->username);
			vol->username = NULL;
2987
			kfree_sensitive(vol->password);
2988 2989 2990 2991 2992
			vol->password = NULL;
			goto out_key_put;
		}
	}

2993 2994 2995 2996 2997
out_key_put:
	up_read(&key->sem);
	key_put(key);
out_err:
	kfree(desc);
2998
	cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009
	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 */

3010 3011 3012 3013 3014 3015 3016
/**
 * 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.
 */
3017
struct cifs_ses *
3018 3019
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
{
3020 3021
	int rc = -ENOMEM;
	unsigned int xid;
3022
	struct cifs_ses *ses;
3023 3024
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3025

3026
	xid = get_xid();
3027

3028
	ses = cifs_find_smb_ses(server, volume_info);
3029
	if (ses) {
3030 3031
		cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
			 ses->status);
3032 3033

		mutex_lock(&ses->session_mutex);
3034 3035 3036 3037 3038
		rc = cifs_negotiate_protocol(xid, ses);
		if (rc) {
			mutex_unlock(&ses->session_mutex);
			/* problem -- put our ses reference */
			cifs_put_smb_ses(ses);
3039
			free_xid(xid);
3040 3041
			return ERR_PTR(rc);
		}
3042
		if (ses->need_reconnect) {
3043
			cifs_dbg(FYI, "Session needs reconnect\n");
3044 3045 3046 3047 3048 3049
			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);
3050
				free_xid(xid);
3051 3052 3053 3054
				return ERR_PTR(rc);
			}
		}
		mutex_unlock(&ses->session_mutex);
3055 3056

		/* existing SMB ses has a server reference already */
3057
		cifs_put_tcp_session(server, 0);
3058
		free_xid(xid);
3059 3060 3061
		return ses;
	}

3062
	cifs_dbg(FYI, "Existing smb sess not found\n");
3063 3064 3065 3066 3067 3068
	ses = sesInfoAlloc();
	if (ses == NULL)
		goto get_ses_fail;

	/* new SMB session uses our server ref */
	ses->server = server;
3069 3070
	if (server->dstaddr.ss_family == AF_INET6)
		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
3071
	else
3072
		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
3073

3074 3075 3076 3077 3078
	if (volume_info->username) {
		ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
		if (!ses->user_name)
			goto get_ses_fail;
	}
3079 3080 3081 3082 3083 3084 3085 3086

	/* 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) {
3087 3088 3089
		ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
		if (!ses->domainName)
			goto get_ses_fail;
3090
	}
3091 3092
	if (volume_info->domainauto)
		ses->domainAuto = volume_info->domainauto;
3093
	ses->cred_uid = volume_info->cred_uid;
3094
	ses->linux_uid = volume_info->linux_uid;
3095

3096 3097
	ses->sectype = volume_info->sectype;
	ses->sign = volume_info->sign;
3098
	mutex_lock(&ses->session_mutex);
3099 3100 3101 3102 3103 3104

	/* 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;

3105 3106 3107
	rc = cifs_negotiate_protocol(xid, ses);
	if (!rc)
		rc = cifs_setup_session(xid, ses, volume_info->local_nls);
3108 3109 3110 3111 3112

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

3113
	mutex_unlock(&ses->session_mutex);
3114
	if (rc)
3115 3116
		goto get_ses_fail;

3117
	/* success, put it on the list and add it as first channel */
3118
	spin_lock(&cifs_tcp_ses_lock);
3119
	list_add(&ses->smb_ses_list, &server->smb_ses_list);
3120
	spin_unlock(&cifs_tcp_ses_lock);
3121

3122
	free_xid(xid);
A
Aurelien Aptel 已提交
3123 3124 3125

	cifs_setup_ipc(ses, volume_info);

3126 3127 3128 3129
	return ses;

get_ses_fail:
	sesInfoFree(ses);
3130
	free_xid(xid);
3131 3132 3133
	return ERR_PTR(rc);
}

3134
static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
3135 3136 3137
{
	if (tcon->tidStatus == CifsExiting)
		return 0;
3138
	if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
3139
		return 0;
3140 3141 3142 3143
	if (tcon->seal != volume_info->seal)
		return 0;
	if (tcon->snapshot_time != volume_info->snapshot_time)
		return 0;
3144 3145
	if (tcon->handle_timeout != volume_info->handle_timeout)
		return 0;
3146 3147
	if (tcon->no_lease != volume_info->no_lease)
		return 0;
S
Steve French 已提交
3148 3149
	if (tcon->nodelete != volume_info->nodelete)
		return 0;
3150 3151 3152
	return 1;
}

3153
static struct cifs_tcon *
3154
cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
3155 3156
{
	struct list_head *tmp;
3157
	struct cifs_tcon *tcon;
3158

3159
	spin_lock(&cifs_tcp_ses_lock);
3160
	list_for_each(tmp, &ses->tcon_list) {
3161
		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
3162 3163 3164 3165
#ifdef CONFIG_CIFS_DFS_UPCALL
		if (tcon->dfs_path)
			continue;
#endif
3166
		if (!match_tcon(tcon, volume_info))
3167 3168
			continue;
		++tcon->tc_count;
3169
		spin_unlock(&cifs_tcp_ses_lock);
3170
		return tcon;
L
Linus Torvalds 已提交
3171
	}
3172
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
3173 3174 3175
	return NULL;
}

3176
void
3177
cifs_put_tcon(struct cifs_tcon *tcon)
3178
{
3179
	unsigned int xid;
A
Aurelien Aptel 已提交
3180
	struct cifs_ses *ses;
3181

A
Aurelien Aptel 已提交
3182 3183 3184 3185 3186 3187 3188 3189
	/*
	 * 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;
3190
	cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
3191
	spin_lock(&cifs_tcp_ses_lock);
3192
	if (--tcon->tc_count > 0) {
3193
		spin_unlock(&cifs_tcp_ses_lock);
3194 3195 3196 3197
		return;
	}

	list_del_init(&tcon->tcon_list);
3198
	spin_unlock(&cifs_tcp_ses_lock);
3199

3200
	xid = get_xid();
3201 3202
	if (ses->server->ops->tree_disconnect)
		ses->server->ops->tree_disconnect(xid, tcon);
3203
	_free_xid(xid);
3204

3205
	cifs_fscache_release_super_cookie(tcon);
3206
	tconInfoFree(tcon);
3207 3208 3209
	cifs_put_smb_ses(ses);
}

3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229
/**
 * 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.
 */
3230 3231
static struct cifs_tcon *
cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
3232 3233
{
	int rc, xid;
3234
	struct cifs_tcon *tcon;
3235

3236
	tcon = cifs_find_tcon(ses, volume_info);
3237
	if (tcon) {
3238 3239 3240 3241
		/*
		 * tcon has refcount already incremented but we need to
		 * decrement extra ses reference gotten by caller (case b)
		 */
3242
		cifs_dbg(FYI, "Found match on UNC path\n");
3243 3244 3245 3246
		cifs_put_smb_ses(ses);
		return tcon;
	}

3247 3248 3249 3250 3251
	if (!ses->server->ops->tree_connect) {
		rc = -ENOSYS;
		goto out_fail;
	}

3252 3253 3254 3255 3256 3257
	tcon = tconInfoAlloc();
	if (tcon == NULL) {
		rc = -ENOMEM;
		goto out_fail;
	}

3258 3259 3260 3261 3262 3263 3264 3265 3266 3267
	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;
	}

3268 3269 3270 3271 3272 3273 3274 3275 3276 3277
	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;
	}

3278 3279 3280 3281 3282 3283 3284 3285 3286
	tcon->ses = ses;
	if (volume_info->password) {
		tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
		if (!tcon->password) {
			rc = -ENOMEM;
			goto out_fail;
		}
	}

3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302
	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;
		}
	}

3303 3304
	if (volume_info->linux_ext) {
		if (ses->server->posix_ext_supported) {
3305
			tcon->posix_extensions = true;
J
Joe Perches 已提交
3306
			pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
3307
		} else {
J
Joe Perches 已提交
3308
			cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
3309 3310
			rc = -EOPNOTSUPP;
			goto out_fail;
3311
		}
3312 3313
	}

3314 3315 3316 3317
	/*
	 * BB Do we need to wrap session_mutex around this TCon call and Unix
	 * SetFS as we do on SessSetup and reconnect?
	 */
3318
	xid = get_xid();
3319 3320
	rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
					    volume_info->local_nls);
3321
	free_xid(xid);
3322
	cifs_dbg(FYI, "Tcon rc = %d\n", rc);
3323 3324 3325
	if (rc)
		goto out_fail;

3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347
	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 已提交
3348 3349 3350 3351 3352 3353 3354 3355
	} 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;
3356 3357
	}

3358 3359 3360 3361 3362 3363 3364 3365
	/* 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");
	}

3366 3367 3368 3369 3370 3371 3372 3373 3374 3375
	if (volume_info->no_lease) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
				"SMB2 or later required for nolease option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
			tcon->no_lease = volume_info->no_lease;
	}

3376 3377 3378 3379 3380
	/*
	 * 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.
	 */
3381 3382
	tcon->retry = volume_info->retry;
	tcon->nocase = volume_info->nocase;
3383 3384 3385 3386
	if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
		tcon->nohandlecache = volume_info->nohandlecache;
	else
		tcon->nohandlecache = 1;
S
Steve French 已提交
3387
	tcon->nodelete = volume_info->nodelete;
3388
	tcon->local_lease = volume_info->local_lease;
3389
	INIT_LIST_HEAD(&tcon->pending_opens);
3390

3391
	spin_lock(&cifs_tcp_ses_lock);
3392
	list_add(&tcon->tcon_list, &ses->tcon_list);
3393
	spin_unlock(&cifs_tcp_ses_lock);
3394

3395 3396
	cifs_fscache_get_super_cookie(tcon);

3397 3398 3399 3400 3401 3402 3403
	return tcon;

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

3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420
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;
}
3421

3422 3423 3424 3425 3426
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;
3427 3428
	unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
	unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
3429 3430 3431 3432

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

3433 3434 3435 3436
	if (old->mnt_cifs_serverino_autodisabled)
		newflags &= ~CIFS_MOUNT_SERVER_INUM;

	if (oldflags != newflags)
3437 3438 3439
		return 0;

	/*
3440 3441
	 * 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.
3442 3443 3444 3445
	 */
	if (new->wsize && new->wsize < old->wsize)
		return 0;

3446 3447 3448
	if (new->rsize && new->rsize < old->rsize)
		return 0;

3449
	if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464
		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;
}

3465 3466 3467 3468 3469
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;
3470 3471 3472 3473
	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;
3474

S
Sachin Prabhu 已提交
3475
	if (old_set && new_set && !strcmp(new->prepath, old->prepath))
3476
		return 1;
S
Sachin Prabhu 已提交
3477 3478 3479
	else if (!old_set && !new_set)
		return 1;

3480 3481 3482
	return 0;
}

3483 3484 3485 3486 3487 3488 3489
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;
3490 3491
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507
	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;

3508
	if (!match_server(tcp_srv, volume_info) ||
3509
	    !match_session(ses, volume_info) ||
3510
	    !match_tcon(tcon, volume_info) ||
3511
	    !match_prepath(sb, mnt_data)) {
3512 3513 3514 3515 3516 3517 3518
		rc = 0;
		goto out;
	}

	rc = compare_mount_options(sb, mnt_data);
out:
	spin_unlock(&cifs_tcp_ses_lock);
3519
	cifs_put_tlink(tlink);
3520 3521 3522
	return rc;
}

3523 3524 3525 3526 3527 3528 3529 3530
#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;
3531
	BUG_ON(!sock_allow_reclassification(sk));
3532 3533 3534 3535 3536 3537 3538 3539
	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;
3540
	BUG_ON(!sock_allow_reclassification(sk));
3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
	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 已提交
3556
/* See RFC1001 section 14 on representation of Netbios names */
3557
static void rfc1002mangle(char *target, char *source, unsigned int length)
L
Linus Torvalds 已提交
3558
{
3559
	unsigned int i, j;
L
Linus Torvalds 已提交
3560

3561
	for (i = 0, j = 0; i < (length); i++) {
L
Linus Torvalds 已提交
3562 3563 3564
		/* mask a nibble at a time and encode */
		target[j] = 'A' + (0x0F & (source[i] >> 4));
		target[j+1] = 'A' + (0x0F & source[i]);
3565
		j += 2;
L
Linus Torvalds 已提交
3566 3567 3568 3569
	}

}

3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585
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)
3586
				cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3587
					 &saddr6->sin6_addr, rc);
3588
			else
3589
				cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3590
					 &saddr4->sin_addr.s_addr, rc);
3591 3592 3593 3594
		}
	}
	return rc;
}
L
Linus Torvalds 已提交
3595 3596

static int
3597
ip_rfc1001_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
3598 3599
{
	int rc = 0;
3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611
	/*
	 * 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;

3612
		if (server->server_RFC1001_name[0] != 0)
3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628
			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.
		 */
3629
		if (server->workstation_RFC1001_name[0] != 0)
3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644
			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 */
3645
		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671
		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;
3672
	__be16 sport;
3673
	int slen, sfamily;
3674
	struct socket *socket = server->ssocket;
3675 3676 3677 3678 3679
	struct sockaddr *saddr;

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

	if (server->dstaddr.ss_family == AF_INET6) {
3680 3681 3682
		struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;

		sport = ipv6->sin6_port;
3683 3684
		slen = sizeof(struct sockaddr_in6);
		sfamily = AF_INET6;
3685 3686
		cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
				ntohs(sport));
3687
	} else {
3688 3689 3690
		struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;

		sport = ipv4->sin_port;
3691 3692
		slen = sizeof(struct sockaddr_in);
		sfamily = AF_INET;
3693 3694
		cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
				ntohs(sport));
3695
	}
L
Linus Torvalds 已提交
3696

3697
	if (socket == NULL) {
3698 3699
		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
				   IPPROTO_TCP, &socket, 1);
L
Linus Torvalds 已提交
3700
		if (rc < 0) {
3701
			cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
3702
			server->ssocket = NULL;
L
Linus Torvalds 已提交
3703 3704
			return rc;
		}
3705 3706

		/* BB other socket options to set KEEPALIVE, NODELAY? */
3707
		cifs_dbg(FYI, "Socket created\n");
3708 3709
		server->ssocket = socket;
		socket->sk->sk_allocation = GFP_NOFS;
3710 3711 3712 3713
		if (sfamily == AF_INET6)
			cifs_reclassify_socket6(socket);
		else
			cifs_reclassify_socket4(socket);
L
Linus Torvalds 已提交
3714 3715
	}

3716 3717 3718 3719
	rc = bind_socket(server);
	if (rc < 0)
		return rc;

3720 3721
	/*
	 * Eventually check for other socket options to change from
3722 3723
	 * the default. sock_setsockopt not used because it expects
	 * user space buffer
3724 3725
	 */
	socket->sk->sk_rcvtimeo = 7 * HZ;
3726
	socket->sk->sk_sndtimeo = 5 * HZ;
3727

3728
	/* make the bufsizes depend on wsize/rsize and max requests */
3729 3730 3731 3732 3733
	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;
3734
	}
L
Linus Torvalds 已提交
3735

3736 3737
	if (server->tcp_nodelay)
		tcp_sock_set_nodelay(socket->sk);
3738

3739
	cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
3740
		 socket->sk->sk_sndbuf,
3741
		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3742

3743 3744
	rc = socket->ops->connect(socket, saddr, slen,
				  server->noblockcnt ? O_NONBLOCK : 0);
3745 3746 3747 3748 3749 3750
	/*
	 * 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)
3751
		rc = 0;
3752
	if (rc < 0) {
3753
		cifs_dbg(FYI, "Error %d connecting to server\n", rc);
3754 3755 3756 3757 3758
		sock_release(socket);
		server->ssocket = NULL;
		return rc;
	}

3759 3760
	if (sport == htons(RFC1001_PORT))
		rc = ip_rfc1001_connect(server);
3761

L
Linus Torvalds 已提交
3762 3763 3764 3765
	return rc;
}

static int
3766
ip_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
3767
{
3768
	__be16 *sport;
3769 3770
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
L
Linus Torvalds 已提交
3771

3772 3773 3774 3775
	if (server->dstaddr.ss_family == AF_INET6)
		sport = &addr6->sin6_port;
	else
		sport = &addr->sin_port;
L
Linus Torvalds 已提交
3776

3777 3778
	if (*sport == 0) {
		int rc;
L
Linus Torvalds 已提交
3779

3780 3781
		/* try with 445 port at first */
		*sport = htons(CIFS_PORT);
3782

3783
		rc = generic_ip_connect(server);
L
Linus Torvalds 已提交
3784
		if (rc >= 0)
3785
			return rc;
3786

3787 3788
		/* if it failed, try with 139 port */
		*sport = htons(RFC1001_PORT);
3789 3790
	}

3791
	return generic_ip_connect(server);
L
Linus Torvalds 已提交
3792 3793
}

3794
void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
3795
			  struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806
{
	/* 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);
3807

3808 3809 3810
	if (vol_info && vol_info->no_linux_ext) {
		tcon->fsUnixInfo.Capability = 0;
		tcon->unix_ext = 0; /* Unix Extensions disabled */
3811
		cifs_dbg(FYI, "Linux protocol extensions disabled\n");
3812 3813 3814 3815 3816
		return;
	} else if (vol_info)
		tcon->unix_ext = 1; /* Unix Extensions supported */

	if (tcon->unix_ext == 0) {
3817
		cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
3818 3819
		return;
	}
3820

S
Steve French 已提交
3821
	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
3822
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3823
		cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
3824 3825
		/* check for reconnect case in which we do not
		   want to change the mount behavior if we can avoid it */
S
Steve French 已提交
3826
		if (vol_info == NULL) {
3827
			/* turn off POSIX ACL and PATHNAMES if not set
3828 3829 3830
			   originally at mount time */
			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
3831 3832
			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
3833
					cifs_dbg(VFS, "POSIXPATH support change\n");
3834
				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
3835
			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3836 3837
				cifs_dbg(VFS, "possible reconnect error\n");
				cifs_dbg(VFS, "server disabled POSIX path support\n");
3838
			}
3839
		}
3840

3841
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3842
			cifs_dbg(VFS, "per-share encryption not supported yet\n");
3843

3844
		cap &= CIFS_UNIX_CAP_MASK;
3845
		if (vol_info && vol_info->no_psx_acl)
3846
			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
3847
		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
3848
			cifs_dbg(FYI, "negotiated posix acl support\n");
3849 3850 3851
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
					CIFS_MOUNT_POSIXACL;
3852 3853
		}

3854
		if (vol_info && vol_info->posix_paths == 0)
3855
			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
3856
		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3857
			cifs_dbg(FYI, "negotiate posix pathnames\n");
3858 3859
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
3860 3861
					CIFS_MOUNT_POSIX_PATHS;
		}
3862

3863
		cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
3864
#ifdef CONFIG_CIFS_DEBUG2
3865
		if (cap & CIFS_UNIX_FCNTL_CAP)
3866
			cifs_dbg(FYI, "FCNTL cap\n");
3867
		if (cap & CIFS_UNIX_EXTATTR_CAP)
3868
			cifs_dbg(FYI, "EXTATTR cap\n");
3869
		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
3870
			cifs_dbg(FYI, "POSIX path cap\n");
3871
		if (cap & CIFS_UNIX_XATTR_CAP)
3872
			cifs_dbg(FYI, "XATTR cap\n");
3873
		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
3874
			cifs_dbg(FYI, "POSIX ACL cap\n");
3875
		if (cap & CIFS_UNIX_LARGE_READ_CAP)
3876
			cifs_dbg(FYI, "very large read cap\n");
3877
		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
3878
			cifs_dbg(FYI, "very large write cap\n");
3879
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3880
			cifs_dbg(FYI, "transport encryption cap\n");
3881
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3882
			cifs_dbg(FYI, "mandatory transport encryption cap\n");
3883 3884
#endif /* CIFS_DEBUG2 */
		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
3885
			if (vol_info == NULL) {
3886
				cifs_dbg(FYI, "resetting capabilities failed\n");
3887
			} else
3888
				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");
3889

3890 3891 3892 3893
		}
	}
}

3894
int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3895
			struct cifs_sb_info *cifs_sb)
3896
{
3897 3898
	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);

3899 3900 3901
	spin_lock_init(&cifs_sb->tlink_tree_lock);
	cifs_sb->tlink_tree = RB_ROOT;

3902
	cifs_sb->bsize = pvolume_info->bsize;
3903
	/*
3904 3905
	 * Temporarily set r/wsize for matching superblock. If we end up using
	 * new sb then client will later negotiate it downward if needed.
3906
	 */
3907
	cifs_sb->rsize = pvolume_info->rsize;
3908 3909
	cifs_sb->wsize = pvolume_info->wsize;

S
Steve French 已提交
3910 3911 3912 3913
	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;
3914
	cifs_dbg(FYI, "file mode: %04ho  dir mode: %04ho\n",
3915
		 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
S
Steve French 已提交
3916

3917
	cifs_sb->actimeo = pvolume_info->actimeo;
3918
	cifs_sb->local_nls = pvolume_info->local_nls;
3919

3920 3921
	if (pvolume_info->nodfs)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
S
Steve French 已提交
3922 3923 3924 3925
	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;
3926 3927
	if (pvolume_info->setuidfromacl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
S
Steve French 已提交
3928 3929 3930
	if (pvolume_info->server_ino)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
	if (pvolume_info->remap)
3931 3932
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
	if (pvolume_info->sfu_remap)
S
Steve French 已提交
3933 3934 3935 3936 3937 3938 3939
		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 已提交
3940 3941
	if (pvolume_info->nohandlecache)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
3942
	if (pvolume_info->nostrictsync)
S
Steve French 已提交
3943
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
3944 3945
	if (pvolume_info->mand_lock)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
3946 3947
	if (pvolume_info->rwpidforward)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
3948 3949
	if (pvolume_info->mode_ace)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
S
Steve French 已提交
3950 3951
	if (pvolume_info->cifs_acl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
3952
	if (pvolume_info->backupuid_specified) {
3953
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
3954 3955 3956
		cifs_sb->mnt_backupuid = pvolume_info->backupuid;
	}
	if (pvolume_info->backupgid_specified) {
3957
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
3958 3959
		cifs_sb->mnt_backupgid = pvolume_info->backupgid;
	}
S
Steve French 已提交
3960 3961 3962 3963 3964 3965
	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;
3966 3967
	if (pvolume_info->fsc)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
J
Jeff Layton 已提交
3968 3969 3970
	if (pvolume_info->multiuser)
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
					    CIFS_MOUNT_NO_PERM);
3971 3972
	if (pvolume_info->strict_io)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
S
Steve French 已提交
3973
	if (pvolume_info->direct_io) {
3974
		cifs_dbg(FYI, "mounting share using direct i/o\n");
S
Steve French 已提交
3975 3976
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
	}
3977 3978 3979
	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;
3980 3981 3982 3983
	} 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);
3984
	}
3985 3986
	if (pvolume_info->mfsymlinks) {
		if (pvolume_info->sfu_emul) {
3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998
			/*
			 * 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");
3999
		}
4000
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
4001
	}
S
Steve French 已提交
4002 4003

	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
4004
		cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
4005 4006 4007 4008 4009 4010 4011 4012

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

	return 0;
4013 4014
}

P
Paulo Alcantara 已提交
4015 4016
void
cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
I
Igor Mammedov 已提交
4017
{
4018
	kfree(volume_info->username);
4019
	kfree_sensitive(volume_info->password);
4020
	kfree(volume_info->UNC);
4021 4022
	kfree(volume_info->domainname);
	kfree(volume_info->iocharset);
I
Igor Mammedov 已提交
4023
	kfree(volume_info->prepath);
J
Jeff Layton 已提交
4024 4025 4026 4027 4028 4029 4030
}

void
cifs_cleanup_volume_info(struct smb_vol *volume_info)
{
	if (!volume_info)
		return;
P
Paulo Alcantara 已提交
4031
	cifs_cleanup_volume_info_contents(volume_info);
I
Igor Mammedov 已提交
4032 4033 4034
	kfree(volume_info);
}

P
Paulo Alcantara 已提交
4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094
/* 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))) {
4095
		cifs_server_dbg(VFS, "persistent handles not supported by server\n");
P
Paulo Alcantara 已提交
4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126
		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 */
4127
	if (!tcon->pipe && server->ops->qfs_tcon) {
4128
		server->ops->qfs_tcon(*xid, tcon, cifs_sb);
4129 4130
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
			if (tcon->fsDevInfo.DeviceCharacteristics &
4131
			    cpu_to_le32(FILE_READ_ONLY_DEVICE))
4132
				cifs_dbg(VFS, "mounted to read only share\n");
4133 4134
			else if ((cifs_sb->mnt_cifs_flags &
				  CIFS_MOUNT_RW_CACHE) == 0)
4135
				cifs_dbg(VFS, "read only mount of RW share\n");
4136
			/* no need to log a RW mount of a typical RW share */
4137 4138
		}
	}
P
Paulo Alcantara 已提交
4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170

	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 已提交
4171

S
Steve French 已提交
4172
#ifdef CONFIG_CIFS_DFS_UPCALL
4173 4174 4175 4176
/*
 * cifs_build_path_to_root returns full path to root when we do not have an
 * exiting connection (tcon)
 */
I
Igor Mammedov 已提交
4177
static char *
4178
build_unc_path_to_root(const struct smb_vol *vol,
4179
		       const struct cifs_sb_info *cifs_sb, bool useppath)
I
Igor Mammedov 已提交
4180
{
4181
	char *full_path, *pos;
4182 4183
	unsigned int pplen = useppath && vol->prepath ?
		strlen(vol->prepath) + 1 : 0;
4184
	unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
I
Igor Mammedov 已提交
4185

4186 4187 4188
	if (unc_len > MAX_TREE_SIZE)
		return ERR_PTR(-EINVAL);

4189
	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
I
Igor Mammedov 已提交
4190 4191 4192
	if (full_path == NULL)
		return ERR_PTR(-ENOMEM);

4193
	memcpy(full_path, vol->UNC, unc_len);
4194 4195 4196
	pos = full_path + unc_len;

	if (pplen) {
4197
		*pos = CIFS_DIR_SEP(cifs_sb);
4198
		memcpy(pos + 1, vol->prepath, pplen);
4199 4200 4201 4202
		pos += pplen;
	}

	*pos = '\0'; /* add trailing null */
4203
	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
4204
	cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
I
Igor Mammedov 已提交
4205 4206
	return full_path;
}
4207

4208 4209 4210
/**
 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
 *
4211
 *
4212 4213 4214
 * 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.
4215 4216 4217 4218 4219
 *
 * Returns the rc from get_dfs_path to the caller, which can be used to
 * determine whether there were referrals.
 */
static int
4220
expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
4221
		    struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
4222
		    char *ref_path)
4223 4224
{
	int rc;
4225
	struct dfs_info3_param referral = {0};
4226
	char *full_path = NULL, *mdata = NULL;
4227

4228 4229 4230
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
		return -EREMOTE;

4231
	full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
4232 4233 4234
	if (IS_ERR(full_path))
		return PTR_ERR(full_path);

4235 4236 4237
	rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
			    ref_path, &referral, NULL);
	if (!rc) {
4238 4239 4240
		char *fake_devname = NULL;

		mdata = cifs_compose_mount_options(cifs_sb->mountdata,
4241
						   full_path + 1, &referral,
4242
						   &fake_devname);
4243
		free_dfs_info_param(&referral);
4244

4245 4246 4247
		if (IS_ERR(mdata)) {
			rc = PTR_ERR(mdata);
			mdata = NULL;
J
Jeff Layton 已提交
4248
		} else {
P
Paulo Alcantara 已提交
4249
			cifs_cleanup_volume_info_contents(volume_info);
J
Jeff Layton 已提交
4250
			rc = cifs_setup_volume_info(volume_info, mdata,
4251
						    fake_devname, false);
4252
		}
J
Jeff Layton 已提交
4253 4254
		kfree(fake_devname);
		kfree(cifs_sb->mountdata);
4255
		cifs_sb->mountdata = mdata;
4256 4257 4258 4259
	}
	kfree(full_path);
	return rc;
}
4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281

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;
4282
	scnprintf(new_unc, len, "\\%s", tgt);
4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296

	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;
}

4297
static int setup_dfs_tgt_conn(const char *path, const char *full_path,
4298
			      const struct dfs_cache_tgt_iterator *tgt_it,
4299 4300
			      struct cifs_sb_info *cifs_sb, struct smb_vol *vol, unsigned int *xid,
			      struct TCP_Server_Info **server, struct cifs_ses **ses,
4301 4302 4303 4304 4305
			      struct cifs_tcon **tcon)
{
	int rc;
	struct dfs_info3_param ref = {0};
	char *mdata = NULL, *fake_devname = NULL;
4306
	struct smb_vol fake_vol = {NULL};
4307 4308 4309 4310 4311 4312 4313

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

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

4314
	mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname);
4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336
	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);
4337
		if (!rc || (*server && *ses)) {
4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348
			/*
			 * 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;
}

4349 4350 4351 4352
static int do_dfs_failover(const char *path, const char *full_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)
4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370
{
	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 */
4371 4372 4373
		rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, vol, xid, server, ses,
					tcon);
		if (!rc || (*server && *ses))
4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388
			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 已提交
4389
#endif
I
Igor Mammedov 已提交
4390

4391
int
4392
cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
4393
			const char *devname, bool is_smb3)
L
Linus Torvalds 已提交
4394
{
4395
	int rc = 0;
L
Linus Torvalds 已提交
4396

4397
	if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
4398
		return -EINVAL;
L
Linus Torvalds 已提交
4399

4400
	if (volume_info->nullauth) {
4401
		cifs_dbg(FYI, "Anonymous login\n");
J
Jeff Layton 已提交
4402 4403
		kfree(volume_info->username);
		volume_info->username = NULL;
4404
	} else if (volume_info->username) {
L
Linus Torvalds 已提交
4405
		/* BB fixme parse for domain name here */
4406
		cifs_dbg(FYI, "Username: %s\n", volume_info->username);
L
Linus Torvalds 已提交
4407
	} else {
4408
		cifs_dbg(VFS, "No username specified\n");
4409 4410
	/* In userspace mount helper we can get user name from alternate
	   locations such as env variables and files on disk */
4411
		return -EINVAL;
L
Linus Torvalds 已提交
4412 4413 4414
	}

	/* this is needed for ASCII cp to Unicode converts */
4415
	if (volume_info->iocharset == NULL) {
4416 4417
		/* load_nls_default cannot return null */
		volume_info->local_nls = load_nls_default();
L
Linus Torvalds 已提交
4418
	} else {
4419 4420
		volume_info->local_nls = load_nls(volume_info->iocharset);
		if (volume_info->local_nls == NULL) {
4421
			cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
4422
				 volume_info->iocharset);
4423
			return -ELIBACC;
L
Linus Torvalds 已提交
4424 4425
		}
	}
4426 4427 4428 4429

	return rc;
}

4430
struct smb_vol *
4431
cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
4432 4433 4434 4435
{
	int rc;
	struct smb_vol *volume_info;

4436
	volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
4437 4438 4439
	if (!volume_info)
		return ERR_PTR(-ENOMEM);

4440
	rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
4441 4442 4443 4444 4445 4446 4447 4448
	if (rc) {
		cifs_cleanup_volume_info(volume_info);
		volume_info = ERR_PTR(rc);
	}

	return volume_info;
}

4449 4450 4451 4452 4453
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,
4454 4455
					char *full_path,
					int added_treename)
4456 4457 4458 4459
{
	int rc;
	char *s;
	char sep, tmp;
4460
	int skip = added_treename ? 1 : 0;
4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474

	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++;
4475 4476 4477 4478 4479 4480 4481 4482
		/*
		 * if the treename is added, we then have to skip the first
		 * part within the separators
		 */
		if (skip) {
			skip = 0;
			continue;
		}
4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495
		/*
		 * 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 已提交
4496 4497 4498 4499 4500 4501 4502 4503
/*
 * 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)
4504
{
4505
	int rc;
P
Paulo Alcantara 已提交
4506
	char *full_path;
4507

P
Paulo Alcantara 已提交
4508 4509
	if (!server->ops->is_path_accessible)
		return -EOPNOTSUPP;
4510

P
Paulo Alcantara 已提交
4511 4512 4513 4514 4515 4516 4517
	/*
	 * 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;
4518

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

P
Paulo Alcantara 已提交
4521 4522 4523 4524 4525
	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
					     full_path);
	if (rc != 0 && rc != -EREMOTE) {
		kfree(full_path);
		return rc;
4526
	}
S
Steve French 已提交
4527

P
Paulo Alcantara 已提交
4528 4529
	if (rc != -EREMOTE) {
		rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4530
			cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
P
Paulo Alcantara 已提交
4531
		if (rc != 0) {
J
Joe Perches 已提交
4532
			cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
P
Paulo Alcantara 已提交
4533 4534 4535
			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
			rc = 0;
		}
4536
	}
I
Igor Mammedov 已提交
4537

P
Paulo Alcantara 已提交
4538 4539 4540
	kfree(full_path);
	return rc;
}
4541

P
Paulo Alcantara 已提交
4542
#ifdef CONFIG_CIFS_DFS_UPCALL
4543 4544
static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
			 struct cifs_ses **root_ses)
4545
{
4546 4547 4548 4549 4550 4551 4552 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
	if (ses) {
		spin_lock(&cifs_tcp_ses_lock);
		ses->ses_count++;
		ses->tcon_ipc->remap = cifs_remap(cifs_sb);
		spin_unlock(&cifs_tcp_ses_lock);
	}
	*root_ses = ses;
}

static void put_root_ses(struct cifs_ses *ses)
{
	if (ses)
		cifs_put_smb_ses(ses);
}

/* Check if a path component is remote and then update @dfs_path accordingly */
static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
			     const unsigned int xid, struct TCP_Server_Info *server,
			     struct cifs_tcon *tcon, char **dfs_path)
{
	char *path, *s;
	char sep = CIFS_DIR_SEP(cifs_sb), tmp;
	char *npath;
	int rc = 0;
	int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
	int skip = added_treename;

	path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename);
	if (!path)
		return -ENOMEM;

	/*
	 * Walk through the path components in @path and check if they're accessible. In case any of
	 * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
	 * (NOT including the remaining components).
	 */
	s = path;
	do {
		/* skip separators */
		while (*s && *s == sep)
			s++;
		if (!*s)
			break;
		/* next separator */
		while (*s && *s != sep)
			s++;
		/*
		 * if the treename is added, we then have to skip the first
		 * part within the separators
		 */
		if (skip) {
			skip = 0;
			continue;
		}
		tmp = *s;
		*s = 0;
		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
		if (rc && rc == -EREMOTE) {
			struct smb_vol v = {NULL};
			/* if @path contains a tree name, skip it in the prefix path */
			if (added_treename) {
				rc = cifs_parse_devname(path, &v);
				if (rc)
					break;
				rc = -EREMOTE;
				npath = build_unc_path_to_root(&v, cifs_sb, true);
				cifs_cleanup_volume_info_contents(&v);
			} else {
				v.UNC = vol->UNC;
				v.prepath = path + 1;
				npath = build_unc_path_to_root(&v, cifs_sb, true);
			}
			if (IS_ERR(npath)) {
				rc = PTR_ERR(npath);
				break;
			}
			kfree(*dfs_path);
			*dfs_path = npath;
		}
		*s = tmp;
	} while (rc == 0);

	kfree(path);
	return rc;
4630 4631
}

P
Paulo Alcantara 已提交
4632 4633 4634 4635
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
{
	int rc = 0;
	unsigned int xid;
4636 4637
	struct TCP_Server_Info *server = NULL;
	struct cifs_ses *ses = NULL, *root_ses = NULL;
P
Paulo Alcantara 已提交
4638
	struct cifs_tcon *tcon = NULL;
4639 4640 4641 4642
	int count = 0;
	char *ref_path = NULL, *full_path = NULL;
	char *oldmnt = NULL;
	char *mntdata = NULL;
4643

P
Paulo Alcantara 已提交
4644
	rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4645
	/*
4646 4647
	 * Unconditionally try to get an DFS referral (even cached) to determine whether it is an
	 * DFS mount.
4648
	 *
4649 4650
	 * Skip prefix path 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.
4651
	 */
4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662
	if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL,
			   NULL)) {
		/* No DFS referral was returned.  Looks like a regular share. */
		if (rc)
			goto error;
		/* Check if it is fully accessible and then mount it */
		rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
		if (!rc)
			goto out;
		if (rc != -EREMOTE)
			goto error;
4663
	}
4664 4665 4666
	/* Save mount options */
	mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL);
	if (!mntdata) {
4667 4668 4669
		rc = -ENOMEM;
		goto error;
	}
4670 4671 4672 4673 4674
	/* Get path of DFS root */
	ref_path = build_unc_path_to_root(vol, cifs_sb, false);
	if (IS_ERR(ref_path)) {
		rc = PTR_ERR(ref_path);
		ref_path = NULL;
4675 4676
		goto error;
	}
I
Igor Mammedov 已提交
4677

4678 4679 4680
	set_root_ses(cifs_sb, ses, &root_ses);
	do {
		/* Save full path of last DFS path we used to resolve final target server */
4681
		kfree(full_path);
4682
		full_path = build_unc_path_to_root(vol, cifs_sb, !!count);
4683 4684
		if (IS_ERR(full_path)) {
			rc = PTR_ERR(full_path);
4685
			full_path = NULL;
4686 4687
			break;
		}
4688 4689 4690
		/* Chase referral */
		oldmnt = cifs_sb->mountdata;
		rc = expand_dfs_referral(xid, root_ses, vol, cifs_sb, ref_path + 1);
P
Paulo Alcantara 已提交
4691 4692
		if (rc)
			break;
4693 4694
		/* Connect to new DFS target only if we were redirected */
		if (oldmnt != cifs_sb->mountdata) {
P
Paulo Alcantara 已提交
4695
			mount_put_conns(cifs_sb, xid, server, ses, tcon);
4696
			rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
P
Paulo Alcantara 已提交
4697
		}
4698 4699 4700 4701
		if (rc && !server && !ses) {
			/* Failed to connect. Try to connect to other targets in the referral. */
			rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, vol, root_ses, &xid,
					     &server, &ses, &tcon);
I
Igor Mammedov 已提交
4702
		}
4703 4704 4705 4706 4707
		if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses)
			break;
		if (!tcon)
			continue;
		/* Make sure that requests go through new root servers */
4708
		if (is_tcon_dfs(tcon)) {
4709 4710 4711 4712 4713 4714 4715 4716 4717
			put_root_ses(root_ses);
			set_root_ses(cifs_sb, ses, &root_ses);
		}
		/* Check for remaining path components and then continue chasing them (-EREMOTE) */
		rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path);
		/* Prevent recursion on broken link referrals */
		if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
			rc = -ELOOP;
	} while (rc == -EREMOTE);
I
Igor Mammedov 已提交
4718

4719
	if (rc)
P
Paulo Alcantara 已提交
4720
		goto error;
4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733
	put_root_ses(root_ses);
	root_ses = NULL;
	kfree(ref_path);
	ref_path = NULL;
	/*
	 * Store DFS full path in both superblock and tree connect structures.
	 *
	 * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so
	 * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS
	 * links, the prefix path is included in both and may be changed during reconnect.  See
	 * cifs_tree_connect().
	 */
	cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
4734 4735 4736 4737
	if (!cifs_sb->origin_fullpath) {
		rc = -ENOMEM;
		goto error;
	}
4738 4739 4740 4741
	spin_lock(&cifs_tcp_ses_lock);
	tcon->dfs_path = full_path;
	full_path = NULL;
	tcon->remap = cifs_remap(cifs_sb);
4742 4743
	spin_unlock(&cifs_tcp_ses_lock);

4744 4745 4746
	/* Add original volume information for DFS cache to be used when refreshing referrals */
	rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath);
	if (rc)
4747
		goto error;
4748 4749 4750 4751 4752 4753
	/*
	 * 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);
4754 4755 4756 4757 4758 4759 4760 4761 4762
	/*
	 * Force the use of prefix path to support failover on DFS paths that
	 * resolve to targets that have different prefix paths.
	 */
	cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
	kfree(cifs_sb->prepath);
	cifs_sb->prepath = vol->prepath;
	vol->prepath = NULL;

P
Paulo Alcantara 已提交
4763 4764
out:
	free_xid(xid);
4765
	cifs_try_adding_channels(ses);
P
Paulo Alcantara 已提交
4766
	return mount_setup_tlink(cifs_sb, ses, tcon);
4767

P
Paulo Alcantara 已提交
4768
error:
4769
	kfree(ref_path);
4770
	kfree(full_path);
4771 4772 4773
	kfree(mntdata);
	kfree(cifs_sb->origin_fullpath);
	put_root_ses(root_ses);
P
Paulo Alcantara 已提交
4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784
	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;
4785

P
Paulo Alcantara 已提交
4786 4787 4788
	rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
	if (rc)
		goto error;
4789

P
Paulo Alcantara 已提交
4790 4791 4792 4793 4794 4795
	if (tcon) {
		rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
		if (rc == -EREMOTE)
			rc = -EOPNOTSUPP;
		if (rc)
			goto error;
I
Igor Mammedov 已提交
4796 4797
	}

4798
	free_xid(xid);
P
Paulo Alcantara 已提交
4799 4800 4801 4802 4803

	return mount_setup_tlink(cifs_sb, ses, tcon);

error:
	mount_put_conns(cifs_sb, xid, server, ses, tcon);
L
Linus Torvalds 已提交
4804 4805
	return rc;
}
P
Paulo Alcantara 已提交
4806
#endif
L
Linus Torvalds 已提交
4807

4808
/*
A
Aurelien Aptel 已提交
4809
 * Issue a TREE_CONNECT request.
4810
 */
L
Linus Torvalds 已提交
4811
int
4812
CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
4813
	 const char *tree, struct cifs_tcon *tcon,
L
Linus Torvalds 已提交
4814 4815 4816 4817 4818 4819 4820 4821
	 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;
4822 4823
	int length;
	__u16 bytes_left, count;
L
Linus Torvalds 已提交
4824 4825 4826 4827 4828

	if (ses == NULL)
		return -EIO;

	smb_buffer = cifs_buf_get();
S
Steve French 已提交
4829
	if (smb_buffer == NULL)
L
Linus Torvalds 已提交
4830
		return -ENOMEM;
S
Steve French 已提交
4831

L
Linus Torvalds 已提交
4832 4833 4834 4835
	smb_buffer_response = smb_buffer;

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

4837
	smb_buffer->Mid = get_next_mid(ses->server);
L
Linus Torvalds 已提交
4838 4839 4840 4841 4842 4843 4844
	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 已提交
4845
	if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
4846
		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
4847
		*bcc_ptr = 0; /* password is null byte */
4848
		bcc_ptr++;              /* skip password */
4849
		/* already aligned so no need to do it below */
4850
	} else {
4851
		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
4852 4853 4854
		/* 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
4855
		   weaker LANMAN (which we do not send by default) is accepted
4856 4857
		   by Samba (not sure whether other servers allow
		   NTLMv2 password here) */
4858
#ifdef CONFIG_CIFS_WEAK_PW_HASH
4859
		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
4860
		    (ses->sectype == LANMAN))
4861
			calc_lanman_hash(tcon->password, ses->server->cryptkey,
4862
					 ses->server->sec_mode &
4863 4864
					    SECMODE_PW_ENCRYPT ? true : false,
					 bcc_ptr);
4865 4866
		else
#endif /* CIFS_WEAK_PW_HASH */
4867
		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
4868
					bcc_ptr, nls_codepage);
4869 4870 4871 4872 4873 4874
		if (rc) {
			cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
				 __func__, rc);
			cifs_buf_release(smb_buffer);
			return rc;
		}
4875

4876
		bcc_ptr += CIFS_AUTH_RESP_SIZE;
S
Steve French 已提交
4877
		if (ses->capabilities & CAP_UNICODE) {
4878 4879 4880 4881
			/* must align unicode strings */
			*bcc_ptr = 0; /* null byte password */
			bcc_ptr++;
		}
4882
	}
L
Linus Torvalds 已提交
4883

4884
	if (ses->server->sign)
L
Linus Torvalds 已提交
4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895
		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 =
4896
		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
4897
			6 /* max utf8 char length in bytes */ *
4898 4899
			(/* server len*/ + 256 /* share len */), nls_codepage);
		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
L
Linus Torvalds 已提交
4900 4901 4902 4903 4904 4905 4906 4907 4908
		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];
4909
	be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
L
Linus Torvalds 已提交
4910 4911
	pSMB->ByteCount = cpu_to_le16(count);

4912
	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
4913
			 0);
L
Linus Torvalds 已提交
4914 4915

	/* above now done in SendReceive */
A
Aurelien Aptel 已提交
4916
	if (rc == 0) {
4917 4918
		bool is_unicode;

L
Linus Torvalds 已提交
4919
		tcon->tidStatus = CifsGood;
S
Steve French 已提交
4920
		tcon->need_reconnect = false;
L
Linus Torvalds 已提交
4921 4922
		tcon->tid = smb_buffer_response->Tid;
		bcc_ptr = pByteArea(smb_buffer_response);
4923
		bytes_left = get_bcc(smb_buffer_response);
4924
		length = strnlen(bcc_ptr, bytes_left - 2);
4925 4926 4927 4928 4929
		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
			is_unicode = true;
		else
			is_unicode = false;

4930

4931
		/* skip service field (NB: this field is always ASCII) */
4932 4933 4934
		if (length == 3) {
			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
			    (bcc_ptr[2] == 'C')) {
4935
				cifs_dbg(FYI, "IPC connection\n");
A
Aurelien Aptel 已提交
4936 4937
				tcon->ipc = true;
				tcon->pipe = true;
4938 4939 4940 4941
			}
		} else if (length == 2) {
			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
				/* the most common case */
4942
				cifs_dbg(FYI, "disk share connection\n");
4943 4944
			}
		}
4945
		bcc_ptr += length + 1;
4946
		bytes_left -= (length + 1);
4947
		strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
4948 4949

		/* mostly informational -- no need to fail on error here */
4950
		kfree(tcon->nativeFileSystem);
4951
		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
4952
						      bytes_left, is_unicode,
4953 4954
						      nls_codepage);

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

S
Steve French 已提交
4957
		if ((smb_buffer_response->WordCount == 3) ||
S
Steve French 已提交
4958 4959
			 (smb_buffer_response->WordCount == 7))
			/* field is in same location */
4960 4961 4962
			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
		else
			tcon->Flags = 0;
4963
		cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
L
Linus Torvalds 已提交
4964 4965
	}

4966
	cifs_buf_release(smb_buffer);
L
Linus Torvalds 已提交
4967 4968 4969
	return rc;
}

4970 4971 4972 4973 4974 4975 4976
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 已提交
4977 4978
void
cifs_umount(struct cifs_sb_info *cifs_sb)
L
Linus Torvalds 已提交
4979
{
J
Jeff Layton 已提交
4980 4981 4982
	struct rb_root *root = &cifs_sb->tlink_tree;
	struct rb_node *node;
	struct tcon_link *tlink;
4983

4984 4985
	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);

J
Jeff Layton 已提交
4986 4987 4988 4989 4990 4991
	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 已提交
4992

J
Jeff Layton 已提交
4993 4994 4995 4996 4997
		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);
4998

4999
	kfree(cifs_sb->mountdata);
5000
	kfree(cifs_sb->prepath);
5001
#ifdef CONFIG_CIFS_DFS_UPCALL
5002
	dfs_cache_del_vol(cifs_sb->origin_fullpath);
5003 5004
	kfree(cifs_sb->origin_fullpath);
#endif
5005
	call_rcu(&cifs_sb->rcu, delayed_free);
5006
}
L
Linus Torvalds 已提交
5007

5008 5009
int
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
L
Linus Torvalds 已提交
5010 5011
{
	int rc = 0;
5012
	struct TCP_Server_Info *server = cifs_ses_server(ses);
L
Linus Torvalds 已提交
5013

5014 5015 5016
	if (!server->ops->need_neg || !server->ops->negotiate)
		return -ENOSYS;

5017
	/* only send once per connect */
5018
	if (!server->ops->need_neg(server))
5019 5020
		return 0;

5021
	rc = server->ops->negotiate(xid, ses);
5022 5023
	if (rc == 0) {
		spin_lock(&GlobalMid_Lock);
5024
		if (server->tcpStatus == CifsNeedNegotiate)
5025 5026 5027 5028 5029 5030 5031 5032 5033
			server->tcpStatus = CifsGood;
		else
			rc = -EHOSTDOWN;
		spin_unlock(&GlobalMid_Lock);
	}

	return rc;
}

5034 5035 5036
int
cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
		   struct nls_table *nls_info)
5037
{
5038
	int rc = -ENOSYS;
5039
	struct TCP_Server_Info *server = cifs_ses_server(ses);
5040

5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053
	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;
		}
	}
5054

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

5058 5059 5060
	if (server->ops->sess_setup)
		rc = server->ops->sess_setup(xid, ses, nls_info);

5061
	if (rc)
5062
		cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
5063

L
Linus Torvalds 已提交
5064 5065 5066
	return rc;
}

5067 5068 5069
static int
cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
{
5070 5071 5072 5073
	vol->sectype = ses->sectype;

	/* krb5 is special, since we don't need username or pw */
	if (vol->sectype == Kerberos)
5074 5075 5076 5077 5078
		return 0;

	return cifs_set_cifscreds(vol, ses);
}

5079
static struct cifs_tcon *
5080
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
5081
{
5082
	int rc;
5083 5084 5085
	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
	struct cifs_ses *ses;
	struct cifs_tcon *tcon = NULL;
5086 5087 5088
	struct smb_vol *vol_info;

	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
5089 5090
	if (vol_info == NULL)
		return ERR_PTR(-ENOMEM);
5091 5092 5093 5094 5095 5096 5097

	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 已提交
5098
	vol_info->nohandlecache = master_tcon->nohandlecache;
5099
	vol_info->local_lease = master_tcon->local_lease;
5100
	vol_info->no_lease = master_tcon->no_lease;
5101 5102
	vol_info->resilient = master_tcon->use_resilient;
	vol_info->persistent = master_tcon->use_persistent;
5103
	vol_info->handle_timeout = master_tcon->handle_timeout;
5104
	vol_info->no_linux_ext = !master_tcon->unix_ext;
5105
	vol_info->linux_ext = master_tcon->posix_extensions;
5106 5107
	vol_info->sectype = master_tcon->ses->sectype;
	vol_info->sign = master_tcon->ses->sign;
5108
	vol_info->seal = master_tcon->seal;
5109

5110 5111 5112 5113 5114
	rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
	if (rc) {
		tcon = ERR_PTR(rc);
		goto out;
	}
5115 5116

	/* get a reference for the same TCP session */
5117
	spin_lock(&cifs_tcp_ses_lock);
5118
	++master_tcon->ses->server->srv_count;
5119
	spin_unlock(&cifs_tcp_ses_lock);
5120 5121 5122

	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
	if (IS_ERR(ses)) {
5123
		tcon = (struct cifs_tcon *)ses;
5124
		cifs_put_tcp_session(master_tcon->ses->server, 0);
5125 5126 5127 5128 5129 5130 5131 5132 5133
		goto out;
	}

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

5134
	if (cap_unix(ses))
5135
		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
5136

5137
out:
5138
	kfree(vol_info->username);
5139
	kfree_sensitive(vol_info->password);
5140 5141 5142 5143 5144
	kfree(vol_info);

	return tcon;
}

5145
struct cifs_tcon *
5146 5147 5148 5149 5150
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{
	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
}

J
Jeff Layton 已提交
5151 5152
/* find and return a tlink with given uid */
static struct tcon_link *
5153
tlink_rb_search(struct rb_root *root, kuid_t uid)
J
Jeff Layton 已提交
5154 5155 5156 5157 5158 5159 5160
{
	struct rb_node *node = root->rb_node;
	struct tcon_link *tlink;

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

5161
		if (uid_gt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
5162
			node = node->rb_left;
5163
		else if (uid_lt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181
			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;

5182
		if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
J
Jeff Layton 已提交
5183 5184 5185 5186 5187 5188 5189 5190 5191
			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);
}

5192 5193 5194 5195 5196 5197 5198
/*
 * 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.
 *
5199
 * First, search the rbtree for an existing tcon for this fsuid. If one
5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211
 * 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;
5212
	kuid_t fsuid = current_fsuid();
5213 5214 5215 5216 5217 5218
	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 已提交
5219
	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5220 5221 5222 5223 5224 5225 5226 5227
	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 已提交
5228
		newtlink->tl_uid = fsuid;
5229 5230 5231 5232 5233 5234 5235
		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 已提交
5236
		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5237 5238 5239 5240 5241 5242 5243
		if (tlink) {
			cifs_get_tlink(tlink);
			spin_unlock(&cifs_sb->tlink_tree_lock);
			kfree(newtlink);
			goto wait_for_construction;
		}
		tlink = newtlink;
J
Jeff Layton 已提交
5244 5245
		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
		spin_unlock(&cifs_sb->tlink_tree_lock);
5246 5247 5248 5249 5250 5251
	} else {
wait_for_construction:
		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
				  TASK_INTERRUPTIBLE);
		if (ret) {
			cifs_put_tlink(tlink);
5252
			return ERR_PTR(-ERESTARTSYS);
5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279
		}

		/* 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;
}
5280 5281 5282 5283 5284 5285 5286 5287 5288 5289

/*
 * 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 已提交
5290
	struct rb_root *root = &cifs_sb->tlink_tree;
5291
	struct rb_node *node;
J
Jeff Layton 已提交
5292 5293
	struct rb_node *tmp;
	struct tcon_link *tlink;
5294

J
Jeff Layton 已提交
5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312
	/*
	 * 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;
5313

J
Jeff Layton 已提交
5314 5315 5316 5317 5318 5319 5320 5321 5322
		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);
5323

J
Jeff Layton 已提交
5324
	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
5325 5326
				TLINK_IDLE_EXPIRE);
}
5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340

#ifdef CONFIG_CIFS_DFS_UPCALL
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	int rc;
	struct TCP_Server_Info *server = tcon->ses->server;
	const struct smb_version_operations *ops = server->ops;
	struct dfs_cache_tgt_list tl;
	struct dfs_cache_tgt_iterator *it = NULL;
	char *tree;
	const char *tcp_host;
	size_t tcp_host_len;
	const char *dfs_host;
	size_t dfs_host_len;
5341
	char *share = NULL, *prefix = NULL;
5342 5343
	struct dfs_info3_param ref = {0};
	bool isroot;
5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358

	tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
	if (!tree)
		return -ENOMEM;

	if (!tcon->dfs_path) {
		if (tcon->ipc) {
			scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
		} else {
			rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
		}
		goto out;
	}

5359
	rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl);
5360 5361
	if (rc)
		goto out;
5362 5363
	isroot = ref.server_type == DFS_TYPE_ROOT;
	free_dfs_info_param(&ref);
5364 5365 5366 5367 5368 5369

	extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);

	for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) {
		bool target_match;

5370 5371
		kfree(share);
		kfree(prefix);
5372 5373
		share = NULL;
		prefix = NULL;
5374 5375

		rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix);
5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401
		if (rc) {
			cifs_dbg(VFS, "%s: failed to parse target share %d\n",
				 __func__, rc);
			continue;
		}

		extract_unc_hostname(share, &dfs_host, &dfs_host_len);

		if (dfs_host_len != tcp_host_len
		    || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
			cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
				 dfs_host, (int)tcp_host_len, tcp_host);

			rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match);
			if (rc) {
				cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
				break;
			}

			if (!target_match) {
				cifs_dbg(FYI, "%s: skipping target\n", __func__);
				continue;
			}
		}

		if (tcon->ipc) {
5402
			scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share);
5403 5404
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
		} else {
5405
			scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
5406
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5407 5408
			/* Only handle prefix paths of DFS link targets */
			if (!rc && !isroot) {
5409
				rc = update_super_prepath(tcon, prefix);
5410 5411 5412 5413 5414 5415 5416
				break;
			}
		}
		if (rc == -EREMOTE)
			break;
	}

5417 5418 5419
	kfree(share);
	kfree(prefix);

5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438
	if (!rc) {
		if (it)
			rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it);
		else
			rc = -ENOENT;
	}
	dfs_cache_free_tgts(&tl);
out:
	kfree(tree);
	return rc;
}
#else
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	const struct smb_version_operations *ops = tcon->ses->server->ops;

	return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
}
#endif