blob: d82467cfb0e2df5ef7e655bc601f4f17f3b890b1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve French1080ef72011-02-24 18:07:19 +00004 * Copyright (C) International Business Machines Corp., 2002,2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010024#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/list.h>
26#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/pagemap.h>
29#include <linux/ctype.h>
30#include <linux/utsname.h>
31#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070032#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070033#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000034#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070035#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080036#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040037#include <linux/namei.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080038#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040040#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040041#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050042#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000043#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040044#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060045#include <linux/bvec.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040046
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include "cifspdu.h"
48#include "cifsglob.h"
49#include "cifsproto.h"
50#include "cifs_unicode.h"
51#include "cifs_debug.h"
52#include "cifs_fs_sb.h"
53#include "ntlmssp.h"
54#include "nterr.h"
55#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053056#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070057#ifdef CONFIG_CIFS_SMB2
58#include "smb2proto.h"
59#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61#define CIFS_PORT 445
62#define RFC1001_PORT 139
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064extern mempool_t *cifs_req_poolp;
65
Jeff Layton2de970f2010-10-06 19:51:12 -040066/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040067#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040068#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040069
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040070enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040071 /* Mount options that take no arguments */
72 Opt_user_xattr, Opt_nouser_xattr,
73 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040074 Opt_forcegid, Opt_noforcegid,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040075 Opt_noblocksend, Opt_noautotune,
76 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050077 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040078 Opt_mapchars, Opt_nomapchars, Opt_sfu,
79 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
80 Opt_noposixpaths, Opt_nounix,
81 Opt_nocase,
82 Opt_brl, Opt_nobrl,
Steve French95932652016-09-23 01:36:34 -050083 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040084 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
85 Opt_nohard, Opt_nosoft,
86 Opt_nointr, Opt_intr,
87 Opt_nostrictsync, Opt_strictsync,
88 Opt_serverino, Opt_noserverino,
89 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
90 Opt_acl, Opt_noacl, Opt_locallease,
Jeff Layton1b359202012-09-19 15:20:27 -070091 Opt_sign, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040092 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040093 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050094 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060095 Opt_resilient, Opt_noresilient,
Germano Percossi39566442016-12-15 12:31:18 +053096 Opt_domainauto,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040097
98 /* Mount options which take numeric value */
99 Opt_backupuid, Opt_backupgid, Opt_uid,
100 Opt_cruid, Opt_gid, Opt_file_mode,
101 Opt_dirmode, Opt_port,
102 Opt_rsize, Opt_wsize, Opt_actimeo,
Steve French141891f2016-09-23 00:44:16 -0500103 Opt_echo_interval, Opt_max_credits,
Steve French8b217fe2016-11-11 22:36:20 -0600104 Opt_snapshot,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400105
106 /* Mount options which take string value */
107 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400108 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400109 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400110 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400111
112 /* Mount options to be ignored */
113 Opt_ignore,
114
115 /* Options which could be blank */
116 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100117 Opt_blank_user,
118 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400119
120 Opt_err
121};
122
123static const match_table_t cifs_mount_option_tokens = {
124
125 { Opt_user_xattr, "user_xattr" },
126 { Opt_nouser_xattr, "nouser_xattr" },
127 { Opt_forceuid, "forceuid" },
128 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400129 { Opt_forcegid, "forcegid" },
130 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400131 { Opt_noblocksend, "noblocksend" },
132 { Opt_noautotune, "noautotune" },
133 { Opt_hard, "hard" },
134 { Opt_soft, "soft" },
135 { Opt_perm, "perm" },
136 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500137 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400138 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500139 { Opt_mapposix, "mapposix" }, /* SFM style */
140 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400141 { Opt_sfu, "sfu" },
142 { Opt_nosfu, "nosfu" },
143 { Opt_nodfs, "nodfs" },
144 { Opt_posixpaths, "posixpaths" },
145 { Opt_noposixpaths, "noposixpaths" },
146 { Opt_nounix, "nounix" },
147 { Opt_nounix, "nolinux" },
148 { Opt_nocase, "nocase" },
149 { Opt_nocase, "ignorecase" },
150 { Opt_brl, "brl" },
151 { Opt_nobrl, "nobrl" },
152 { Opt_nobrl, "nolock" },
153 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400154 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400155 { Opt_setuids, "setuids" },
156 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500157 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400158 { Opt_dynperm, "dynperm" },
159 { Opt_nodynperm, "nodynperm" },
160 { Opt_nohard, "nohard" },
161 { Opt_nosoft, "nosoft" },
162 { Opt_nointr, "nointr" },
163 { Opt_intr, "intr" },
164 { Opt_nostrictsync, "nostrictsync" },
165 { Opt_strictsync, "strictsync" },
166 { Opt_serverino, "serverino" },
167 { Opt_noserverino, "noserverino" },
168 { Opt_rwpidforward, "rwpidforward" },
169 { Opt_cifsacl, "cifsacl" },
170 { Opt_nocifsacl, "nocifsacl" },
171 { Opt_acl, "acl" },
172 { Opt_noacl, "noacl" },
173 { Opt_locallease, "locallease" },
174 { Opt_sign, "sign" },
175 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400176 { Opt_noac, "noac" },
177 { Opt_fsc, "fsc" },
178 { Opt_mfsymlinks, "mfsymlinks" },
179 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400180 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400181 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500182 { Opt_persistent, "persistenthandles"},
183 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600184 { Opt_resilient, "resilienthandles"},
185 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530186 { Opt_domainauto, "domainauto"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400187
188 { Opt_backupuid, "backupuid=%s" },
189 { Opt_backupgid, "backupgid=%s" },
190 { Opt_uid, "uid=%s" },
191 { Opt_cruid, "cruid=%s" },
192 { Opt_gid, "gid=%s" },
193 { Opt_file_mode, "file_mode=%s" },
194 { Opt_dirmode, "dirmode=%s" },
195 { Opt_dirmode, "dir_mode=%s" },
196 { Opt_port, "port=%s" },
197 { Opt_rsize, "rsize=%s" },
198 { Opt_wsize, "wsize=%s" },
199 { Opt_actimeo, "actimeo=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600200 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500201 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600202 { Opt_snapshot, "snapshot=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400203
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100204 { Opt_blank_user, "user=" },
205 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400206 { Opt_user, "user=%s" },
207 { Opt_user, "username=%s" },
208 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100209 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400210 { Opt_pass, "pass=%s" },
211 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100212 { Opt_blank_ip, "ip=" },
213 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400214 { Opt_ip, "ip=%s" },
215 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400216 { Opt_ignore, "unc=%s" },
217 { Opt_ignore, "target=%s" },
218 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400219 { Opt_domain, "dom=%s" },
220 { Opt_domain, "domain=%s" },
221 { Opt_domain, "workgroup=%s" },
222 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400223 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400224 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400225 { Opt_netbiosname, "netbiosname=%s" },
226 { Opt_servern, "servern=%s" },
227 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400228 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400229 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400230 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400231
232 { Opt_ignore, "cred" },
233 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400234 { Opt_ignore, "cred=%s" },
235 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400236 { Opt_ignore, "guest" },
237 { Opt_ignore, "rw" },
238 { Opt_ignore, "ro" },
239 { Opt_ignore, "suid" },
240 { Opt_ignore, "nosuid" },
241 { Opt_ignore, "exec" },
242 { Opt_ignore, "noexec" },
243 { Opt_ignore, "nodev" },
244 { Opt_ignore, "noauto" },
245 { Opt_ignore, "dev" },
246 { Opt_ignore, "mand" },
247 { Opt_ignore, "nomand" },
248 { Opt_ignore, "_netdev" },
249
250 { Opt_err, NULL }
251};
252
253enum {
254 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
255 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400256 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
257 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400258 Opt_sec_none,
259
260 Opt_sec_err
261};
262
263static const match_table_t cifs_secflavor_tokens = {
264 { Opt_sec_krb5, "krb5" },
265 { Opt_sec_krb5i, "krb5i" },
266 { Opt_sec_krb5p, "krb5p" },
267 { Opt_sec_ntlmsspi, "ntlmsspi" },
268 { Opt_sec_ntlmssp, "ntlmssp" },
269 { Opt_ntlm, "ntlm" },
270 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400271 { Opt_sec_ntlmv2, "nontlm" },
272 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400273 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400274 { Opt_sec_lanman, "lanman" },
275 { Opt_sec_none, "none" },
276
277 { Opt_sec_err, NULL }
278};
279
Jeff Layton15b6a472012-05-16 07:50:15 -0400280/* cache flavors */
281enum {
282 Opt_cache_loose,
283 Opt_cache_strict,
284 Opt_cache_none,
285 Opt_cache_err
286};
287
288static const match_table_t cifs_cacheflavor_tokens = {
289 { Opt_cache_loose, "loose" },
290 { Opt_cache_strict, "strict" },
291 { Opt_cache_none, "none" },
292 { Opt_cache_err, NULL }
293};
294
Jeff Layton23db65f2012-05-15 12:20:51 -0400295static const match_table_t cifs_smb_version_tokens = {
296 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600297 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000298 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500299 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500300 { Smb_302, SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600301#ifdef CONFIG_CIFS_SMB311
302 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500303 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600304#endif /* SMB311 */
305 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400306};
307
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300308static int ip_connect(struct TCP_Server_Info *server);
309static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400310static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400311static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400312static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
313 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
Jeff Laytond5c56052008-12-01 18:42:33 -0500315/*
316 * cifs tcp session reconnection
317 *
318 * mark tcp session as reconnecting so temporarily locked
319 * mark all smb sessions as reconnecting for tcp session
320 * reconnect tcp session
321 * wake up waiters on reconnection? - (not needed currently)
322 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400323int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324cifs_reconnect(struct TCP_Server_Info *server)
325{
326 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500327 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000328 struct cifs_ses *ses;
329 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000330 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400331 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000334 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000335 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 next time through the loop */
337 spin_unlock(&GlobalMid_Lock);
338 return rc;
339 } else
340 server->tcpStatus = CifsNeedReconnect;
341 spin_unlock(&GlobalMid_Lock);
342 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400343#ifdef CONFIG_CIFS_SMB2
344 server->max_read = 0;
345#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Joe Perchesf96637b2013-05-04 22:12:25 -0500347 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349 /* before reconnecting the tcp session, mark the smb session (uid)
350 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500351 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
352 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530353 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500354 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000355 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500356 ses->need_reconnect = true;
357 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500358 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000359 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500360 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530363 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500364
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500366 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500367 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000368 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500369 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
370 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800371 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500372 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
373 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 sock_release(server->ssocket);
375 server->ssocket = NULL;
376 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500377 server->sequence_number = 0;
378 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500379 kfree(server->session_key.response);
380 server->session_key.response = NULL;
381 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000382 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500384 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400385 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500386 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500388 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
389 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400390 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
391 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400392 list_move(&mid_entry->qhead, &retry_list);
393 }
394 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100395 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400396
Joe Perchesf96637b2013-05-04 22:12:25 -0500397 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400398 list_for_each_safe(tmp, tmp2, &retry_list) {
399 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500400 list_del_init(&mid_entry->qhead);
401 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400404 do {
Steve French6c3d8902006-07-31 22:46:20 +0000405 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300406
407 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400408 mutex_lock(&server->srv_mutex);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300409 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000410 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500411 cifs_dbg(FYI, "reconnect error %d\n", rc);
Federico Sauter4afe2602015-03-17 17:45:28 +0100412 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700413 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 } else {
415 atomic_inc(&tcpSesReconnectCount);
416 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000417 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000418 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000419 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100420 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400422 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500423
Sachin Prabhub8c60012016-10-20 19:52:24 -0400424 if (server->tcpStatus == CifsNeedNegotiate)
425 mod_delayed_work(cifsiod_wq, &server->echo, 0);
426
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 return rc;
428}
429
Jeff Laytonc74093b2011-01-11 07:24:23 -0500430static void
431cifs_echo_request(struct work_struct *work)
432{
433 int rc;
434 struct TCP_Server_Info *server = container_of(work,
435 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400436 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500437
Jeff Layton247ec9b2011-02-04 17:09:50 -0500438 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400439 * If we need to renegotiate, set echo interval to zero to
440 * immediately call echo service where we can renegotiate.
441 */
442 if (server->tcpStatus == CifsNeedNegotiate)
443 echo_interval = 0;
444 else
445 echo_interval = server->echo_interval;
446
447 /*
448 * We cannot send an echo if it is disabled.
449 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500450 */
Steve French4fcd1812016-06-22 20:12:05 -0500451
452 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400453 server->tcpStatus == CifsExiting ||
454 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400455 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600456 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500457 goto requeue_echo;
458
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400459 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500460 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500461 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
462 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500463
464requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400465 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500466}
467
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400468static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400469allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400470{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400471 if (!server->bigbuf) {
472 server->bigbuf = (char *)cifs_buf_get();
473 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500474 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400475 msleep(3000);
476 /* retry will check if exiting */
477 return false;
478 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400479 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400480 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400481 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400482 }
483
Jeff Layton2a37ef92011-10-19 15:29:23 -0400484 if (!server->smallbuf) {
485 server->smallbuf = (char *)cifs_small_buf_get();
486 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500487 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400488 msleep(1000);
489 /* retry will check if exiting */
490 return false;
491 }
492 /* beginning of smb buffer is cleared in our buf_get */
493 } else {
494 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400495 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400496 }
497
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400498 return true;
499}
500
Jeff Laytonba749e62011-10-11 06:41:32 -0400501static bool
502server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400503{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300504 /*
505 * We need to wait 2 echo intervals to make sure we handle such
506 * situations right:
507 * 1s client sends a normal SMB request
508 * 2s client gets a response
509 * 30s echo workqueue job pops, and decides we got a response recently
510 * and don't need to send another
511 * ...
512 * 65s kernel_recvmsg times out, and we see that we haven't gotten
513 * a response in >60s.
514 */
515 if (server->tcpStatus == CifsGood &&
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600516 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
517 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
518 server->hostname, (2 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400519 cifs_reconnect(server);
520 wake_up(&server->response_q);
521 return true;
522 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400523
Jeff Laytonba749e62011-10-11 06:41:32 -0400524 return false;
525}
526
Al Viro71335662016-01-09 19:54:50 -0500527static int
528cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400529{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400530 int length = 0;
531 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400532
Al Viro71335662016-01-09 19:54:50 -0500533 smb_msg->msg_control = NULL;
534 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400535
Al Viro71335662016-01-09 19:54:50 -0500536 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500537 try_to_freeze();
538
Al Viro71335662016-01-09 19:54:50 -0500539 if (server_unresponsive(server))
540 return -ECONNABORTED;
541
542 length = sock_recvmsg(server->ssocket, smb_msg, 0);
543
544 if (server->tcpStatus == CifsExiting)
545 return -ESHUTDOWN;
546
547 if (server->tcpStatus == CifsNeedReconnect) {
548 cifs_reconnect(server);
549 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400550 }
551
Al Viro71335662016-01-09 19:54:50 -0500552 if (length == -ERESTARTSYS ||
553 length == -EAGAIN ||
554 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400555 /*
556 * Minimum sleep to prevent looping, allowing socket
557 * to clear and app threads to set tcpStatus
558 * CifsNeedReconnect if server hung.
559 */
560 usleep_range(1000, 2000);
561 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400562 continue;
Al Viro71335662016-01-09 19:54:50 -0500563 }
564
565 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500566 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400567 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500568 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400569 }
570 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400571 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400572}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400573
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400574int
575cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
576 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400577{
Al Viro71335662016-01-09 19:54:50 -0500578 struct msghdr smb_msg;
579 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
580 iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400581
Al Viro71335662016-01-09 19:54:50 -0500582 return cifs_readv_from_socket(server, &smb_msg);
583}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400584
Al Viro71335662016-01-09 19:54:50 -0500585int
586cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
587 unsigned int to_read)
588{
589 struct msghdr smb_msg;
590 struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
591 iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
592 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400593}
594
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400595static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400596is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400597{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400598 /*
599 * The first byte big endian of the length field,
600 * is actually not part of the length but the type
601 * with the most common, zero, as regular data.
602 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400603 switch (type) {
604 case RFC1002_SESSION_MESSAGE:
605 /* Regular SMB response */
606 return true;
607 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500608 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400609 break;
610 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500611 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400612 break;
613 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400614 /*
615 * We get this from Windows 98 instead of an error on
616 * SMB negprot response.
617 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500618 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400619 /* give server a second to clean up */
620 msleep(1000);
621 /*
622 * Always try 445 first on reconnect since we get NACK
623 * on some if we ever connected to port 139 (the NACK
624 * is since we do not begin with RFC1001 session
625 * initialize frame).
626 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400627 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400628 cifs_reconnect(server);
629 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400630 break;
631 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500632 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400633 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400634 }
635
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400636 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400637}
638
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400639void
640dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400641{
642#ifdef CONFIG_CIFS_STATS2
643 mid->when_received = jiffies;
644#endif
645 spin_lock(&GlobalMid_Lock);
646 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400647 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400648 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400649 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400650 list_del_init(&mid->qhead);
651 spin_unlock(&GlobalMid_Lock);
652}
653
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400654static void
655handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400656 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400657{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400658 if (server->ops->check_trans2 &&
659 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400660 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400661 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400662 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400663 /* Was previous buf put in mpx struct for multi-rsp? */
664 if (!mid->multiRsp) {
665 /* smb buffer will be freed by user thread */
666 if (server->large_buf)
667 server->bigbuf = NULL;
668 else
669 server->smallbuf = NULL;
670 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400671 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400672}
673
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400674static void clean_demultiplex_info(struct TCP_Server_Info *server)
675{
676 int length;
677
678 /* take it off the list, if it's not already */
679 spin_lock(&cifs_tcp_ses_lock);
680 list_del_init(&server->tcp_ses_list);
681 spin_unlock(&cifs_tcp_ses_lock);
682
683 spin_lock(&GlobalMid_Lock);
684 server->tcpStatus = CifsExiting;
685 spin_unlock(&GlobalMid_Lock);
686 wake_up_all(&server->response_q);
687
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400688 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300689 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400690 if (server->credits <= 0)
691 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300692 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400693 /*
694 * Although there should not be any requests blocked on this queue it
695 * can not hurt to be paranoid and try to wake up requests that may
696 * haven been blocked when more than 50 at time were on the wire to the
697 * same server - they now will see the session is in exit state and get
698 * out of SendReceive.
699 */
700 wake_up_all(&server->request_q);
701 /* give those requests time to exit */
702 msleep(125);
703
704 if (server->ssocket) {
705 sock_release(server->ssocket);
706 server->ssocket = NULL;
707 }
708
709 if (!list_empty(&server->pending_mid_q)) {
710 struct list_head dispose_list;
711 struct mid_q_entry *mid_entry;
712 struct list_head *tmp, *tmp2;
713
714 INIT_LIST_HEAD(&dispose_list);
715 spin_lock(&GlobalMid_Lock);
716 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
717 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500718 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400719 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400720 list_move(&mid_entry->qhead, &dispose_list);
721 }
722 spin_unlock(&GlobalMid_Lock);
723
724 /* now walk dispose list and issue callbacks */
725 list_for_each_safe(tmp, tmp2, &dispose_list) {
726 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500727 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400728 list_del_init(&mid_entry->qhead);
729 mid_entry->callback(mid_entry);
730 }
731 /* 1/8th of sec is more than enough time for them to exit */
732 msleep(125);
733 }
734
735 if (!list_empty(&server->pending_mid_q)) {
736 /*
737 * mpx threads have not exited yet give them at least the smb
738 * send timeout time for long ops.
739 *
740 * Due to delays on oplock break requests, we need to wait at
741 * least 45 seconds before giving up on a request getting a
742 * response and going ahead and killing cifsd.
743 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500744 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400745 msleep(46000);
746 /*
747 * If threads still have not exited they are probably never
748 * coming home not much else we can do but free the memory.
749 */
750 }
751
752 kfree(server->hostname);
753 kfree(server);
754
755 length = atomic_dec_return(&tcpSesAllocCount);
756 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700757 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400758}
759
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400760static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400761standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
762{
763 int length;
764 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400765 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400766
767 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400768 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500769 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400770 cifs_reconnect(server);
771 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400772 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400773 }
774
775 /* switch to large buffer if too big for a small one */
776 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
777 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400778 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400779 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400780 }
781
782 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400783 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
784 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400785 if (length < 0)
786 return length;
787 server->total_read += length;
788
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400789 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400790
Pavel Shilovsky4326ed22016-11-17 15:24:46 -0800791 return cifs_handle_standard(server, mid);
792}
793
794int
795cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
796{
797 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
798 int length;
799
Jeff Laytone9097ab2011-10-19 15:29:40 -0400800 /*
801 * We know that we received enough to get to the MID as we
802 * checked the pdu_length earlier. Now check to see
803 * if the rest of the header is OK. We borrow the length
804 * var for the rest of the loop to avoid a new stack var.
805 *
806 * 48 bytes is enough to display the header and a little bit
807 * into the payload for debugging purposes.
808 */
Steve French373512e2015-12-18 13:05:30 -0600809 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400810 if (length != 0)
811 cifs_dump_mem("Bad SMB: ", buf,
812 min_t(unsigned int, server->total_read, 48));
813
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700814 if (server->ops->is_status_pending &&
815 server->ops->is_status_pending(buf, server, length))
816 return -1;
817
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500818 if (!mid)
819 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400820
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400821 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500822 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400823}
824
825static int
Al Viro7c97c202011-06-21 08:51:28 -0400826cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
828 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400829 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400830 unsigned int pdu_length;
831 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500832 struct task_struct *task_to_wake = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500836 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400837
838 length = atomic_inc_return(&tcpSesAllocCount);
839 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700840 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700842 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000843 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700844 if (try_to_freeze())
845 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700846
Jeff Layton2a37ef92011-10-19 15:29:23 -0400847 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400848 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700849
Jeff Layton2a37ef92011-10-19 15:29:23 -0400850 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400851 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000852 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000853
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400854 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400855 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000856 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400857 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700858
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400859 /*
860 * The right amount was read from socket - 4 bytes,
861 * so we can now interpret the length field.
862 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400863 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700864
Joe Perchesf96637b2013-05-04 22:12:25 -0500865 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400866 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000867 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700868
Jeff Layton89482a52011-10-19 15:28:57 -0400869 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400870 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500871 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
872 pdu_length);
Jeff Layton89482a52011-10-19 15:28:57 -0400873 cifs_reconnect(server);
874 wake_up(&server->response_q);
875 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700876 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400877
Jeff Layton89482a52011-10-19 15:28:57 -0400878 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400879 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400880 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -0400881 if (length < 0)
882 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400883 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400884
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -0800885 if (server->ops->is_transform_hdr &&
886 server->ops->receive_transform &&
887 server->ops->is_transform_hdr(buf)) {
888 length = server->ops->receive_transform(server,
889 &mid_entry);
890 } else {
891 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400892
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -0800893 if (!mid_entry || !mid_entry->receive)
894 length = standard_receive3(server, mid_entry);
895 else
896 length = mid_entry->receive(server, mid_entry);
897 }
Jeff Layton44d22d82011-10-19 15:29:49 -0400898
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400899 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700900 continue;
901
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400902 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400903 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700904
Steve Frenchfda35942011-01-20 18:06:34 +0000905 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500906 if (mid_entry != NULL) {
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800907 if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
908 mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
909 server->ops->handle_cancelled_mid)
910 server->ops->handle_cancelled_mid(
911 mid_entry->resp_buf,
912 server);
913
Jeff Layton2a37ef92011-10-19 15:29:23 -0400914 if (!mid_entry->multiRsp || mid_entry->multiEnd)
915 mid_entry->callback(mid_entry);
Sachin Prabhu38bd4902017-03-03 15:41:38 -0800916 } else if (server->ops->is_oplock_break &&
917 server->ops->is_oplock_break(buf, server)) {
918 cifs_dbg(FYI, "Received oplock break\n");
919 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -0500920 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
921 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400922 cifs_dump_mem("Received Data is: ", buf,
923 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000924#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400925 if (server->ops->dump_detail)
926 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +0000927 cifs_dump_mids(server);
928#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000929
Steve Frenche4eb2952005-04-28 22:41:09 -0700930 }
931 } /* end while !EXITING */
932
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800933 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400934 cifs_buf_release(server->bigbuf);
935 if (server->smallbuf) /* no sense logging a debug message if NULL */
936 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500938 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400939 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500940
941 /* if server->tsk was NULL then wait for a signal before exiting */
942 if (!task_to_wake) {
943 set_current_state(TASK_INTERRUPTIBLE);
944 while (!signal_pending(current)) {
945 schedule();
946 set_current_state(TASK_INTERRUPTIBLE);
947 }
948 set_current_state(TASK_RUNNING);
949 }
950
Jeff Layton0468a2c2008-12-01 07:09:35 -0500951 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952}
953
Jeff Laytonc359cf32007-11-16 22:22:06 +0000954/* extract the host portion of the UNC string */
955static char *
956extract_hostname(const char *unc)
957{
958 const char *src;
959 char *dst, *delim;
960 unsigned int len;
961
962 /* skip double chars at beginning of string */
963 /* BB: check validity of these bytes? */
964 src = unc + 2;
965
966 /* delimiter between hostname and sharename is always '\\' now */
967 delim = strchr(src, '\\');
968 if (!delim)
969 return ERR_PTR(-EINVAL);
970
971 len = delim - src;
972 dst = kmalloc((len + 1), GFP_KERNEL);
973 if (dst == NULL)
974 return ERR_PTR(-ENOMEM);
975
976 memcpy(dst, src, len);
977 dst[len] = '\0';
978
979 return dst;
980}
981
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400982static int get_option_ul(substring_t args[], unsigned long *option)
983{
984 int rc;
985 char *string;
986
987 string = match_strdup(args);
988 if (string == NULL)
989 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +0100990 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400991 kfree(string);
992
993 return rc;
994}
995
Eric W. Biederman3da46562013-02-06 01:37:39 -0800996static int get_option_uid(substring_t args[], kuid_t *result)
997{
998 unsigned long value;
999 kuid_t uid;
1000 int rc;
1001
1002 rc = get_option_ul(args, &value);
1003 if (rc)
1004 return rc;
1005
1006 uid = make_kuid(current_user_ns(), value);
1007 if (!uid_valid(uid))
1008 return -EINVAL;
1009
1010 *result = uid;
1011 return 0;
1012}
1013
1014static int get_option_gid(substring_t args[], kgid_t *result)
1015{
1016 unsigned long value;
1017 kgid_t gid;
1018 int rc;
1019
1020 rc = get_option_ul(args, &value);
1021 if (rc)
1022 return rc;
1023
1024 gid = make_kgid(current_user_ns(), value);
1025 if (!gid_valid(gid))
1026 return -EINVAL;
1027
1028 *result = gid;
1029 return 0;
1030}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001031
1032static int cifs_parse_security_flavors(char *value,
1033 struct smb_vol *vol)
1034{
1035
1036 substring_t args[MAX_OPT_ARGS];
1037
Jeff Layton1e3cc572013-06-10 17:12:23 -05001038 /*
1039 * With mount options, the last one should win. Reset any existing
1040 * settings back to default.
1041 */
1042 vol->sectype = Unspecified;
1043 vol->sign = false;
1044
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001045 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001046 case Opt_sec_krb5p:
1047 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1048 return 1;
1049 case Opt_sec_krb5i:
1050 vol->sign = true;
1051 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001052 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001053 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001054 break;
1055 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001056 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001057 /* Fallthrough */
1058 case Opt_sec_ntlmssp:
1059 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001060 break;
1061 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001062 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001063 /* Fallthrough */
1064 case Opt_ntlm:
1065 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001066 break;
1067 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001068 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001069 /* Fallthrough */
1070 case Opt_sec_ntlmv2:
1071 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001072 break;
1073#ifdef CONFIG_CIFS_WEAK_PW_HASH
1074 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001075 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001076 break;
1077#endif
1078 case Opt_sec_none:
1079 vol->nullauth = 1;
1080 break;
1081 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001082 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001083 return 1;
1084 }
1085
1086 return 0;
1087}
1088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001090cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1091{
1092 substring_t args[MAX_OPT_ARGS];
1093
1094 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1095 case Opt_cache_loose:
1096 vol->direct_io = false;
1097 vol->strict_io = false;
1098 break;
1099 case Opt_cache_strict:
1100 vol->direct_io = false;
1101 vol->strict_io = true;
1102 break;
1103 case Opt_cache_none:
1104 vol->direct_io = true;
1105 vol->strict_io = false;
1106 break;
1107 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001108 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001109 return 1;
1110 }
1111 return 0;
1112}
1113
1114static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001115cifs_parse_smb_version(char *value, struct smb_vol *vol)
1116{
1117 substring_t args[MAX_OPT_ARGS];
1118
1119 switch (match_token(value, cifs_smb_version_tokens, args)) {
1120 case Smb_1:
1121 vol->ops = &smb1_operations;
1122 vol->vals = &smb1_values;
1123 break;
Steve French1080ef72011-02-24 18:07:19 +00001124#ifdef CONFIG_CIFS_SMB2
Steve Frenchdd446b12012-11-28 23:21:06 -06001125 case Smb_20:
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001126 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001127 vol->vals = &smb20_values;
1128 break;
Steve French1080ef72011-02-24 18:07:19 +00001129 case Smb_21:
1130 vol->ops = &smb21_operations;
1131 vol->vals = &smb21_values;
1132 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001133 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001134 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001135 vol->vals = &smb30_values;
1136 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001137 case Smb_302:
1138 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1139 vol->vals = &smb302_values;
1140 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001141#ifdef CONFIG_CIFS_SMB311
1142 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001143 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001144 vol->vals = &smb311_values;
1145 break;
1146#endif /* SMB311 */
Steve French1080ef72011-02-24 18:07:19 +00001147#endif
Jeff Layton23db65f2012-05-15 12:20:51 -04001148 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001149 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001150 return 1;
1151 }
1152 return 0;
1153}
1154
Jeff Laytond387a5c2012-12-10 06:10:46 -05001155/*
1156 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1157 * fields with the result. Returns 0 on success and an error otherwise.
1158 */
1159static int
1160cifs_parse_devname(const char *devname, struct smb_vol *vol)
1161{
1162 char *pos;
1163 const char *delims = "/\\";
1164 size_t len;
1165
1166 /* make sure we have a valid UNC double delimiter prefix */
1167 len = strspn(devname, delims);
1168 if (len != 2)
1169 return -EINVAL;
1170
1171 /* find delimiter between host and sharename */
1172 pos = strpbrk(devname + 2, delims);
1173 if (!pos)
1174 return -EINVAL;
1175
1176 /* skip past delimiter */
1177 ++pos;
1178
1179 /* now go until next delimiter or end of string */
1180 len = strcspn(pos, delims);
1181
1182 /* move "pos" up to delimiter or NULL */
1183 pos += len;
1184 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1185 if (!vol->UNC)
1186 return -ENOMEM;
1187
1188 convert_delimiter(vol->UNC, '\\');
1189
Sachin Prabhu11e31642016-02-08 13:44:01 +05301190 /* skip any delimiter */
1191 if (*pos == '/' || *pos == '\\')
1192 pos++;
1193
1194 /* If pos is NULL then no prepath */
1195 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001196 return 0;
1197
1198 vol->prepath = kstrdup(pos, GFP_KERNEL);
1199 if (!vol->prepath)
1200 return -ENOMEM;
1201
1202 return 0;
1203}
1204
Jeff Layton23db65f2012-05-15 12:20:51 -04001205static int
Sean Finneyb9468452011-04-11 13:19:32 +00001206cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001207 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001209 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001210 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 unsigned int temp_len, i, j;
1212 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001213 short int override_uid = -1;
1214 short int override_gid = -1;
1215 bool uid_specified = false;
1216 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001217 bool sloppy = false;
1218 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001219 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001220 char *string = NULL;
1221 char *tmp_end, *value;
1222 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001223 bool got_ip = false;
1224 unsigned short port = 0;
1225 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
1227 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001228 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001229 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Jeff Layton6ee95422012-11-26 11:09:57 -05001231 /* ensure we always start with zeroed-out smb_vol */
1232 memset(vol, 0, sizeof(*vol));
1233
Jeff Layton88463992010-11-22 15:31:03 -05001234 /*
1235 * does not have to be perfect mapping since field is
1236 * informational, only used for servers that do not support
1237 * port 445 and it can be overridden at mount time
1238 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001239 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1240 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001241 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1242
Jeff Layton1397f2e2011-01-07 11:30:28 -05001243 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001244 /* null target name indicates to use *SMBSERVR default called name
1245 if we end up sending RFC1001 session initialize */
1246 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001247 vol->cred_uid = current_uid();
1248 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001249 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001250
Steve French2baa2682014-09-27 02:19:01 -05001251 /*
1252 * default to SFM style remapping of seven reserved characters
1253 * unless user overrides it or we negotiate CIFS POSIX where
1254 * it is unnecessary. Can not simultaneously use more than one mapping
1255 * since then readdir could list files that open could not open
1256 */
1257 vol->remap = true;
1258
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001259 /* default to only allowing write access to owner of the mount */
1260 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001263 /* default is always to request posix paths. */
1264 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001265 /* default to using server inode numbers where available */
1266 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001267
Jeff Layton1b359202012-09-19 15:20:27 -07001268 /* default is to use strict cifs caching semantics */
1269 vol->strict_io = true;
1270
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301271 vol->actimeo = CIFS_DEF_ACTIMEO;
1272
Jeff Layton23db65f2012-05-15 12:20:51 -04001273 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1274 vol->ops = &smb1_operations;
1275 vol->vals = &smb1_values;
1276
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001277 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1278
Sean Finneyb9468452011-04-11 13:19:32 +00001279 if (!mountdata)
1280 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Sean Finneyb9468452011-04-11 13:19:32 +00001282 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1283 if (!mountdata_copy)
1284 goto cifs_parse_mount_err;
1285
1286 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001287 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001288
Steve French50c2f752007-07-13 00:33:32 +00001289 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001290 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 separator[0] = options[4];
1292 options += 5;
1293 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001294 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 }
1296 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001297 vol->backupuid_specified = false; /* no backup intent for a user */
1298 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001299
Jeff Layton37d4f992013-05-24 07:40:05 -04001300 switch (cifs_parse_devname(devname, vol)) {
1301 case 0:
1302 break;
1303 case -ENOMEM:
1304 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1305 goto cifs_parse_mount_err;
1306 case -EINVAL:
1307 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1308 goto cifs_parse_mount_err;
1309 default:
1310 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1311 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001312 }
1313
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001315 substring_t args[MAX_OPT_ARGS];
1316 unsigned long option;
1317 int token;
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 if (!*data)
1320 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001322 token = match_token(data, cifs_mount_option_tokens, args);
1323
1324 switch (token) {
1325
1326 /* Ingnore the following */
1327 case Opt_ignore:
1328 break;
1329
1330 /* Boolean values */
1331 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001333 break;
1334 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001336 break;
1337 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001338 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001339 break;
1340 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001341 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001342 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001343 case Opt_forcegid:
1344 override_gid = 1;
1345 break;
1346 case Opt_noforcegid:
1347 override_gid = 0;
1348 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001349 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001350 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001351 break;
1352 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001353 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001354 break;
1355 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001357 break;
1358 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001360 break;
1361 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001363 break;
1364 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001366 break;
1367 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001368 vol->sfu_remap = true;
1369 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001370 break;
1371 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001372 vol->sfu_remap = false;
1373 break;
1374 case Opt_mapposix:
1375 vol->remap = true;
1376 vol->sfu_remap = false; /* disable SFU mapping */
1377 break;
1378 case Opt_nomapposix:
1379 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
1381 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001382 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001385 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001388 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
1390 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001391 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 break;
1393 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001394 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001395 break;
1396 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001397 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001398 break;
1399 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001400 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001401 break;
1402 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001403 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001404 break;
1405 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001406 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001407 /*
1408 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001409 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001410 * local vfs will do advisory
1411 */
Steve French50c2f752007-07-13 00:33:32 +00001412 if (vol->file_mode ==
1413 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001414 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001417 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
Steve French95932652016-09-23 01:36:34 -05001425 case Opt_setuidfromacl:
1426 vol->setuidfromacl = 1;
1427 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001428 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001429 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001432 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001439 break;
1440 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
1443 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001447 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001450 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 break;
1452 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001454 break;
1455 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001457 break;
1458 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001459 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 break;
1461 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001462 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001463 break;
1464 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001465 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001466 break;
1467 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001469 break;
1470 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001472 break;
1473 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001474 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001475 break;
1476 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001477 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001478 break;
1479 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001480 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001481 * is a per tree connection (mount) not a per socket
1482 * or per-smb connection option in the protocol
1483 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1484 */
Steve French95b1cb92008-05-15 16:44:38 +00001485 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001486 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001487 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001488 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001489 break;
1490 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301491#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001492 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001493 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301494#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301495 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001496 break;
1497 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001498 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001499 break;
1500 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001501 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001502 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001503 case Opt_sloppy:
1504 sloppy = true;
1505 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001506 case Opt_nosharesock:
1507 vol->nosharesock = true;
1508 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001509 case Opt_nopersistent:
1510 vol->nopersistent = true;
1511 if (vol->persistent) {
1512 cifs_dbg(VFS,
1513 "persistenthandles mount options conflict\n");
1514 goto cifs_parse_mount_err;
1515 }
1516 break;
1517 case Opt_persistent:
1518 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001519 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001520 cifs_dbg(VFS,
1521 "persistenthandles mount options conflict\n");
1522 goto cifs_parse_mount_err;
1523 }
1524 break;
Steve French592fafe2015-11-03 10:08:53 -06001525 case Opt_resilient:
1526 vol->resilient = true;
1527 if (vol->persistent) {
1528 cifs_dbg(VFS,
1529 "persistenthandles mount options conflict\n");
1530 goto cifs_parse_mount_err;
1531 }
1532 break;
1533 case Opt_noresilient:
1534 vol->resilient = false; /* already the default */
1535 break;
Germano Percossi39566442016-12-15 12:31:18 +05301536 case Opt_domainauto:
1537 vol->domainauto = true;
1538 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001539
1540 /* Numeric Values */
1541 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001542 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001543 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1544 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001545 goto cifs_parse_mount_err;
1546 }
1547 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001548 break;
1549 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001550 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001551 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1552 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001553 goto cifs_parse_mount_err;
1554 }
1555 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001556 break;
1557 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001558 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001559 cifs_dbg(VFS, "%s: Invalid uid value\n",
1560 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001561 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001563 uid_specified = true;
1564 break;
1565 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001566 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001567 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1568 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001569 goto cifs_parse_mount_err;
1570 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001571 break;
1572 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001573 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001574 cifs_dbg(VFS, "%s: Invalid gid value\n",
1575 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001576 goto cifs_parse_mount_err;
1577 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001578 gid_specified = true;
1579 break;
1580 case Opt_file_mode:
1581 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001582 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1583 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001584 goto cifs_parse_mount_err;
1585 }
1586 vol->file_mode = option;
1587 break;
1588 case Opt_dirmode:
1589 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001590 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1591 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001592 goto cifs_parse_mount_err;
1593 }
1594 vol->dir_mode = option;
1595 break;
1596 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001597 if (get_option_ul(args, &option) ||
1598 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001599 cifs_dbg(VFS, "%s: Invalid port value\n",
1600 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001601 goto cifs_parse_mount_err;
1602 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001603 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001604 break;
1605 case Opt_rsize:
1606 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001607 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1608 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001609 goto cifs_parse_mount_err;
1610 }
1611 vol->rsize = option;
1612 break;
1613 case Opt_wsize:
1614 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001615 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1616 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001617 goto cifs_parse_mount_err;
1618 }
1619 vol->wsize = option;
1620 break;
1621 case Opt_actimeo:
1622 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001623 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1624 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001625 goto cifs_parse_mount_err;
1626 }
1627 vol->actimeo = HZ * option;
1628 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001629 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001630 goto cifs_parse_mount_err;
1631 }
1632 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001633 case Opt_echo_interval:
1634 if (get_option_ul(args, &option)) {
1635 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1636 __func__);
1637 goto cifs_parse_mount_err;
1638 }
1639 vol->echo_interval = option;
1640 break;
Steve French8b217fe2016-11-11 22:36:20 -06001641 case Opt_snapshot:
1642 if (get_option_ul(args, &option)) {
1643 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
1644 __func__);
1645 goto cifs_parse_mount_err;
1646 }
1647 vol->snapshot_time = option;
1648 break;
Steve French141891f2016-09-23 00:44:16 -05001649 case Opt_max_credits:
1650 if (get_option_ul(args, &option) || (option < 20) ||
1651 (option > 60000)) {
1652 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1653 __func__);
1654 goto cifs_parse_mount_err;
1655 }
1656 vol->max_credits = option;
1657 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001658
1659 /* String Arguments */
1660
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001661 case Opt_blank_user:
1662 /* null user, ie. anonymous authentication */
1663 vol->nullauth = 1;
1664 vol->username = NULL;
1665 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001666 case Opt_user:
1667 string = match_strdup(args);
1668 if (string == NULL)
1669 goto out_nomem;
1670
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001671 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1672 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001673 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001674 goto cifs_parse_mount_err;
1675 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001676
1677 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001678 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001679 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001680 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001681 break;
1682 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001683 /* passwords have to be handled differently
1684 * to allow the character used for deliminator
1685 * to be passed within them
1686 */
1687
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001688 /*
1689 * Check if this is a case where the password
1690 * starts with a delimiter
1691 */
1692 tmp_end = strchr(data, '=');
1693 tmp_end++;
1694 if (!(tmp_end < end && tmp_end[1] == delim)) {
1695 /* No it is not. Set the password to NULL */
Namjae Jeond6ccf492014-08-21 19:11:20 +09001696 kfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001697 vol->password = NULL;
1698 break;
1699 }
1700 /* Yes it is. Drop down to Opt_pass below.*/
1701 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001702 /* Obtain the value string */
1703 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001704 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001705
1706 /* Set tmp_end to end of the string */
1707 tmp_end = (char *) value + strlen(value);
1708
1709 /* Check if following character is the deliminator
1710 * If yes, we have encountered a double deliminator
1711 * reset the NULL character to the deliminator
1712 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301713 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001714 tmp_end[0] = delim;
1715
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301716 /* Keep iterating until we get to a single
1717 * deliminator OR the end
1718 */
1719 while ((tmp_end = strchr(tmp_end, delim))
1720 != NULL && (tmp_end[1] == delim)) {
1721 tmp_end = (char *) &tmp_end[2];
1722 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001723
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301724 /* Reset var options to point to next element */
1725 if (tmp_end) {
1726 tmp_end[0] = '\0';
1727 options = (char *) &tmp_end[1];
1728 } else
1729 /* Reached the end of the mount option
1730 * string */
1731 options = end;
1732 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733
Namjae Jeond6ccf492014-08-21 19:11:20 +09001734 kfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001735 /* Now build new password string */
1736 temp_len = strlen(value);
1737 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1738 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001739 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001740 goto cifs_parse_mount_err;
1741 }
1742
1743 for (i = 0, j = 0; i < temp_len; i++, j++) {
1744 vol->password[j] = value[i];
1745 if ((value[i] == delim) &&
1746 value[i+1] == delim)
1747 /* skip the second deliminator */
1748 i++;
1749 }
1750 vol->password[j] = '\0';
1751 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001752 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001753 /* FIXME: should this be an error instead? */
1754 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001755 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001756 case Opt_ip:
1757 string = match_strdup(args);
1758 if (string == NULL)
1759 goto out_nomem;
1760
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001761 if (!cifs_convert_address(dstaddr, string,
1762 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001763 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001764 goto cifs_parse_mount_err;
1765 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001766 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001767 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001768 case Opt_domain:
1769 string = match_strdup(args);
1770 if (string == NULL)
1771 goto out_nomem;
1772
Chen Gang057d6332013-07-19 09:01:36 +08001773 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
1774 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001775 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 goto cifs_parse_mount_err;
1777 }
1778
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001779 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001780 vol->domainname = kstrdup(string, GFP_KERNEL);
1781 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001782 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001783 goto cifs_parse_mount_err;
1784 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001785 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001786 break;
1787 case Opt_srcaddr:
1788 string = match_strdup(args);
1789 if (string == NULL)
1790 goto out_nomem;
1791
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001792 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001793 (struct sockaddr *)&vol->srcaddr,
1794 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001795 pr_warn("CIFS: Could not parse srcaddr: %s\n",
1796 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001797 goto cifs_parse_mount_err;
1798 }
1799 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001800 case Opt_iocharset:
1801 string = match_strdup(args);
1802 if (string == NULL)
1803 goto out_nomem;
1804
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001805 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001806 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001807 goto cifs_parse_mount_err;
1808 }
1809
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001810 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001811 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 vol->iocharset = kstrdup(string,
1813 GFP_KERNEL);
1814 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001815 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 goto cifs_parse_mount_err;
1817 }
1818 }
1819 /* if iocharset not set then load_nls_default
1820 * is used by caller
1821 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001822 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001823 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001824 case Opt_netbiosname:
1825 string = match_strdup(args);
1826 if (string == NULL)
1827 goto out_nomem;
1828
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001829 memset(vol->source_rfc1001_name, 0x20,
1830 RFC1001_NAME_LEN);
1831 /*
1832 * FIXME: are there cases in which a comma can
1833 * be valid in workstation netbios name (and
1834 * need special handling)?
1835 */
1836 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1837 /* don't ucase netbiosname for user */
1838 if (string[i] == 0)
1839 break;
1840 vol->source_rfc1001_name[i] = string[i];
1841 }
1842 /* The string has 16th byte zero still from
1843 * set at top of the function
1844 */
1845 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001846 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001847 break;
1848 case Opt_servern:
1849 /* servernetbiosname specified override *SMBSERVER */
1850 string = match_strdup(args);
1851 if (string == NULL)
1852 goto out_nomem;
1853
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001854 /* last byte, type, is 0x20 for servr type */
1855 memset(vol->target_rfc1001_name, 0x20,
1856 RFC1001_NAME_LEN_WITH_NULL);
1857
1858 /* BB are there cases in which a comma can be
1859 valid in this workstation netbios name
1860 (and need special handling)? */
1861
1862 /* user or mount helper must uppercase the
1863 netbios name */
1864 for (i = 0; i < 15; i++) {
1865 if (string[i] == 0)
1866 break;
1867 vol->target_rfc1001_name[i] = string[i];
1868 }
1869 /* The string has 16th byte zero still from
1870 set at top of the function */
1871 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001872 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001873 break;
1874 case Opt_ver:
1875 string = match_strdup(args);
1876 if (string == NULL)
1877 goto out_nomem;
1878
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001879 if (strncasecmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001880 /* This is the default */
1881 break;
1882 }
1883 /* For all other value, error */
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001884 pr_warn("CIFS: Invalid version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001885 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001886 case Opt_vers:
1887 string = match_strdup(args);
1888 if (string == NULL)
1889 goto out_nomem;
1890
1891 if (cifs_parse_smb_version(string, vol) != 0)
1892 goto cifs_parse_mount_err;
1893 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001894 case Opt_sec:
1895 string = match_strdup(args);
1896 if (string == NULL)
1897 goto out_nomem;
1898
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 if (cifs_parse_security_flavors(string, vol) != 0)
1900 goto cifs_parse_mount_err;
1901 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001902 case Opt_cache:
1903 string = match_strdup(args);
1904 if (string == NULL)
1905 goto out_nomem;
1906
1907 if (cifs_parse_cache_flavor(string, vol) != 0)
1908 goto cifs_parse_mount_err;
1909 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001910 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001911 /*
1912 * An option we don't recognize. Save it off for later
1913 * if we haven't already found one
1914 */
1915 if (!invalid)
1916 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001917 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001919 /* Free up any allocated string */
1920 kfree(string);
1921 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001923
Jeff Laytond8162552012-03-23 14:40:56 -04001924 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001925 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04001926 goto cifs_parse_mount_err;
1927 }
1928
Jeff Layton8a8798a2012-01-17 16:09:15 -05001929#ifndef CONFIG_KEYS
1930 /* Muliuser mounts require CONFIG_KEYS support */
1931 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001932 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001933 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001934 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001935#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001936 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04001937 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001938 goto cifs_parse_mount_err;
1939 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001940
Jeff Layton62a1a432012-12-10 06:10:45 -05001941 /* make sure UNC has a share name */
1942 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001943 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05001944 goto cifs_parse_mount_err;
1945 }
1946
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001947 if (!got_ip) {
1948 /* No ip= option specified? Try to get it from UNC */
1949 if (!cifs_convert_address(dstaddr, &vol->UNC[2],
1950 strlen(&vol->UNC[2]))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001951 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001952 goto cifs_parse_mount_err;
1953 }
1954 }
1955
1956 /* set the port that we got earlier */
1957 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001959 if (uid_specified)
1960 vol->override_uid = override_uid;
1961 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001962 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001963
1964 if (gid_specified)
1965 vol->override_gid = override_gid;
1966 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001967 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001968
Sean Finneyb9468452011-04-11 13:19:32 +00001969 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001971
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001972out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001973 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001974cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001975 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001976 kfree(mountdata_copy);
1977 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978}
1979
Ben Greear3eb9a882010-09-01 17:06:02 -07001980/** Returns true if srcaddr isn't specified and rhs isn't
1981 * specified, or if srcaddr is specified and
1982 * matches the IP address of the rhs argument.
1983 */
Jeff Layton45151482010-07-06 20:43:02 -04001984static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001985srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1986{
1987 switch (srcaddr->sa_family) {
1988 case AF_UNSPEC:
1989 return (rhs->sa_family == AF_UNSPEC);
1990 case AF_INET: {
1991 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1992 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1993 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1994 }
1995 case AF_INET6: {
1996 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05001997 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07001998 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1999 }
2000 default:
2001 WARN_ON(1);
2002 return false; /* don't expect to be here */
2003 }
2004}
2005
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002006/*
2007 * If no port is specified in addr structure, we try to match with 445 port
2008 * and if it fails - with 139 ports. It should be called only if address
2009 * families of server and addr are equal.
2010 */
2011static bool
2012match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2013{
Steve French6da97912011-03-13 18:55:55 +00002014 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002015
2016 switch (addr->sa_family) {
2017 case AF_INET:
2018 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2019 port = ((struct sockaddr_in *) addr)->sin_port;
2020 break;
2021 case AF_INET6:
2022 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2023 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2024 break;
2025 default:
2026 WARN_ON(1);
2027 return false;
2028 }
2029
2030 if (!port) {
2031 port = htons(CIFS_PORT);
2032 if (port == *sport)
2033 return true;
2034
2035 port = htons(RFC1001_PORT);
2036 }
2037
2038 return port == *sport;
2039}
Ben Greear3eb9a882010-09-01 17:06:02 -07002040
2041static bool
2042match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2043 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044{
Jeff Layton45151482010-07-06 20:43:02 -04002045 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002046 case AF_INET: {
2047 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2048 struct sockaddr_in *srv_addr4 =
2049 (struct sockaddr_in *)&server->dstaddr;
2050
2051 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002052 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002053 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002054 }
2055 case AF_INET6: {
2056 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2057 struct sockaddr_in6 *srv_addr6 =
2058 (struct sockaddr_in6 *)&server->dstaddr;
2059
Jeff Layton45151482010-07-06 20:43:02 -04002060 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002061 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002062 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002063 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002064 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002065 break;
2066 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002067 default:
2068 WARN_ON(1);
2069 return false; /* don't expect to be here */
2070 }
Jeff Layton45151482010-07-06 20:43:02 -04002071
Ben Greear3eb9a882010-09-01 17:06:02 -07002072 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2073 return false;
2074
Jeff Layton45151482010-07-06 20:43:02 -04002075 return true;
2076}
2077
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002078static bool
2079match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2080{
Jeff Layton3f618222013-06-12 19:52:14 -05002081 /*
2082 * The select_sectype function should either return the vol->sectype
2083 * that was specified, or "Unspecified" if that sectype was not
2084 * compatible with the given NEGOTIATE request.
2085 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302086 if (server->ops->select_sectype(server, vol->sectype)
2087 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002088 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002089
Jeff Layton3f618222013-06-12 19:52:14 -05002090 /*
2091 * Now check if signing mode is acceptable. No need to check
2092 * global_secflags at this point since if MUST_SIGN is set then
2093 * the server->sign had better be too.
2094 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002095 if (vol->sign && !server->sign)
2096 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002097
2098 return true;
2099}
2100
Jeff Layton9fa114f2012-11-26 11:09:57 -05002101static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002102{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002103 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2104
Jeff Laytona0b3df52013-05-24 07:40:59 -04002105 if (vol->nosharesock)
2106 return 0;
2107
Jeff Layton23db65f2012-05-15 12:20:51 -04002108 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2109 return 0;
2110
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002111 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2112 return 0;
2113
2114 if (!match_address(server, addr,
2115 (struct sockaddr *)&vol->srcaddr))
2116 return 0;
2117
2118 if (!match_port(server, addr))
2119 return 0;
2120
2121 if (!match_security(server, vol))
2122 return 0;
2123
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002124 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002125 return 0;
2126
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002127 return 1;
2128}
2129
Jeff Layton45151482010-07-06 20:43:02 -04002130static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002131cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002132{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002133 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302135 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002136 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002137 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002138 continue;
2139
Jeff Laytone7ddee92008-11-14 13:44:38 -05002140 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302141 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002142 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002143 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302145 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 return NULL;
2147}
2148
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002149void
2150cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002152 struct task_struct *task;
2153
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302154 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002155 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302156 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002157 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002159
Rob Landleyf1d0c992011-01-22 15:44:05 -06002160 put_net(cifs_net_ns(server));
2161
Jeff Laytone7ddee92008-11-14 13:44:38 -05002162 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302163 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002164
Jeff Laytonc74093b2011-01-11 07:24:23 -05002165 cancel_delayed_work_sync(&server->echo);
2166
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002167#ifdef CONFIG_CIFS_SMB2
2168 if (from_reconnect)
2169 /*
2170 * Avoid deadlock here: reconnect work calls
2171 * cifs_put_tcp_session() at its end. Need to be sure
2172 * that reconnect work does nothing with server pointer after
2173 * that step.
2174 */
2175 cancel_delayed_work(&server->reconnect);
2176 else
2177 cancel_delayed_work_sync(&server->reconnect);
2178#endif
2179
Jeff Laytone7ddee92008-11-14 13:44:38 -05002180 spin_lock(&GlobalMid_Lock);
2181 server->tcpStatus = CifsExiting;
2182 spin_unlock(&GlobalMid_Lock);
2183
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002184 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302185 cifs_fscache_release_client_cookie(server);
2186
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002187 kfree(server->session_key.response);
2188 server->session_key.response = NULL;
2189 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002190
2191 task = xchg(&server->tsk, NULL);
2192 if (task)
2193 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194}
2195
Jeff Layton63c038c2008-12-01 18:41:46 -05002196static struct TCP_Server_Info *
2197cifs_get_tcp_session(struct smb_vol *volume_info)
2198{
2199 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002200 int rc;
2201
Joe Perchesf96637b2013-05-04 22:12:25 -05002202 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002203
2204 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002205 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002206 if (tcp_ses)
2207 return tcp_ses;
2208
2209 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2210 if (!tcp_ses) {
2211 rc = -ENOMEM;
2212 goto out_err;
2213 }
2214
Jeff Layton23db65f2012-05-15 12:20:51 -04002215 tcp_ses->ops = volume_info->ops;
2216 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002217 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002218 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2219 if (IS_ERR(tcp_ses->hostname)) {
2220 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002221 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002222 }
2223
2224 tcp_ses->noblocksnd = volume_info->noblocksnd;
2225 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002226 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002227 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002228 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002229 init_waitqueue_head(&tcp_ses->response_q);
2230 init_waitqueue_head(&tcp_ses->request_q);
2231 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2232 mutex_init(&tcp_ses->srv_mutex);
2233 memcpy(tcp_ses->workstation_RFC1001_name,
2234 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2235 memcpy(tcp_ses->server_RFC1001_name,
2236 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002237 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002238 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002239 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002240 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002241 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2242 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002243 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002244#ifdef CONFIG_CIFS_SMB2
2245 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2246 mutex_init(&tcp_ses->reconnect_mutex);
2247#endif
Jeff Layton9fa114f2012-11-26 11:09:57 -05002248 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2249 sizeof(tcp_ses->srcaddr));
2250 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2251 sizeof(tcp_ses->dstaddr));
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002252#ifdef CONFIG_CIFS_SMB2
Steve Frenchfa70b872016-09-22 00:39:34 -05002253 generate_random_uuid(tcp_ses->client_guid);
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002254#endif
Jeff Layton63c038c2008-12-01 18:41:46 -05002255 /*
2256 * at this point we are the only ones with the pointer
2257 * to the struct since the kernel thread not created yet
2258 * no need to spinlock this init of tcpStatus or srv_count
2259 */
2260 tcp_ses->tcpStatus = CifsNew;
2261 ++tcp_ses->srv_count;
2262
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002263 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2264 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2265 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2266 else
2267 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
2268
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002269 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002270 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002271 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002272 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002273 }
2274
2275 /*
2276 * since we're in a cifs function already, we know that
2277 * this will succeed. No need for try_module_get().
2278 */
2279 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002280 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002281 tcp_ses, "cifsd");
2282 if (IS_ERR(tcp_ses->tsk)) {
2283 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002284 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002285 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002286 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002287 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002288 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002289
2290 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302291 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002292 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302293 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002294
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302295 cifs_fscache_get_client_cookie(tcp_ses);
2296
Jeff Laytonc74093b2011-01-11 07:24:23 -05002297 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002298 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002299
Jeff Layton63c038c2008-12-01 18:41:46 -05002300 return tcp_ses;
2301
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002302out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002303 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002304
Rob Landleyf1d0c992011-01-22 15:44:05 -06002305 put_net(cifs_net_ns(tcp_ses));
2306
Jeff Layton63c038c2008-12-01 18:41:46 -05002307out_err:
2308 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002309 if (!IS_ERR(tcp_ses->hostname))
2310 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002311 if (tcp_ses->ssocket)
2312 sock_release(tcp_ses->ssocket);
2313 kfree(tcp_ses);
2314 }
2315 return ERR_PTR(rc);
2316}
2317
Steve French96daf2b2011-05-27 04:34:02 +00002318static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002319{
Jeff Layton3f618222013-06-12 19:52:14 -05002320 if (vol->sectype != Unspecified &&
2321 vol->sectype != ses->sectype)
2322 return 0;
2323
2324 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002325 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002326 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002327 return 0;
2328 break;
2329 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002330 /* NULL username means anonymous session */
2331 if (ses->user_name == NULL) {
2332 if (!vol->nullauth)
2333 return 0;
2334 break;
2335 }
2336
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002337 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002338 if (strncmp(ses->user_name,
2339 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002340 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002341 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002342 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002343 ses->password != NULL &&
2344 strncmp(ses->password,
2345 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002346 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002347 return 0;
2348 }
2349 return 1;
2350}
2351
Steve French96daf2b2011-05-27 04:34:02 +00002352static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002353cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354{
Steve French96daf2b2011-05-27 04:34:02 +00002355 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302357 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002358 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002359 if (ses->status == CifsExiting)
2360 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002361 if (!match_session(ses, vol))
2362 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002363 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302364 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002365 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302367 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 return NULL;
2369}
2370
Jeff Layton14fbf502008-11-14 13:53:46 -05002371static void
Steve French96daf2b2011-05-27 04:34:02 +00002372cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002373{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002374 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002375 struct TCP_Server_Info *server = ses->server;
2376
Joe Perchesf96637b2013-05-04 22:12:25 -05002377 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002378
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302379 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002380 if (ses->status == CifsExiting) {
2381 spin_unlock(&cifs_tcp_ses_lock);
2382 return;
2383 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002384 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302385 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002386 return;
2387 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002388 if (ses->status == CifsGood)
2389 ses->status = CifsExiting;
2390 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002391
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002392 if (ses->status == CifsExiting && server->ops->logoff) {
2393 xid = get_xid();
2394 rc = server->ops->logoff(xid, ses);
2395 if (rc)
2396 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2397 __func__, rc);
2398 _free_xid(xid);
2399 }
2400
2401 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002402 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302403 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002404
Jeff Layton14fbf502008-11-14 13:53:46 -05002405 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002406 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05002407}
2408
Jeff Layton8a8798a2012-01-17 16:09:15 -05002409#ifdef CONFIG_KEYS
2410
Chen Gang057d6332013-07-19 09:01:36 +08002411/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2412#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002413
2414/* Populate username and pw fields from keyring if possible */
2415static int
2416cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2417{
2418 int rc = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002419 const char *delim, *payload;
2420 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002421 ssize_t len;
2422 struct key *key;
2423 struct TCP_Server_Info *server = ses->server;
2424 struct sockaddr_in *sa;
2425 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002426 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002427
2428 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2429 if (!desc)
2430 return -ENOMEM;
2431
2432 /* try to find an address key first */
2433 switch (server->dstaddr.ss_family) {
2434 case AF_INET:
2435 sa = (struct sockaddr_in *)&server->dstaddr;
2436 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2437 break;
2438 case AF_INET6:
2439 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2440 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2441 break;
2442 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002443 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2444 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002445 rc = -EINVAL;
2446 goto out_err;
2447 }
2448
Joe Perchesf96637b2013-05-04 22:12:25 -05002449 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002450 key = request_key(&key_type_logon, desc, "");
2451 if (IS_ERR(key)) {
2452 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002453 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002454 rc = PTR_ERR(key);
2455 goto out_err;
2456 }
2457
2458 /* didn't work, try to find a domain key */
2459 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002460 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002461 key = request_key(&key_type_logon, desc, "");
2462 if (IS_ERR(key)) {
2463 rc = PTR_ERR(key);
2464 goto out_err;
2465 }
2466 }
2467
2468 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00002469 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002470 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002471 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002472 goto out_key_put;
2473 }
2474
2475 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002476 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002477 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002478 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002479 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002480 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2481 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002482 rc = -EINVAL;
2483 goto out_key_put;
2484 }
2485
2486 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002487 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002488 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2489 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002490 rc = -EINVAL;
2491 goto out_key_put;
2492 }
2493
2494 vol->username = kstrndup(payload, len, GFP_KERNEL);
2495 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002496 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2497 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002498 rc = -ENOMEM;
2499 goto out_key_put;
2500 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002501 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002502
2503 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002504 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002505 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002506 rc = -EINVAL;
2507 kfree(vol->username);
2508 vol->username = NULL;
2509 goto out_key_put;
2510 }
2511
2512 ++delim;
2513 vol->password = kstrndup(delim, len, GFP_KERNEL);
2514 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002515 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2516 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002517 rc = -ENOMEM;
2518 kfree(vol->username);
2519 vol->username = NULL;
2520 goto out_key_put;
2521 }
2522
2523out_key_put:
2524 up_read(&key->sem);
2525 key_put(key);
2526out_err:
2527 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002528 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002529 return rc;
2530}
2531#else /* ! CONFIG_KEYS */
2532static inline int
2533cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2534 struct cifs_ses *ses __attribute__((unused)))
2535{
2536 return -ENOSYS;
2537}
2538#endif /* CONFIG_KEYS */
2539
Steve French96daf2b2011-05-27 04:34:02 +00002540static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002541cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2542{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002543 int rc = -ENOMEM;
2544 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002545 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002546 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2547 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002548
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002549 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002550
Jeff Layton4ff67b72010-07-06 20:43:02 -04002551 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002552 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002553 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2554 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002555
Jeff Layton36988c72010-04-24 07:57:43 -04002556 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002557 rc = cifs_negotiate_protocol(xid, ses);
2558 if (rc) {
2559 mutex_unlock(&ses->session_mutex);
2560 /* problem -- put our ses reference */
2561 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002562 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002563 return ERR_PTR(rc);
2564 }
Jeff Layton36988c72010-04-24 07:57:43 -04002565 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002566 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002567 rc = cifs_setup_session(xid, ses,
2568 volume_info->local_nls);
2569 if (rc) {
2570 mutex_unlock(&ses->session_mutex);
2571 /* problem -- put our reference */
2572 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002573 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002574 return ERR_PTR(rc);
2575 }
2576 }
2577 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002578
2579 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002580 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002581 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002582 return ses;
2583 }
2584
Joe Perchesf96637b2013-05-04 22:12:25 -05002585 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002586 ses = sesInfoAlloc();
2587 if (ses == NULL)
2588 goto get_ses_fail;
2589
2590 /* new SMB session uses our server ref */
2591 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002592 if (server->dstaddr.ss_family == AF_INET6)
2593 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002594 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002595 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002596
Steve French8727c8a2011-02-25 01:11:56 -06002597 if (volume_info->username) {
2598 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2599 if (!ses->user_name)
2600 goto get_ses_fail;
2601 }
Jeff Layton36988c72010-04-24 07:57:43 -04002602
2603 /* volume_info->password freed at unmount */
2604 if (volume_info->password) {
2605 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2606 if (!ses->password)
2607 goto get_ses_fail;
2608 }
2609 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002610 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2611 if (!ses->domainName)
2612 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002613 }
Germano Percossi39566442016-12-15 12:31:18 +05302614 if (volume_info->domainauto)
2615 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002616 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002617 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002618
Jeff Layton28e11bd2013-05-26 07:01:00 -04002619 ses->sectype = volume_info->sectype;
2620 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04002621
2622 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002623 rc = cifs_negotiate_protocol(xid, ses);
2624 if (!rc)
2625 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002626 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002627 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002628 goto get_ses_fail;
2629
2630 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302631 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002632 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302633 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002634
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002635 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002636 return ses;
2637
2638get_ses_fail:
2639 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002640 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002641 return ERR_PTR(rc);
2642}
2643
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002644static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002645{
2646 if (tcon->tidStatus == CifsExiting)
2647 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002648 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002649 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002650 if (tcon->seal != volume_info->seal)
2651 return 0;
2652#ifdef CONFIG_CIFS_SMB2
2653 if (tcon->snapshot_time != volume_info->snapshot_time)
2654 return 0;
2655#endif /* CONFIG_CIFS_SMB2 */
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002656 return 1;
2657}
2658
Steve French96daf2b2011-05-27 04:34:02 +00002659static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06002660cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661{
2662 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002663 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302665 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002666 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002667 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002668 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002669 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002670 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302671 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 return tcon;
2673 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302674 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 return NULL;
2676}
2677
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002678void
Steve French96daf2b2011-05-27 04:34:02 +00002679cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002680{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002681 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002682 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002683
Joe Perchesf96637b2013-05-04 22:12:25 -05002684 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302685 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002686 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302687 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002688 return;
2689 }
2690
2691 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302692 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002693
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002694 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002695 if (ses->server->ops->tree_disconnect)
2696 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002697 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002698
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302699 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002700 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002701 cifs_put_smb_ses(ses);
2702}
2703
Steve French96daf2b2011-05-27 04:34:02 +00002704static struct cifs_tcon *
2705cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002706{
2707 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002708 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002709
Steve French8b217fe2016-11-11 22:36:20 -06002710 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002711 if (tcon) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002712 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002713 /* existing tcon already has a reference */
2714 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002715 return tcon;
2716 }
2717
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002718 if (!ses->server->ops->tree_connect) {
2719 rc = -ENOSYS;
2720 goto out_fail;
2721 }
2722
Jeff Laytond00c28d2010-04-24 07:57:44 -04002723 tcon = tconInfoAlloc();
2724 if (tcon == NULL) {
2725 rc = -ENOMEM;
2726 goto out_fail;
2727 }
2728
Steve French8b217fe2016-11-11 22:36:20 -06002729 if (volume_info->snapshot_time) {
2730#ifdef CONFIG_CIFS_SMB2
2731 if (ses->server->vals->protocol_id == 0) {
2732 cifs_dbg(VFS,
2733 "Use SMB2 or later for snapshot mount option\n");
2734 rc = -EOPNOTSUPP;
2735 goto out_fail;
2736 } else
2737 tcon->snapshot_time = volume_info->snapshot_time;
2738#else
2739 cifs_dbg(VFS, "Snapshot mount option requires SMB2 support\n");
2740 rc = -EOPNOTSUPP;
2741 goto out_fail;
2742#endif /* CONFIG_CIFS_SMB2 */
2743 }
2744
Jeff Laytond00c28d2010-04-24 07:57:44 -04002745 tcon->ses = ses;
2746 if (volume_info->password) {
2747 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2748 if (!tcon->password) {
2749 rc = -ENOMEM;
2750 goto out_fail;
2751 }
2752 }
2753
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002754 /*
2755 * BB Do we need to wrap session_mutex around this TCon call and Unix
2756 * SetFS as we do on SessSetup and reconnect?
2757 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002758 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002759 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2760 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002761 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002762 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002763 if (rc)
2764 goto out_fail;
2765
2766 if (volume_info->nodfs) {
2767 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002768 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002769 }
Steve Frenchb618f002015-11-03 09:15:03 -06002770 tcon->use_persistent = false;
2771 /* check if SMB2 or later, CIFS does not support persistent handles */
2772 if (volume_info->persistent) {
2773 if (ses->server->vals->protocol_id == 0) {
2774 cifs_dbg(VFS,
2775 "SMB3 or later required for persistent handles\n");
2776 rc = -EOPNOTSUPP;
2777 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002778#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002779 } else if (ses->server->capabilities &
2780 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2781 tcon->use_persistent = true;
2782 else /* persistent handles requested but not supported */ {
2783 cifs_dbg(VFS,
2784 "Persistent handles not supported on share\n");
2785 rc = -EOPNOTSUPP;
2786 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002787#endif /* CONFIG_CIFS_SMB2 */
Steve Frenchb618f002015-11-03 09:15:03 -06002788 }
Steve French592fafe2015-11-03 10:08:53 -06002789#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002790 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
2791 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2792 && (volume_info->nopersistent == false)) {
2793 cifs_dbg(FYI, "enabling persistent handles\n");
2794 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06002795#endif /* CONFIG_CIFS_SMB2 */
2796 } else if (volume_info->resilient) {
2797 if (ses->server->vals->protocol_id == 0) {
2798 cifs_dbg(VFS,
2799 "SMB2.1 or later required for resilient handles\n");
2800 rc = -EOPNOTSUPP;
2801 goto out_fail;
2802 }
2803 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06002804 }
2805
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002806 if (volume_info->seal) {
2807 if (ses->server->vals->protocol_id == 0) {
2808 cifs_dbg(VFS,
2809 "SMB3 or later required for encryption\n");
2810 rc = -EOPNOTSUPP;
2811 goto out_fail;
2812#ifdef CONFIG_CIFS_SMB2
2813 } else if (tcon->ses->server->capabilities &
2814 SMB2_GLOBAL_CAP_ENCRYPTION)
2815 tcon->seal = true;
2816 else {
2817 cifs_dbg(VFS, "Encryption is not supported on share\n");
2818 rc = -EOPNOTSUPP;
2819 goto out_fail;
2820#endif /* CONFIG_CIFS_SMB2 */
2821 }
2822 }
2823
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002824 /*
2825 * We can have only one retry value for a connection to a share so for
2826 * resources mounted more than once to the same server share the last
2827 * value passed in for the retry flag is used.
2828 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04002829 tcon->retry = volume_info->retry;
2830 tcon->nocase = volume_info->nocase;
2831 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07002832 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002833
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302834 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002835 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302836 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002837
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302838 cifs_fscache_get_super_cookie(tcon);
2839
Jeff Laytond00c28d2010-04-24 07:57:44 -04002840 return tcon;
2841
2842out_fail:
2843 tconInfoFree(tcon);
2844 return ERR_PTR(rc);
2845}
2846
Jeff Layton9d002df2010-10-06 19:51:11 -04002847void
2848cifs_put_tlink(struct tcon_link *tlink)
2849{
2850 if (!tlink || IS_ERR(tlink))
2851 return;
2852
2853 if (!atomic_dec_and_test(&tlink->tl_count) ||
2854 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2855 tlink->tl_time = jiffies;
2856 return;
2857 }
2858
2859 if (!IS_ERR(tlink_tcon(tlink)))
2860 cifs_put_tcon(tlink_tcon(tlink));
2861 kfree(tlink);
2862 return;
2863}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002864
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002865static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002866cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2867{
2868 return cifs_sb->master_tlink;
2869}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002870
2871static int
2872compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2873{
2874 struct cifs_sb_info *old = CIFS_SB(sb);
2875 struct cifs_sb_info *new = mnt_data->cifs_sb;
2876
2877 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2878 return 0;
2879
2880 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2881 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2882 return 0;
2883
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002884 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002885 * We want to share sb only if we don't specify an r/wsize or
2886 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002887 */
2888 if (new->wsize && new->wsize < old->wsize)
2889 return 0;
2890
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002891 if (new->rsize && new->rsize < old->rsize)
2892 return 0;
2893
Eric W. Biederman1f682332013-02-06 01:20:20 -08002894 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002895 return 0;
2896
2897 if (old->mnt_file_mode != new->mnt_file_mode ||
2898 old->mnt_dir_mode != new->mnt_dir_mode)
2899 return 0;
2900
2901 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2902 return 0;
2903
2904 if (old->actimeo != new->actimeo)
2905 return 0;
2906
2907 return 1;
2908}
2909
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002910static int
2911match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2912{
2913 struct cifs_sb_info *old = CIFS_SB(sb);
2914 struct cifs_sb_info *new = mnt_data->cifs_sb;
2915
2916 if (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) {
2917 if (!(new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH))
2918 return 0;
2919 /* The prepath should be null terminated strings */
2920 if (strcmp(new->prepath, old->prepath))
2921 return 0;
2922
2923 return 1;
2924 }
2925 return 0;
2926}
2927
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002928int
2929cifs_match_super(struct super_block *sb, void *data)
2930{
2931 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2932 struct smb_vol *volume_info;
2933 struct cifs_sb_info *cifs_sb;
2934 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002935 struct cifs_ses *ses;
2936 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002937 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002938 int rc = 0;
2939
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002940 spin_lock(&cifs_tcp_ses_lock);
2941 cifs_sb = CIFS_SB(sb);
2942 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2943 if (IS_ERR(tlink)) {
2944 spin_unlock(&cifs_tcp_ses_lock);
2945 return rc;
2946 }
2947 tcon = tlink_tcon(tlink);
2948 ses = tcon->ses;
2949 tcp_srv = ses->server;
2950
2951 volume_info = mnt_data->vol;
2952
Jeff Layton9fa114f2012-11-26 11:09:57 -05002953 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002954 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08002955 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002956 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002957 rc = 0;
2958 goto out;
2959 }
2960
2961 rc = compare_mount_options(sb, mnt_data);
2962out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002963 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002964 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002965 return rc;
2966}
2967
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002969get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002970 const struct nls_table *nls_codepage, unsigned int *num_referrals,
2971 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972{
2973 char *temp_unc;
2974 int rc = 0;
2975
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002976 if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002977 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002979 *num_referrals = 0;
2980 *referrals = NULL;
2981
2982 if (ses->ipc_tid == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 temp_unc = kmalloc(2 /* for slashes */ +
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002984 strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
2985 + 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 if (temp_unc == NULL)
2987 return -ENOMEM;
2988 temp_unc[0] = '\\';
2989 temp_unc[1] = '\\';
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002990 strcpy(temp_unc + 2, ses->serverName);
2991 strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
2992 rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
2993 nls_codepage);
Joe Perchesf96637b2013-05-04 22:12:25 -05002994 cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 kfree(temp_unc);
2996 }
2997 if (rc == 0)
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002998 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
2999 referrals, num_referrals,
3000 nls_codepage, remap);
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003001 /*
3002 * BB - map targetUNCs to dfs_info3 structures, here or in
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003003 * ses->server->ops->get_dfs_refer.
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003004 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005
3006 return rc;
3007}
3008
Jeff Layton09e50d52008-07-23 10:11:19 -04003009#ifdef CONFIG_DEBUG_LOCK_ALLOC
3010static struct lock_class_key cifs_key[2];
3011static struct lock_class_key cifs_slock_key[2];
3012
3013static inline void
3014cifs_reclassify_socket4(struct socket *sock)
3015{
3016 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003017 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003018 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3019 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3020}
3021
3022static inline void
3023cifs_reclassify_socket6(struct socket *sock)
3024{
3025 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003026 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003027 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3028 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3029}
3030#else
3031static inline void
3032cifs_reclassify_socket4(struct socket *sock)
3033{
3034}
3035
3036static inline void
3037cifs_reclassify_socket6(struct socket *sock)
3038{
3039}
3040#endif
3041
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003043static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044{
Steve French50c2f752007-07-13 00:33:32 +00003045 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046
Steve French50c2f752007-07-13 00:33:32 +00003047 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 /* mask a nibble at a time and encode */
3049 target[j] = 'A' + (0x0F & (source[i] >> 4));
3050 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003051 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 }
3053
3054}
3055
Ben Greear3eb9a882010-09-01 17:06:02 -07003056static int
3057bind_socket(struct TCP_Server_Info *server)
3058{
3059 int rc = 0;
3060 if (server->srcaddr.ss_family != AF_UNSPEC) {
3061 /* Bind to the specified local IP address */
3062 struct socket *socket = server->ssocket;
3063 rc = socket->ops->bind(socket,
3064 (struct sockaddr *) &server->srcaddr,
3065 sizeof(server->srcaddr));
3066 if (rc < 0) {
3067 struct sockaddr_in *saddr4;
3068 struct sockaddr_in6 *saddr6;
3069 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3070 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3071 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05003072 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3073 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003074 else
Joe Perchesf96637b2013-05-04 22:12:25 -05003075 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3076 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003077 }
3078 }
3079 return rc;
3080}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
3082static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003083ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084{
3085 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003086 /*
3087 * some servers require RFC1001 sessinit before sending
3088 * negprot - BB check reconnection in case where second
3089 * sessinit is sent but no second negprot
3090 */
3091 struct rfc1002_session_packet *ses_init_buf;
3092 struct smb_hdr *smb_buf;
3093 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3094 GFP_KERNEL);
3095 if (ses_init_buf) {
3096 ses_init_buf->trailer.session_req.called_len = 32;
3097
Colin Ian King997152f2016-01-25 16:25:54 +00003098 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003099 rfc1002mangle(ses_init_buf->trailer.
3100 session_req.called_name,
3101 server->server_RFC1001_name,
3102 RFC1001_NAME_LEN_WITH_NULL);
3103 else
3104 rfc1002mangle(ses_init_buf->trailer.
3105 session_req.called_name,
3106 DEFAULT_CIFS_CALLED_NAME,
3107 RFC1001_NAME_LEN_WITH_NULL);
3108
3109 ses_init_buf->trailer.session_req.calling_len = 32;
3110
3111 /*
3112 * calling name ends in null (byte 16) from old smb
3113 * convention.
3114 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003115 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003116 rfc1002mangle(ses_init_buf->trailer.
3117 session_req.calling_name,
3118 server->workstation_RFC1001_name,
3119 RFC1001_NAME_LEN_WITH_NULL);
3120 else
3121 rfc1002mangle(ses_init_buf->trailer.
3122 session_req.calling_name,
3123 "LINUX_CIFS_CLNT",
3124 RFC1001_NAME_LEN_WITH_NULL);
3125
3126 ses_init_buf->trailer.session_req.scope1 = 0;
3127 ses_init_buf->trailer.session_req.scope2 = 0;
3128 smb_buf = (struct smb_hdr *)ses_init_buf;
3129
3130 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003131 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003132 rc = smb_send(server, smb_buf, 0x44);
3133 kfree(ses_init_buf);
3134 /*
3135 * RFC1001 layer in at least one server
3136 * requires very short break before negprot
3137 * presumably because not expecting negprot
3138 * to follow so fast. This is a simple
3139 * solution that works without
3140 * complicating the code and causes no
3141 * significant slowing down on mount
3142 * for everyone else
3143 */
3144 usleep_range(1000, 2000);
3145 }
3146 /*
3147 * else the negprot may still work without this
3148 * even though malloc failed
3149 */
3150
3151 return rc;
3152}
3153
3154static int
3155generic_ip_connect(struct TCP_Server_Info *server)
3156{
3157 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003158 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003159 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003160 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003161 struct sockaddr *saddr;
3162
3163 saddr = (struct sockaddr *) &server->dstaddr;
3164
3165 if (server->dstaddr.ss_family == AF_INET6) {
3166 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3167 slen = sizeof(struct sockaddr_in6);
3168 sfamily = AF_INET6;
3169 } else {
3170 sport = ((struct sockaddr_in *) saddr)->sin_port;
3171 slen = sizeof(struct sockaddr_in);
3172 sfamily = AF_INET;
3173 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003175 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003176 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3177 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003179 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003180 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003183
3184 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003185 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003186 server->ssocket = socket;
3187 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003188 if (sfamily == AF_INET6)
3189 cifs_reclassify_socket6(socket);
3190 else
3191 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 }
3193
Ben Greear3eb9a882010-09-01 17:06:02 -07003194 rc = bind_socket(server);
3195 if (rc < 0)
3196 return rc;
3197
Jeff Laytond5c56052008-12-01 18:42:33 -05003198 /*
3199 * Eventually check for other socket options to change from
3200 * the default. sock_setsockopt not used because it expects
3201 * user space buffer
3202 */
3203 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003204 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003205
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003206 /* make the bufsizes depend on wsize/rsize and max requests */
3207 if (server->noautotune) {
3208 if (socket->sk->sk_sndbuf < (200 * 1024))
3209 socket->sk->sk_sndbuf = 200 * 1024;
3210 if (socket->sk->sk_rcvbuf < (140 * 1024))
3211 socket->sk->sk_rcvbuf = 140 * 1024;
3212 }
3213
Steve French6a5fa2362010-01-01 01:28:43 +00003214 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003215 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003216 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3217 (char *)&val, sizeof(val));
3218 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003219 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3220 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003221 }
3222
Joe Perchesf96637b2013-05-04 22:12:25 -05003223 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003224 socket->sk->sk_sndbuf,
3225 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3226
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003227 rc = socket->ops->connect(socket, saddr, slen, 0);
3228 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003229 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003230 sock_release(socket);
3231 server->ssocket = NULL;
3232 return rc;
3233 }
3234
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003235 if (sport == htons(RFC1001_PORT))
3236 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003237
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 return rc;
3239}
3240
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003241static int
3242ip_connect(struct TCP_Server_Info *server)
3243{
Steve French6da97912011-03-13 18:55:55 +00003244 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003245 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3246 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3247
3248 if (server->dstaddr.ss_family == AF_INET6)
3249 sport = &addr6->sin6_port;
3250 else
3251 sport = &addr->sin_port;
3252
3253 if (*sport == 0) {
3254 int rc;
3255
3256 /* try with 445 port at first */
3257 *sport = htons(CIFS_PORT);
3258
3259 rc = generic_ip_connect(server);
3260 if (rc >= 0)
3261 return rc;
3262
3263 /* if it failed, try with 139 port */
3264 *sport = htons(RFC1001_PORT);
3265 }
3266
3267 return generic_ip_connect(server);
3268}
3269
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003270void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003271 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003272{
3273 /* if we are reconnecting then should we check to see if
3274 * any requested capabilities changed locally e.g. via
3275 * remount but we can not do much about it here
3276 * if they have (even if we could detect it by the following)
3277 * Perhaps we could add a backpointer to array of sb from tcon
3278 * or if we change to make all sb to same share the same
3279 * sb as NFS - then we only have one backpointer to sb.
3280 * What if we wanted to mount the server share twice once with
3281 * and once without posixacls or posix paths? */
3282 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003283
Steve Frenchc18c8422007-07-18 23:21:09 +00003284 if (vol_info && vol_info->no_linux_ext) {
3285 tcon->fsUnixInfo.Capability = 0;
3286 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003287 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003288 return;
3289 } else if (vol_info)
3290 tcon->unix_ext = 1; /* Unix Extensions supported */
3291
3292 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003293 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003294 return;
3295 }
Steve French50c2f752007-07-13 00:33:32 +00003296
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003297 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003298 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003299 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003300 /* check for reconnect case in which we do not
3301 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003302 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003303 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003304 originally at mount time */
3305 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3306 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003307 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3308 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003309 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003310 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003311 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003312 cifs_dbg(VFS, "possible reconnect error\n");
3313 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003314 }
Steve French8af18972007-02-14 04:42:51 +00003315 }
Steve French50c2f752007-07-13 00:33:32 +00003316
Steve French6848b732011-05-26 18:38:54 +00003317 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003318 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003319
Steve French8af18972007-02-14 04:42:51 +00003320 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003321 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003322 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003323 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003324 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003325 if (cifs_sb)
3326 cifs_sb->mnt_cifs_flags |=
3327 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003328 }
3329
Steve French75865f8c2007-06-24 18:30:48 +00003330 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003331 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003332 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003333 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003334 if (cifs_sb)
3335 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003336 CIFS_MOUNT_POSIX_PATHS;
3337 }
Steve French50c2f752007-07-13 00:33:32 +00003338
Joe Perchesf96637b2013-05-04 22:12:25 -05003339 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003340#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003341 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003342 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003343 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003344 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003345 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003346 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003347 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003348 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003349 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003350 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003351 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003352 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003353 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003354 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003355 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003356 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003357 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003358 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003359#endif /* CIFS_DEBUG2 */
3360 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003361 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003362 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003363 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003364 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");
Steve French5a44b312007-09-20 15:16:24 +00003365
Steve French8af18972007-02-14 04:42:51 +00003366 }
3367 }
3368}
3369
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003370int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003371 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003372{
Jeff Layton2de970f2010-10-06 19:51:12 -04003373 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3374
Al Viro2ced6f62011-06-17 09:20:04 -04003375 spin_lock_init(&cifs_sb->tlink_tree_lock);
3376 cifs_sb->tlink_tree = RB_ROOT;
3377
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003378 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003379 * Temporarily set r/wsize for matching superblock. If we end up using
3380 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003381 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003382 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003383 cifs_sb->wsize = pvolume_info->wsize;
3384
Steve French3b795212008-11-13 19:45:32 +00003385 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3386 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3387 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3388 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003389 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3390 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003391
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303392 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003393 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303394
Steve French3b795212008-11-13 19:45:32 +00003395 if (pvolume_info->noperm)
3396 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3397 if (pvolume_info->setuids)
3398 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003399 if (pvolume_info->setuidfromacl)
3400 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003401 if (pvolume_info->server_ino)
3402 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3403 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003404 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3405 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003406 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3407 if (pvolume_info->no_xattr)
3408 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3409 if (pvolume_info->sfu_emul)
3410 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3411 if (pvolume_info->nobrl)
3412 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003413 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003414 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003415 if (pvolume_info->mand_lock)
3416 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003417 if (pvolume_info->rwpidforward)
3418 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003419 if (pvolume_info->cifs_acl)
3420 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003421 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003422 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003423 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3424 }
3425 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003426 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003427 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3428 }
Steve French3b795212008-11-13 19:45:32 +00003429 if (pvolume_info->override_uid)
3430 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3431 if (pvolume_info->override_gid)
3432 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3433 if (pvolume_info->dynperm)
3434 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303435 if (pvolume_info->fsc)
3436 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003437 if (pvolume_info->multiuser)
3438 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3439 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003440 if (pvolume_info->strict_io)
3441 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003442 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003443 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003444 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3445 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003446 if (pvolume_info->mfsymlinks) {
3447 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003448 /*
3449 * Our SFU ("Services for Unix" emulation does not allow
3450 * creating symlinks but does allow reading existing SFU
3451 * symlinks (it does allow both creating and reading SFU
3452 * style mknod and FIFOs though). When "mfsymlinks" and
3453 * "sfu" are both enabled at the same time, it allows
3454 * reading both types of symlinks, but will only create
3455 * them with mfsymlinks format. This allows better
3456 * Apple compatibility (probably better for Samba too)
3457 * while still recognizing old Windows style symlinks.
3458 */
3459 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003460 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003461 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003462 }
Steve French3b795212008-11-13 19:45:32 +00003463
3464 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003465 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003466
3467 if (pvolume_info->prepath) {
3468 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3469 if (cifs_sb->prepath == NULL)
3470 return -ENOMEM;
3471 }
3472
3473 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003474}
3475
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003476static void
3477cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003478{
Sean Finneyb9468452011-04-11 13:19:32 +00003479 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003480 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003481 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003482 kfree(volume_info->domainname);
3483 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003484 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003485}
3486
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003487void
3488cifs_cleanup_volume_info(struct smb_vol *volume_info)
3489{
3490 if (!volume_info)
3491 return;
3492 cleanup_volume_info_contents(volume_info);
3493 kfree(volume_info);
3494}
3495
3496
Steve French2d6d5892009-04-09 00:36:44 +00003497#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003498/*
3499 * cifs_build_path_to_root returns full path to root when we do not have an
3500 * exiting connection (tcon)
3501 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003502static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003503build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003504 const struct cifs_sb_info *cifs_sb)
3505{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003506 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003507 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003508 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003509
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003510 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003511 if (full_path == NULL)
3512 return ERR_PTR(-ENOMEM);
3513
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003514 strncpy(full_path, vol->UNC, unc_len);
3515 pos = full_path + unc_len;
3516
3517 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003518 *pos = CIFS_DIR_SEP(cifs_sb);
3519 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003520 pos += pplen;
3521 }
3522
3523 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003524 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003525 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003526 return full_path;
3527}
Sean Finneydd613942011-04-11 13:19:30 +00003528
3529/*
3530 * Perform a dfs referral query for a share and (optionally) prefix
3531 *
Sean Finney046462a2011-04-11 13:19:33 +00003532 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3533 * to a string containing updated options for the submount. Otherwise it
3534 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003535 *
3536 * Returns the rc from get_dfs_path to the caller, which can be used to
3537 * determine whether there were referrals.
3538 */
3539static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003540expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003541 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003542 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003543{
3544 int rc;
3545 unsigned int num_referrals = 0;
3546 struct dfs_info3_param *referrals = NULL;
3547 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3548
3549 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3550 if (IS_ERR(full_path))
3551 return PTR_ERR(full_path);
3552
3553 /* For DFS paths, skip the first '\' of the UNC */
3554 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3555
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003556 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003557 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003558
3559 if (!rc && num_referrals > 0) {
3560 char *fake_devname = NULL;
3561
3562 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3563 full_path + 1, referrals,
3564 &fake_devname);
3565
3566 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003567
Sean Finneydd613942011-04-11 13:19:30 +00003568 if (IS_ERR(mdata)) {
3569 rc = PTR_ERR(mdata);
3570 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003571 } else {
3572 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003573 rc = cifs_setup_volume_info(volume_info, mdata,
3574 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003575 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003576 kfree(fake_devname);
3577 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003578 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003579 }
3580 kfree(full_path);
3581 return rc;
3582}
Steve French2d6d5892009-04-09 00:36:44 +00003583#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003584
Jeff Layton04db79b2011-07-06 08:10:38 -04003585static int
3586cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3587 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003589 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003590
Jeff Layton04db79b2011-07-06 08:10:38 -04003591 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3592 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593
Jeff Layton7586b762008-12-01 18:41:49 -05003594 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003595 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003596 kfree(volume_info->username);
3597 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003598 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003600 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003602 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003603 /* In userspace mount helper we can get user name from alternate
3604 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003605 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606 }
3607
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003609 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003610 /* load_nls_default cannot return null */
3611 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003613 volume_info->local_nls = load_nls(volume_info->iocharset);
3614 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003615 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003616 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003617 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 }
3619 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003620
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003621 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003622}
3623
3624struct smb_vol *
3625cifs_get_volume_info(char *mount_data, const char *devname)
3626{
3627 int rc;
3628 struct smb_vol *volume_info;
3629
Jeff Layton6ee95422012-11-26 11:09:57 -05003630 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003631 if (!volume_info)
3632 return ERR_PTR(-ENOMEM);
3633
3634 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3635 if (rc) {
3636 cifs_cleanup_volume_info(volume_info);
3637 volume_info = ERR_PTR(rc);
3638 }
3639
3640 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003641}
3642
Aurelien Aptela6b50582016-05-25 19:59:09 +02003643static int
3644cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
3645 unsigned int xid,
3646 struct cifs_tcon *tcon,
3647 struct cifs_sb_info *cifs_sb,
3648 char *full_path)
3649{
3650 int rc;
3651 char *s;
3652 char sep, tmp;
3653
3654 sep = CIFS_DIR_SEP(cifs_sb);
3655 s = full_path;
3656
3657 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
3658 while (rc == 0) {
3659 /* skip separators */
3660 while (*s == sep)
3661 s++;
3662 if (!*s)
3663 break;
3664 /* next separator */
3665 while (*s && *s != sep)
3666 s++;
3667
3668 /*
3669 * temporarily null-terminate the path at the end of
3670 * the current component
3671 */
3672 tmp = *s;
3673 *s = 0;
3674 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3675 full_path);
3676 *s = tmp;
3677 }
3678 return rc;
3679}
3680
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003681int
Al Viro2c6292a2011-06-17 09:05:48 -04003682cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003683{
Jeff Layton1daaae82012-03-21 06:30:40 -04003684 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003685 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003686 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003687 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003688 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003689 char *full_path;
3690 struct tcon_link *tlink;
3691#ifdef CONFIG_CIFS_DFS_UPCALL
3692 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003693#endif
Al Virodd854462011-06-17 08:24:42 -04003694
Christoph Hellwigb4caecd2015-01-14 10:42:32 +01003695 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs");
Al Virodd854462011-06-17 08:24:42 -04003696 if (rc)
3697 return rc;
3698
Jeff Layton20547492011-07-09 12:21:07 -04003699#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003700try_mount_again:
3701 /* cleanup activities if we're chasing a referral */
3702 if (referral_walks_count) {
3703 if (tcon)
3704 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003705 else if (ses)
3706 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003707
Sachin Prabhu1dfd18d2015-06-16 16:36:17 +01003708 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3709
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003710 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003711 }
3712#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003713 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003714 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003715 ses = NULL;
3716 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003717 full_path = NULL;
3718 tlink = NULL;
3719
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003720 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721
Jeff Layton63c038c2008-12-01 18:41:46 -05003722 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003723 server = cifs_get_tcp_session(volume_info);
3724 if (IS_ERR(server)) {
3725 rc = PTR_ERR(server);
Al Virodd854462011-06-17 08:24:42 -04003726 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003727 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 }
Steve French141891f2016-09-23 00:44:16 -05003729 if ((volume_info->max_credits < 20) ||
3730 (volume_info->max_credits > 60000))
3731 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3732 else
3733 server->max_credits = volume_info->max_credits;
Jeff Layton36988c72010-04-24 07:57:43 -04003734 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003735 ses = cifs_get_smb_ses(server, volume_info);
3736 if (IS_ERR(ses)) {
3737 rc = PTR_ERR(ses);
3738 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003739 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 }
Steve French50c2f752007-07-13 00:33:32 +00003741
Steve French592fafe2015-11-03 10:08:53 -06003742#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06003743 if ((volume_info->persistent == true) && ((ses->server->capabilities &
3744 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
3745 cifs_dbg(VFS, "persistent handles not supported by server\n");
3746 rc = -EOPNOTSUPP;
3747 goto mount_fail_check;
3748 }
Steve French592fafe2015-11-03 10:08:53 -06003749#endif /* CONFIG_CIFS_SMB2*/
3750
Jeff Laytond00c28d2010-04-24 07:57:44 -04003751 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003752 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003753 if (IS_ERR(tcon)) {
3754 rc = PTR_ERR(tcon);
3755 tcon = NULL;
Mark Syms40920c22016-11-29 11:36:46 +00003756 if (rc == -EACCES)
3757 goto mount_fail_check;
3758
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003759 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003760 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003761
Steve French6848b732011-05-26 18:38:54 +00003762 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003763 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003764 /* reset of caps checks mount to see if unix extensions
3765 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003766 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003767 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3768 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3769 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3770 rc = -EACCES;
3771 goto mount_fail_check;
3772 }
3773 } else
3774 tcon->unix_ext = 0; /* server does not support them */
3775
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003776 /* do not care if a following call succeed - informational */
3777 if (!tcon->ipc && server->ops->qfs_tcon)
3778 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003779
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003780 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3781 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003782
Jeff Layton66bfaad2011-10-19 15:30:35 -04003783 /* tune readahead according to rsize */
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03003784 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003785
Igor Mammedove4cce942009-02-10 14:10:26 +03003786remote_path_check:
3787#ifdef CONFIG_CIFS_DFS_UPCALL
3788 /*
3789 * Perform an unconditional check for whether there are DFS
3790 * referrals for this path without prefix, to provide support
3791 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003792 * with PATH_NOT_COVERED to requests that include the prefix.
3793 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003794 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003795 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003796 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3797 false);
Steve Frencheeac8042006-01-13 21:34:58 -08003798 if (!refrc) {
Steve French4523cc32007-04-30 20:13:06 +00003799 referral_walks_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 goto try_mount_again;
3801 }
3802 }
3803#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003804
Steve Frenchf87d39d2011-05-27 03:50:55 +00003805 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003807 if (!server->ops->is_path_accessible) {
3808 rc = -ENOSYS;
3809 goto mount_fail_check;
3810 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003811 /*
3812 * cifs_build_path_to_root works only when we have a valid tcon
3813 */
Sachin Prabhu374402a2016-12-15 12:31:19 +05303814 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
3815 tcon->Flags & SMB_SHARE_IS_IN_DFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 if (full_path == NULL) {
3817 rc = -ENOMEM;
3818 goto mount_fail_check;
3819 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003820 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3821 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 if (rc != 0 && rc != -EREMOTE) {
3823 kfree(full_path);
3824 goto mount_fail_check;
3825 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02003826
Sachin Prabhud1713562016-09-06 13:22:34 +01003827 if (rc != -EREMOTE) {
3828 rc = cifs_are_all_path_components_accessible(server,
Aurelien Aptela6b50582016-05-25 19:59:09 +02003829 xid, tcon, cifs_sb,
3830 full_path);
Sachin Prabhud1713562016-09-06 13:22:34 +01003831 if (rc != 0) {
3832 cifs_dbg(VFS, "cannot query dirs between root and final path, "
3833 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
3834 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
3835 rc = 0;
3836 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02003837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 kfree(full_path);
3839 }
3840
3841 /* get referral if needed */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003842 if (rc == -EREMOTE) {
3843#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003844 if (referral_walks_count > MAX_NESTED_LINKS) {
3845 /*
3846 * BB: when we implement proper loop detection,
3847 * we will remove this check. But now we need it
3848 * to prevent an indefinite loop if 'DFS tree' is
3849 * misconfigured (i.e. has loops).
3850 */
3851 rc = -ELOOP;
3852 goto mount_fail_check;
3853 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003854
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003855 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003856
Sean Finneydd613942011-04-11 13:19:30 +00003857 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003858 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003859 goto try_mount_again;
3860 }
Sean Finneydd613942011-04-11 13:19:30 +00003861 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003862#else /* No DFS support, return error on mount */
3863 rc = -EOPNOTSUPP;
3864#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003865 }
3866
Jeff Layton9d002df2010-10-06 19:51:11 -04003867 if (rc)
3868 goto mount_fail_check;
3869
3870 /* now, hang the tcon off of the superblock */
3871 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3872 if (tlink == NULL) {
3873 rc = -ENOMEM;
3874 goto mount_fail_check;
3875 }
3876
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003877 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003878 tlink->tl_tcon = tcon;
3879 tlink->tl_time = jiffies;
3880 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3881 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3882
Jeff Layton413e6612010-10-28 13:33:38 -04003883 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003884 spin_lock(&cifs_sb->tlink_tree_lock);
3885 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3886 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003887
Jeff Laytonda472fc2012-03-23 14:40:53 -04003888 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003889 TLINK_IDLE_EXPIRE);
3890
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003891mount_fail_check:
3892 /* on error free sesinfo and tcon struct if needed */
3893 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003894 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003895 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003896 if (tcon)
3897 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003898 else if (ses)
3899 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003900 else
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003901 cifs_put_tcp_session(server, 0);
Al Virodd854462011-06-17 08:24:42 -04003902 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003903 }
3904
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003906 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 return rc;
3908}
3909
Jeff Layton8d1bca32011-06-11 21:17:10 -04003910/*
3911 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3912 * pointer may be NULL.
3913 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003915CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00003916 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 const struct nls_table *nls_codepage)
3918{
3919 struct smb_hdr *smb_buffer;
3920 struct smb_hdr *smb_buffer_response;
3921 TCONX_REQ *pSMB;
3922 TCONX_RSP *pSMBr;
3923 unsigned char *bcc_ptr;
3924 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003925 int length;
3926 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927
3928 if (ses == NULL)
3929 return -EIO;
3930
3931 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003932 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003934
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 smb_buffer_response = smb_buffer;
3936
3937 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3938 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003939
Pavel Shilovsky88257362012-05-23 14:01:59 +04003940 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 smb_buffer->Uid = ses->Suid;
3942 pSMB = (TCONX_REQ *) smb_buffer;
3943 pSMBr = (TCONX_RSP *) smb_buffer_response;
3944
3945 pSMB->AndXCommand = 0xFF;
3946 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003948 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003949 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003950 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003951 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003952 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003953 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003954 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003955 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3956 specified as required (when that support is added to
3957 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003958 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003959 by Samba (not sure whether other servers allow
3960 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003961#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003962 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05003963 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003964 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003965 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003966 SECMODE_PW_ENCRYPT ? true : false,
3967 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003968 else
3969#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003970 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003971 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05003972 if (rc) {
3973 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
3974 __func__, rc);
3975 cifs_buf_release(smb_buffer);
3976 return rc;
3977 }
Steve Frencheeac8042006-01-13 21:34:58 -08003978
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003979 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003980 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003981 /* must align unicode strings */
3982 *bcc_ptr = 0; /* null byte password */
3983 bcc_ptr++;
3984 }
Steve Frencheeac8042006-01-13 21:34:58 -08003985 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986
Jeff Layton38d77c52013-05-26 07:01:00 -04003987 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3989
3990 if (ses->capabilities & CAP_STATUS32) {
3991 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3992 }
3993 if (ses->capabilities & CAP_DFS) {
3994 smb_buffer->Flags2 |= SMBFLG2_DFS;
3995 }
3996 if (ses->capabilities & CAP_UNICODE) {
3997 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3998 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003999 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004000 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004001 (/* server len*/ + 256 /* share len */), nls_codepage);
4002 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 bcc_ptr += 2; /* skip trailing null */
4004 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 strcpy(bcc_ptr, tree);
4006 bcc_ptr += strlen(tree) + 1;
4007 }
4008 strcpy(bcc_ptr, "?????");
4009 bcc_ptr += strlen("?????");
4010 bcc_ptr += 1;
4011 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004012 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4013 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 pSMB->ByteCount = cpu_to_le16(count);
4015
Steve French133672e2007-11-13 22:41:37 +00004016 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004017 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 /* above now done in SendReceive */
4020 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004021 bool is_unicode;
4022
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004024 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 tcon->tid = smb_buffer_response->Tid;
4026 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004027 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004028 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004029 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4030 is_unicode = true;
4031 else
4032 is_unicode = false;
4033
Jeff Laytoncc20c032009-04-30 07:16:21 -04004034
Steve French50c2f752007-07-13 00:33:32 +00004035 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004036 if (length == 3) {
4037 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4038 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004039 cifs_dbg(FYI, "IPC connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004040 tcon->ipc = 1;
4041 }
4042 } else if (length == 2) {
4043 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4044 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05004045 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00004046 }
4047 }
Steve French50c2f752007-07-13 00:33:32 +00004048 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004049 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05004050 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04004051
4052 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004053 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004054 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004055 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004056 nls_codepage);
4057
Joe Perchesf96637b2013-05-04 22:12:25 -05004058 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004059
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004060 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004061 (smb_buffer_response->WordCount == 7))
4062 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004063 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4064 else
4065 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05004066 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004068 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 ses->ipc_tid = smb_buffer_response->Tid;
4070 }
4071
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004072 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 return rc;
4074}
4075
Al Viro2e32cf52013-10-03 12:53:37 -04004076static void delayed_free(struct rcu_head *p)
4077{
4078 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
4079 unload_nls(sbi->local_nls);
4080 kfree(sbi);
4081}
4082
Al Viro2a9b9952011-06-17 09:27:16 -04004083void
4084cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085{
Jeff Laytonb647c352010-10-28 11:16:44 -04004086 struct rb_root *root = &cifs_sb->tlink_tree;
4087 struct rb_node *node;
4088 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Jeff Layton2de970f2010-10-06 19:51:12 -04004090 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4091
Jeff Laytonb647c352010-10-28 11:16:44 -04004092 spin_lock(&cifs_sb->tlink_tree_lock);
4093 while ((node = rb_first(root))) {
4094 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4095 cifs_get_tlink(tlink);
4096 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4097 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004098
Jeff Laytonb647c352010-10-28 11:16:44 -04004099 spin_unlock(&cifs_sb->tlink_tree_lock);
4100 cifs_put_tlink(tlink);
4101 spin_lock(&cifs_sb->tlink_tree_lock);
4102 }
4103 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004104
Al Virodd854462011-06-17 08:24:42 -04004105 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004106 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02004107 kfree(cifs_sb->prepath);
Al Viro2e32cf52013-10-03 12:53:37 -04004108 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00004109}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004111int
4112cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113{
4114 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004115 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004117 if (!server->ops->need_neg || !server->ops->negotiate)
4118 return -ENOSYS;
4119
Jeff Layton198b5682010-04-24 07:57:48 -04004120 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004121 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004122 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
Pavel Shilovsky45275782012-05-17 17:53:29 +04004124 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004125
4126 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004127 if (rc == 0) {
4128 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004129 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004130 server->tcpStatus = CifsGood;
4131 else
4132 rc = -EHOSTDOWN;
4133 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 }
Steve French26b994f2008-08-06 05:11:33 +00004135
Jeff Layton198b5682010-04-24 07:57:48 -04004136 return rc;
4137}
Steve French26b994f2008-08-06 05:11:33 +00004138
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004139int
4140cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4141 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004142{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004143 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004144 struct TCP_Server_Info *server = ses->server;
4145
Jeff Layton198b5682010-04-24 07:57:48 -04004146 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004147 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004148 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004149
Joe Perchesf96637b2013-05-04 22:12:25 -05004150 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004151 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004152
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004153 if (server->ops->sess_setup)
4154 rc = server->ops->sess_setup(xid, ses, nls_info);
4155
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004156 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004157 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004158
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 return rc;
4160}
4161
Jeff Layton8a8798a2012-01-17 16:09:15 -05004162static int
4163cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4164{
Jeff Layton3f618222013-06-12 19:52:14 -05004165 vol->sectype = ses->sectype;
4166
4167 /* krb5 is special, since we don't need username or pw */
4168 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004169 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004170
4171 return cifs_set_cifscreds(vol, ses);
4172}
4173
Steve French96daf2b2011-05-27 04:34:02 +00004174static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004175cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004176{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004177 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004178 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4179 struct cifs_ses *ses;
4180 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004181 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004182
4183 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004184 if (vol_info == NULL)
4185 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004186
Jeff Layton9d002df2010-10-06 19:51:11 -04004187 vol_info->local_nls = cifs_sb->local_nls;
4188 vol_info->linux_uid = fsuid;
4189 vol_info->cred_uid = fsuid;
4190 vol_info->UNC = master_tcon->treeName;
4191 vol_info->retry = master_tcon->retry;
4192 vol_info->nocase = master_tcon->nocase;
4193 vol_info->local_lease = master_tcon->local_lease;
4194 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004195 vol_info->sectype = master_tcon->ses->sectype;
4196 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004197
Jeff Layton8a8798a2012-01-17 16:09:15 -05004198 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4199 if (rc) {
4200 tcon = ERR_PTR(rc);
4201 goto out;
4202 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004203
4204 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304205 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004206 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304207 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004208
4209 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4210 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004211 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07004212 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04004213 goto out;
4214 }
4215
4216 tcon = cifs_get_tcon(ses, vol_info);
4217 if (IS_ERR(tcon)) {
4218 cifs_put_smb_ses(ses);
4219 goto out;
4220 }
4221
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004222 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004223 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4224out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004225 kfree(vol_info->username);
4226 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004227 kfree(vol_info);
4228
4229 return tcon;
4230}
4231
Steve French96daf2b2011-05-27 04:34:02 +00004232struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004233cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4234{
4235 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4236}
4237
Jeff Laytonb647c352010-10-28 11:16:44 -04004238/* find and return a tlink with given uid */
4239static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004240tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004241{
4242 struct rb_node *node = root->rb_node;
4243 struct tcon_link *tlink;
4244
4245 while (node) {
4246 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4247
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004248 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004249 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004250 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004251 node = node->rb_right;
4252 else
4253 return tlink;
4254 }
4255 return NULL;
4256}
4257
4258/* insert a tcon_link into the tree */
4259static void
4260tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4261{
4262 struct rb_node **new = &(root->rb_node), *parent = NULL;
4263 struct tcon_link *tlink;
4264
4265 while (*new) {
4266 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4267 parent = *new;
4268
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004269 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004270 new = &((*new)->rb_left);
4271 else
4272 new = &((*new)->rb_right);
4273 }
4274
4275 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4276 rb_insert_color(&new_tlink->tl_rbnode, root);
4277}
4278
Jeff Layton9d002df2010-10-06 19:51:11 -04004279/*
4280 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4281 * current task.
4282 *
4283 * If the superblock doesn't refer to a multiuser mount, then just return
4284 * the master tcon for the mount.
4285 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304286 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004287 * exists, then check to see if it's pending construction. If it is then wait
4288 * for construction to complete. Once it's no longer pending, check to see if
4289 * it failed and either return an error or retry construction, depending on
4290 * the timeout.
4291 *
4292 * If one doesn't exist then insert a new tcon_link struct into the tree and
4293 * try to construct a new one.
4294 */
4295struct tcon_link *
4296cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4297{
4298 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004299 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004300 struct tcon_link *tlink, *newtlink;
4301
4302 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4303 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4304
4305 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004306 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004307 if (tlink)
4308 cifs_get_tlink(tlink);
4309 spin_unlock(&cifs_sb->tlink_tree_lock);
4310
4311 if (tlink == NULL) {
4312 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4313 if (newtlink == NULL)
4314 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004315 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004316 newtlink->tl_tcon = ERR_PTR(-EACCES);
4317 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4318 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4319 cifs_get_tlink(newtlink);
4320
Jeff Layton9d002df2010-10-06 19:51:11 -04004321 spin_lock(&cifs_sb->tlink_tree_lock);
4322 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004323 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004324 if (tlink) {
4325 cifs_get_tlink(tlink);
4326 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004327 kfree(newtlink);
4328 goto wait_for_construction;
4329 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004330 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004331 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4332 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004333 } else {
4334wait_for_construction:
4335 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004336 TASK_INTERRUPTIBLE);
4337 if (ret) {
4338 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004339 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004340 }
4341
4342 /* if it's good, return it */
4343 if (!IS_ERR(tlink->tl_tcon))
4344 return tlink;
4345
4346 /* return error if we tried this already recently */
4347 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4348 cifs_put_tlink(tlink);
4349 return ERR_PTR(-EACCES);
4350 }
4351
4352 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4353 goto wait_for_construction;
4354 }
4355
4356 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4357 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4358 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4359
4360 if (IS_ERR(tlink->tl_tcon)) {
4361 cifs_put_tlink(tlink);
4362 return ERR_PTR(-EACCES);
4363 }
4364
4365 return tlink;
4366}
Jeff Layton2de970f2010-10-06 19:51:12 -04004367
4368/*
4369 * periodic workqueue job that scans tcon_tree for a superblock and closes
4370 * out tcons.
4371 */
4372static void
4373cifs_prune_tlinks(struct work_struct *work)
4374{
4375 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4376 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004377 struct rb_root *root = &cifs_sb->tlink_tree;
4378 struct rb_node *node = rb_first(root);
4379 struct rb_node *tmp;
4380 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004381
Jeff Laytonb647c352010-10-28 11:16:44 -04004382 /*
4383 * Because we drop the spinlock in the loop in order to put the tlink
4384 * it's not guarded against removal of links from the tree. The only
4385 * places that remove entries from the tree are this function and
4386 * umounts. Because this function is non-reentrant and is canceled
4387 * before umount can proceed, this is safe.
4388 */
4389 spin_lock(&cifs_sb->tlink_tree_lock);
4390 node = rb_first(root);
4391 while (node != NULL) {
4392 tmp = node;
4393 node = rb_next(tmp);
4394 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4395
4396 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4397 atomic_read(&tlink->tl_count) != 0 ||
4398 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4399 continue;
4400
4401 cifs_get_tlink(tlink);
4402 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4403 rb_erase(tmp, root);
4404
Jeff Layton2de970f2010-10-06 19:51:12 -04004405 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004406 cifs_put_tlink(tlink);
4407 spin_lock(&cifs_sb->tlink_tree_lock);
4408 }
4409 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004410
Jeff Laytonda472fc2012-03-23 14:40:53 -04004411 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004412 TLINK_IDLE_EXPIRE);
4413}