blob: db726e8311caeceb3355ffecd81d5f21ad0989f8 [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>
24#include <linux/list.h>
25#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070031#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070032#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000033#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070034#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080035#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040036#include <linux/namei.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <asm/uaccess.h>
38#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040039#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040040#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050041#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000042#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040043#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060044#include <linux/bvec.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040045
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include "cifspdu.h"
47#include "cifsglob.h"
48#include "cifsproto.h"
49#include "cifs_unicode.h"
50#include "cifs_debug.h"
51#include "cifs_fs_sb.h"
52#include "ntlmssp.h"
53#include "nterr.h"
54#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053055#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#define CIFS_PORT 445
58#define RFC1001_PORT 139
59
Linus Torvalds1da177e2005-04-16 15:20:36 -070060extern mempool_t *cifs_req_poolp;
61
Jeff Layton2de970f2010-10-06 19:51:12 -040062/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040063#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040064#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040065
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040066enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040067 /* Mount options that take no arguments */
68 Opt_user_xattr, Opt_nouser_xattr,
69 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040070 Opt_forcegid, Opt_noforcegid,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040071 Opt_noblocksend, Opt_noautotune,
72 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050073 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040074 Opt_mapchars, Opt_nomapchars, Opt_sfu,
75 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
76 Opt_noposixpaths, Opt_nounix,
77 Opt_nocase,
78 Opt_brl, Opt_nobrl,
Steve French95932652016-09-23 01:36:34 -050079 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040080 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
81 Opt_nohard, Opt_nosoft,
82 Opt_nointr, Opt_intr,
83 Opt_nostrictsync, Opt_strictsync,
84 Opt_serverino, Opt_noserverino,
85 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
86 Opt_acl, Opt_noacl, Opt_locallease,
Jeff Layton1b359202012-09-19 15:20:27 -070087 Opt_sign, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040088 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040089 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050090 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060091 Opt_resilient, Opt_noresilient,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040092
93 /* Mount options which take numeric value */
94 Opt_backupuid, Opt_backupgid, Opt_uid,
95 Opt_cruid, Opt_gid, Opt_file_mode,
96 Opt_dirmode, Opt_port,
97 Opt_rsize, Opt_wsize, Opt_actimeo,
Steve French141891f2016-09-23 00:44:16 -050098 Opt_echo_interval, Opt_max_credits,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040099
100 /* Mount options which take string value */
101 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400102 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400103 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400104 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400105
106 /* Mount options to be ignored */
107 Opt_ignore,
108
109 /* Options which could be blank */
110 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100111 Opt_blank_user,
112 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400113
114 Opt_err
115};
116
117static const match_table_t cifs_mount_option_tokens = {
118
119 { Opt_user_xattr, "user_xattr" },
120 { Opt_nouser_xattr, "nouser_xattr" },
121 { Opt_forceuid, "forceuid" },
122 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400123 { Opt_forcegid, "forcegid" },
124 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400125 { Opt_noblocksend, "noblocksend" },
126 { Opt_noautotune, "noautotune" },
127 { Opt_hard, "hard" },
128 { Opt_soft, "soft" },
129 { Opt_perm, "perm" },
130 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500131 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400132 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500133 { Opt_mapposix, "mapposix" }, /* SFM style */
134 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400135 { Opt_sfu, "sfu" },
136 { Opt_nosfu, "nosfu" },
137 { Opt_nodfs, "nodfs" },
138 { Opt_posixpaths, "posixpaths" },
139 { Opt_noposixpaths, "noposixpaths" },
140 { Opt_nounix, "nounix" },
141 { Opt_nounix, "nolinux" },
142 { Opt_nocase, "nocase" },
143 { Opt_nocase, "ignorecase" },
144 { Opt_brl, "brl" },
145 { Opt_nobrl, "nobrl" },
146 { Opt_nobrl, "nolock" },
147 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400148 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400149 { Opt_setuids, "setuids" },
150 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500151 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400152 { Opt_dynperm, "dynperm" },
153 { Opt_nodynperm, "nodynperm" },
154 { Opt_nohard, "nohard" },
155 { Opt_nosoft, "nosoft" },
156 { Opt_nointr, "nointr" },
157 { Opt_intr, "intr" },
158 { Opt_nostrictsync, "nostrictsync" },
159 { Opt_strictsync, "strictsync" },
160 { Opt_serverino, "serverino" },
161 { Opt_noserverino, "noserverino" },
162 { Opt_rwpidforward, "rwpidforward" },
163 { Opt_cifsacl, "cifsacl" },
164 { Opt_nocifsacl, "nocifsacl" },
165 { Opt_acl, "acl" },
166 { Opt_noacl, "noacl" },
167 { Opt_locallease, "locallease" },
168 { Opt_sign, "sign" },
169 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400170 { Opt_noac, "noac" },
171 { Opt_fsc, "fsc" },
172 { Opt_mfsymlinks, "mfsymlinks" },
173 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400174 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400175 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500176 { Opt_persistent, "persistenthandles"},
177 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600178 { Opt_resilient, "resilienthandles"},
179 { Opt_noresilient, "noresilienthandles"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400180
181 { Opt_backupuid, "backupuid=%s" },
182 { Opt_backupgid, "backupgid=%s" },
183 { Opt_uid, "uid=%s" },
184 { Opt_cruid, "cruid=%s" },
185 { Opt_gid, "gid=%s" },
186 { Opt_file_mode, "file_mode=%s" },
187 { Opt_dirmode, "dirmode=%s" },
188 { Opt_dirmode, "dir_mode=%s" },
189 { Opt_port, "port=%s" },
190 { Opt_rsize, "rsize=%s" },
191 { Opt_wsize, "wsize=%s" },
192 { Opt_actimeo, "actimeo=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600193 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500194 { Opt_max_credits, "max_credits=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400195
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100196 { Opt_blank_user, "user=" },
197 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400198 { Opt_user, "user=%s" },
199 { Opt_user, "username=%s" },
200 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100201 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400202 { Opt_pass, "pass=%s" },
203 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100204 { Opt_blank_ip, "ip=" },
205 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400206 { Opt_ip, "ip=%s" },
207 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400208 { Opt_ignore, "unc=%s" },
209 { Opt_ignore, "target=%s" },
210 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400211 { Opt_domain, "dom=%s" },
212 { Opt_domain, "domain=%s" },
213 { Opt_domain, "workgroup=%s" },
214 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400215 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400216 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400217 { Opt_netbiosname, "netbiosname=%s" },
218 { Opt_servern, "servern=%s" },
219 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400220 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400221 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400222 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400223
224 { Opt_ignore, "cred" },
225 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400226 { Opt_ignore, "cred=%s" },
227 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400228 { Opt_ignore, "guest" },
229 { Opt_ignore, "rw" },
230 { Opt_ignore, "ro" },
231 { Opt_ignore, "suid" },
232 { Opt_ignore, "nosuid" },
233 { Opt_ignore, "exec" },
234 { Opt_ignore, "noexec" },
235 { Opt_ignore, "nodev" },
236 { Opt_ignore, "noauto" },
237 { Opt_ignore, "dev" },
238 { Opt_ignore, "mand" },
239 { Opt_ignore, "nomand" },
240 { Opt_ignore, "_netdev" },
241
242 { Opt_err, NULL }
243};
244
245enum {
246 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
247 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400248 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
249 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400250 Opt_sec_none,
251
252 Opt_sec_err
253};
254
255static const match_table_t cifs_secflavor_tokens = {
256 { Opt_sec_krb5, "krb5" },
257 { Opt_sec_krb5i, "krb5i" },
258 { Opt_sec_krb5p, "krb5p" },
259 { Opt_sec_ntlmsspi, "ntlmsspi" },
260 { Opt_sec_ntlmssp, "ntlmssp" },
261 { Opt_ntlm, "ntlm" },
262 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400263 { Opt_sec_ntlmv2, "nontlm" },
264 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400265 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400266 { Opt_sec_lanman, "lanman" },
267 { Opt_sec_none, "none" },
268
269 { Opt_sec_err, NULL }
270};
271
Jeff Layton15b6a472012-05-16 07:50:15 -0400272/* cache flavors */
273enum {
274 Opt_cache_loose,
275 Opt_cache_strict,
276 Opt_cache_none,
277 Opt_cache_err
278};
279
280static const match_table_t cifs_cacheflavor_tokens = {
281 { Opt_cache_loose, "loose" },
282 { Opt_cache_strict, "strict" },
283 { Opt_cache_none, "none" },
284 { Opt_cache_err, NULL }
285};
286
Jeff Layton23db65f2012-05-15 12:20:51 -0400287static const match_table_t cifs_smb_version_tokens = {
288 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600289 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000290 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500291 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500292 { Smb_302, SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600293#ifdef CONFIG_CIFS_SMB311
294 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500295 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600296#endif /* SMB311 */
297 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400298};
299
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300300static int ip_connect(struct TCP_Server_Info *server);
301static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400302static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400303static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400304static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
305 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Jeff Laytond5c56052008-12-01 18:42:33 -0500307/*
308 * cifs tcp session reconnection
309 *
310 * mark tcp session as reconnecting so temporarily locked
311 * mark all smb sessions as reconnecting for tcp session
312 * reconnect tcp session
313 * wake up waiters on reconnection? - (not needed currently)
314 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400315int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316cifs_reconnect(struct TCP_Server_Info *server)
317{
318 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500319 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000320 struct cifs_ses *ses;
321 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000322 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400323 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000324
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000326 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000327 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 next time through the loop */
329 spin_unlock(&GlobalMid_Lock);
330 return rc;
331 } else
332 server->tcpStatus = CifsNeedReconnect;
333 spin_unlock(&GlobalMid_Lock);
334 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400335#ifdef CONFIG_CIFS_SMB2
336 server->max_read = 0;
337#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Joe Perchesf96637b2013-05-04 22:12:25 -0500339 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
341 /* before reconnecting the tcp session, mark the smb session (uid)
342 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500343 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
344 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530345 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500346 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000347 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500348 ses->need_reconnect = true;
349 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500350 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000351 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500352 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530355 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500356
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500358 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500359 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000360 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500361 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
362 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800363 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500364 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
365 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 sock_release(server->ssocket);
367 server->ssocket = NULL;
368 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500369 server->sequence_number = 0;
370 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500371 kfree(server->session_key.response);
372 server->session_key.response = NULL;
373 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000374 server->lstrp = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500376 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400377 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500378 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500380 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
381 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400382 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
383 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400384 list_move(&mid_entry->qhead, &retry_list);
385 }
386 spin_unlock(&GlobalMid_Lock);
Rabin Vincent820962d2015-12-23 07:32:41 +0100387 mutex_unlock(&server->srv_mutex);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400388
Joe Perchesf96637b2013-05-04 22:12:25 -0500389 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400390 list_for_each_safe(tmp, tmp2, &retry_list) {
391 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500392 list_del_init(&mid_entry->qhead);
393 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400396 do {
Steve French6c3d8902006-07-31 22:46:20 +0000397 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300398
399 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400400 mutex_lock(&server->srv_mutex);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300401 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000402 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500403 cifs_dbg(FYI, "reconnect error %d\n", rc);
Federico Sauter4afe2602015-03-17 17:45:28 +0100404 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700405 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 } else {
407 atomic_inc(&tcpSesReconnectCount);
408 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000409 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000410 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000411 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100412 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400414 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 return rc;
417}
418
Jeff Laytonc74093b2011-01-11 07:24:23 -0500419static void
420cifs_echo_request(struct work_struct *work)
421{
422 int rc;
423 struct TCP_Server_Info *server = container_of(work,
424 struct TCP_Server_Info, echo.work);
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600425 unsigned long echo_interval = server->echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500426
Jeff Layton247ec9b2011-02-04 17:09:50 -0500427 /*
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400428 * We cannot send an echo if it is disabled or until the
429 * NEGOTIATE_PROTOCOL request is done, which is indicated by
430 * server->ops->need_neg() == true. Also, no need to ping if
431 * we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500432 */
Steve French4fcd1812016-06-22 20:12:05 -0500433
434 if (server->tcpStatus == CifsNeedReconnect ||
435 server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400436 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600437 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500438 goto requeue_echo;
439
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400440 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500441 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500442 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
443 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500444
445requeue_echo:
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600446 queue_delayed_work(cifsiod_wq, &server->echo, echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500447}
448
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400449static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400450allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400451{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400452 if (!server->bigbuf) {
453 server->bigbuf = (char *)cifs_buf_get();
454 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500455 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400456 msleep(3000);
457 /* retry will check if exiting */
458 return false;
459 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400460 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400461 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400462 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400463 }
464
Jeff Layton2a37ef92011-10-19 15:29:23 -0400465 if (!server->smallbuf) {
466 server->smallbuf = (char *)cifs_small_buf_get();
467 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500468 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400469 msleep(1000);
470 /* retry will check if exiting */
471 return false;
472 }
473 /* beginning of smb buffer is cleared in our buf_get */
474 } else {
475 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400476 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400477 }
478
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400479 return true;
480}
481
Jeff Laytonba749e62011-10-11 06:41:32 -0400482static bool
483server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400484{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300485 /*
486 * We need to wait 2 echo intervals to make sure we handle such
487 * situations right:
488 * 1s client sends a normal SMB request
489 * 2s client gets a response
490 * 30s echo workqueue job pops, and decides we got a response recently
491 * and don't need to send another
492 * ...
493 * 65s kernel_recvmsg times out, and we see that we haven't gotten
494 * a response in >60s.
495 */
496 if (server->tcpStatus == CifsGood &&
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600497 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
498 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
499 server->hostname, (2 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400500 cifs_reconnect(server);
501 wake_up(&server->response_q);
502 return true;
503 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400504
Jeff Laytonba749e62011-10-11 06:41:32 -0400505 return false;
506}
507
Al Viro71335662016-01-09 19:54:50 -0500508static int
509cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400510{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400511 int length = 0;
512 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400513
Al Viro71335662016-01-09 19:54:50 -0500514 smb_msg->msg_control = NULL;
515 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400516
Al Viro71335662016-01-09 19:54:50 -0500517 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500518 try_to_freeze();
519
Al Viro71335662016-01-09 19:54:50 -0500520 if (server_unresponsive(server))
521 return -ECONNABORTED;
522
523 length = sock_recvmsg(server->ssocket, smb_msg, 0);
524
525 if (server->tcpStatus == CifsExiting)
526 return -ESHUTDOWN;
527
528 if (server->tcpStatus == CifsNeedReconnect) {
529 cifs_reconnect(server);
530 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400531 }
532
Al Viro71335662016-01-09 19:54:50 -0500533 if (length == -ERESTARTSYS ||
534 length == -EAGAIN ||
535 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400536 /*
537 * Minimum sleep to prevent looping, allowing socket
538 * to clear and app threads to set tcpStatus
539 * CifsNeedReconnect if server hung.
540 */
541 usleep_range(1000, 2000);
542 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400543 continue;
Al Viro71335662016-01-09 19:54:50 -0500544 }
545
546 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500547 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400548 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500549 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400550 }
551 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400552 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400553}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400554
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400555int
556cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
557 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400558{
Al Viro71335662016-01-09 19:54:50 -0500559 struct msghdr smb_msg;
560 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
561 iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400562
Al Viro71335662016-01-09 19:54:50 -0500563 return cifs_readv_from_socket(server, &smb_msg);
564}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400565
Al Viro71335662016-01-09 19:54:50 -0500566int
567cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
568 unsigned int to_read)
569{
570 struct msghdr smb_msg;
571 struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
572 iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
573 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400574}
575
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400576static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400577is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400578{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400579 /*
580 * The first byte big endian of the length field,
581 * is actually not part of the length but the type
582 * with the most common, zero, as regular data.
583 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400584 switch (type) {
585 case RFC1002_SESSION_MESSAGE:
586 /* Regular SMB response */
587 return true;
588 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500589 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400590 break;
591 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500592 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400593 break;
594 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400595 /*
596 * We get this from Windows 98 instead of an error on
597 * SMB negprot response.
598 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500599 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400600 /* give server a second to clean up */
601 msleep(1000);
602 /*
603 * Always try 445 first on reconnect since we get NACK
604 * on some if we ever connected to port 139 (the NACK
605 * is since we do not begin with RFC1001 session
606 * initialize frame).
607 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400608 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400609 cifs_reconnect(server);
610 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400611 break;
612 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500613 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400614 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400615 }
616
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400617 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400618}
619
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400620void
621dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400622{
623#ifdef CONFIG_CIFS_STATS2
624 mid->when_received = jiffies;
625#endif
626 spin_lock(&GlobalMid_Lock);
627 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400628 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400629 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400630 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400631 list_del_init(&mid->qhead);
632 spin_unlock(&GlobalMid_Lock);
633}
634
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400635static void
636handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400637 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400638{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400639 if (server->ops->check_trans2 &&
640 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400641 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400642 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400643 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400644 /* Was previous buf put in mpx struct for multi-rsp? */
645 if (!mid->multiRsp) {
646 /* smb buffer will be freed by user thread */
647 if (server->large_buf)
648 server->bigbuf = NULL;
649 else
650 server->smallbuf = NULL;
651 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400652 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400653}
654
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400655static void clean_demultiplex_info(struct TCP_Server_Info *server)
656{
657 int length;
658
659 /* take it off the list, if it's not already */
660 spin_lock(&cifs_tcp_ses_lock);
661 list_del_init(&server->tcp_ses_list);
662 spin_unlock(&cifs_tcp_ses_lock);
663
664 spin_lock(&GlobalMid_Lock);
665 server->tcpStatus = CifsExiting;
666 spin_unlock(&GlobalMid_Lock);
667 wake_up_all(&server->response_q);
668
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400669 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300670 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400671 if (server->credits <= 0)
672 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300673 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400674 /*
675 * Although there should not be any requests blocked on this queue it
676 * can not hurt to be paranoid and try to wake up requests that may
677 * haven been blocked when more than 50 at time were on the wire to the
678 * same server - they now will see the session is in exit state and get
679 * out of SendReceive.
680 */
681 wake_up_all(&server->request_q);
682 /* give those requests time to exit */
683 msleep(125);
684
685 if (server->ssocket) {
686 sock_release(server->ssocket);
687 server->ssocket = NULL;
688 }
689
690 if (!list_empty(&server->pending_mid_q)) {
691 struct list_head dispose_list;
692 struct mid_q_entry *mid_entry;
693 struct list_head *tmp, *tmp2;
694
695 INIT_LIST_HEAD(&dispose_list);
696 spin_lock(&GlobalMid_Lock);
697 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
698 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500699 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400700 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400701 list_move(&mid_entry->qhead, &dispose_list);
702 }
703 spin_unlock(&GlobalMid_Lock);
704
705 /* now walk dispose list and issue callbacks */
706 list_for_each_safe(tmp, tmp2, &dispose_list) {
707 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500708 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400709 list_del_init(&mid_entry->qhead);
710 mid_entry->callback(mid_entry);
711 }
712 /* 1/8th of sec is more than enough time for them to exit */
713 msleep(125);
714 }
715
716 if (!list_empty(&server->pending_mid_q)) {
717 /*
718 * mpx threads have not exited yet give them at least the smb
719 * send timeout time for long ops.
720 *
721 * Due to delays on oplock break requests, we need to wait at
722 * least 45 seconds before giving up on a request getting a
723 * response and going ahead and killing cifsd.
724 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500725 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400726 msleep(46000);
727 /*
728 * If threads still have not exited they are probably never
729 * coming home not much else we can do but free the memory.
730 */
731 }
732
733 kfree(server->hostname);
734 kfree(server);
735
736 length = atomic_dec_return(&tcpSesAllocCount);
737 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700738 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400739}
740
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400741static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400742standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
743{
744 int length;
745 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400746 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400747
748 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400749 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500750 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400751 cifs_reconnect(server);
752 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400753 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400754 }
755
756 /* switch to large buffer if too big for a small one */
757 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
758 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400759 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400760 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400761 }
762
763 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400764 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
765 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400766 if (length < 0)
767 return length;
768 server->total_read += length;
769
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400770 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400771
772 /*
773 * We know that we received enough to get to the MID as we
774 * checked the pdu_length earlier. Now check to see
775 * if the rest of the header is OK. We borrow the length
776 * var for the rest of the loop to avoid a new stack var.
777 *
778 * 48 bytes is enough to display the header and a little bit
779 * into the payload for debugging purposes.
780 */
Steve French373512e2015-12-18 13:05:30 -0600781 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400782 if (length != 0)
783 cifs_dump_mem("Bad SMB: ", buf,
784 min_t(unsigned int, server->total_read, 48));
785
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700786 if (server->ops->is_status_pending &&
787 server->ops->is_status_pending(buf, server, length))
788 return -1;
789
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500790 if (!mid)
791 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400792
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400793 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500794 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400795}
796
797static int
Al Viro7c97c202011-06-21 08:51:28 -0400798cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799{
800 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400801 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400802 unsigned int pdu_length;
803 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500804 struct task_struct *task_to_wake = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500808 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400809
810 length = atomic_inc_return(&tcpSesAllocCount);
811 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700812 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700814 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000815 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700816 if (try_to_freeze())
817 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700818
Jeff Layton2a37ef92011-10-19 15:29:23 -0400819 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400820 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700821
Jeff Layton2a37ef92011-10-19 15:29:23 -0400822 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400823 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000824 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000825
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400826 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400827 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000828 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400829 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700830
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400831 /*
832 * The right amount was read from socket - 4 bytes,
833 * so we can now interpret the length field.
834 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400835 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700836
Joe Perchesf96637b2013-05-04 22:12:25 -0500837 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400838 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000839 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700840
Jeff Layton89482a52011-10-19 15:28:57 -0400841 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400842 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500843 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
844 pdu_length);
Jeff Layton89482a52011-10-19 15:28:57 -0400845 cifs_reconnect(server);
846 wake_up(&server->response_q);
847 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700848 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400849
Jeff Layton89482a52011-10-19 15:28:57 -0400850 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400851 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400852 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -0400853 if (length < 0)
854 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400855 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400856
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400857 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400858
Jeff Layton44d22d82011-10-19 15:29:49 -0400859 if (!mid_entry || !mid_entry->receive)
860 length = standard_receive3(server, mid_entry);
861 else
862 length = mid_entry->receive(server, mid_entry);
863
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400864 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700865 continue;
866
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400867 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400868 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700869
Steve Frenchfda35942011-01-20 18:06:34 +0000870 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500871 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -0400872 if (!mid_entry->multiRsp || mid_entry->multiEnd)
873 mid_entry->callback(mid_entry);
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400874 } else if (!server->ops->is_oplock_break ||
875 !server->ops->is_oplock_break(buf, server)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500876 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
877 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400878 cifs_dump_mem("Received Data is: ", buf,
879 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000880#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400881 if (server->ops->dump_detail)
882 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +0000883 cifs_dump_mids(server);
884#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000885
Steve Frenche4eb2952005-04-28 22:41:09 -0700886 }
887 } /* end while !EXITING */
888
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800889 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400890 cifs_buf_release(server->bigbuf);
891 if (server->smallbuf) /* no sense logging a debug message if NULL */
892 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500894 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400895 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500896
897 /* if server->tsk was NULL then wait for a signal before exiting */
898 if (!task_to_wake) {
899 set_current_state(TASK_INTERRUPTIBLE);
900 while (!signal_pending(current)) {
901 schedule();
902 set_current_state(TASK_INTERRUPTIBLE);
903 }
904 set_current_state(TASK_RUNNING);
905 }
906
Jeff Layton0468a2c2008-12-01 07:09:35 -0500907 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908}
909
Jeff Laytonc359cf32007-11-16 22:22:06 +0000910/* extract the host portion of the UNC string */
911static char *
912extract_hostname(const char *unc)
913{
914 const char *src;
915 char *dst, *delim;
916 unsigned int len;
917
918 /* skip double chars at beginning of string */
919 /* BB: check validity of these bytes? */
920 src = unc + 2;
921
922 /* delimiter between hostname and sharename is always '\\' now */
923 delim = strchr(src, '\\');
924 if (!delim)
925 return ERR_PTR(-EINVAL);
926
927 len = delim - src;
928 dst = kmalloc((len + 1), GFP_KERNEL);
929 if (dst == NULL)
930 return ERR_PTR(-ENOMEM);
931
932 memcpy(dst, src, len);
933 dst[len] = '\0';
934
935 return dst;
936}
937
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400938static int get_option_ul(substring_t args[], unsigned long *option)
939{
940 int rc;
941 char *string;
942
943 string = match_strdup(args);
944 if (string == NULL)
945 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +0100946 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400947 kfree(string);
948
949 return rc;
950}
951
Eric W. Biederman3da46562013-02-06 01:37:39 -0800952static int get_option_uid(substring_t args[], kuid_t *result)
953{
954 unsigned long value;
955 kuid_t uid;
956 int rc;
957
958 rc = get_option_ul(args, &value);
959 if (rc)
960 return rc;
961
962 uid = make_kuid(current_user_ns(), value);
963 if (!uid_valid(uid))
964 return -EINVAL;
965
966 *result = uid;
967 return 0;
968}
969
970static int get_option_gid(substring_t args[], kgid_t *result)
971{
972 unsigned long value;
973 kgid_t gid;
974 int rc;
975
976 rc = get_option_ul(args, &value);
977 if (rc)
978 return rc;
979
980 gid = make_kgid(current_user_ns(), value);
981 if (!gid_valid(gid))
982 return -EINVAL;
983
984 *result = gid;
985 return 0;
986}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400987
988static int cifs_parse_security_flavors(char *value,
989 struct smb_vol *vol)
990{
991
992 substring_t args[MAX_OPT_ARGS];
993
Jeff Layton1e3cc572013-06-10 17:12:23 -0500994 /*
995 * With mount options, the last one should win. Reset any existing
996 * settings back to default.
997 */
998 vol->sectype = Unspecified;
999 vol->sign = false;
1000
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001001 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001002 case Opt_sec_krb5p:
1003 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1004 return 1;
1005 case Opt_sec_krb5i:
1006 vol->sign = true;
1007 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001008 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001009 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001010 break;
1011 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001012 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001013 /* Fallthrough */
1014 case Opt_sec_ntlmssp:
1015 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001016 break;
1017 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001018 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001019 /* Fallthrough */
1020 case Opt_ntlm:
1021 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001022 break;
1023 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001024 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001025 /* Fallthrough */
1026 case Opt_sec_ntlmv2:
1027 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001028 break;
1029#ifdef CONFIG_CIFS_WEAK_PW_HASH
1030 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001031 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001032 break;
1033#endif
1034 case Opt_sec_none:
1035 vol->nullauth = 1;
1036 break;
1037 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001038 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001039 return 1;
1040 }
1041
1042 return 0;
1043}
1044
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001046cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1047{
1048 substring_t args[MAX_OPT_ARGS];
1049
1050 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1051 case Opt_cache_loose:
1052 vol->direct_io = false;
1053 vol->strict_io = false;
1054 break;
1055 case Opt_cache_strict:
1056 vol->direct_io = false;
1057 vol->strict_io = true;
1058 break;
1059 case Opt_cache_none:
1060 vol->direct_io = true;
1061 vol->strict_io = false;
1062 break;
1063 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001064 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001065 return 1;
1066 }
1067 return 0;
1068}
1069
1070static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001071cifs_parse_smb_version(char *value, struct smb_vol *vol)
1072{
1073 substring_t args[MAX_OPT_ARGS];
1074
1075 switch (match_token(value, cifs_smb_version_tokens, args)) {
1076 case Smb_1:
1077 vol->ops = &smb1_operations;
1078 vol->vals = &smb1_values;
1079 break;
Steve French1080ef72011-02-24 18:07:19 +00001080#ifdef CONFIG_CIFS_SMB2
Steve Frenchdd446b12012-11-28 23:21:06 -06001081 case Smb_20:
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001082 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001083 vol->vals = &smb20_values;
1084 break;
Steve French1080ef72011-02-24 18:07:19 +00001085 case Smb_21:
1086 vol->ops = &smb21_operations;
1087 vol->vals = &smb21_values;
1088 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001089 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001090 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001091 vol->vals = &smb30_values;
1092 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001093 case Smb_302:
1094 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1095 vol->vals = &smb302_values;
1096 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001097#ifdef CONFIG_CIFS_SMB311
1098 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001099 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001100 vol->vals = &smb311_values;
1101 break;
1102#endif /* SMB311 */
Steve French1080ef72011-02-24 18:07:19 +00001103#endif
Jeff Layton23db65f2012-05-15 12:20:51 -04001104 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001105 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001106 return 1;
1107 }
1108 return 0;
1109}
1110
Jeff Laytond387a5c2012-12-10 06:10:46 -05001111/*
1112 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1113 * fields with the result. Returns 0 on success and an error otherwise.
1114 */
1115static int
1116cifs_parse_devname(const char *devname, struct smb_vol *vol)
1117{
1118 char *pos;
1119 const char *delims = "/\\";
1120 size_t len;
1121
1122 /* make sure we have a valid UNC double delimiter prefix */
1123 len = strspn(devname, delims);
1124 if (len != 2)
1125 return -EINVAL;
1126
1127 /* find delimiter between host and sharename */
1128 pos = strpbrk(devname + 2, delims);
1129 if (!pos)
1130 return -EINVAL;
1131
1132 /* skip past delimiter */
1133 ++pos;
1134
1135 /* now go until next delimiter or end of string */
1136 len = strcspn(pos, delims);
1137
1138 /* move "pos" up to delimiter or NULL */
1139 pos += len;
1140 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1141 if (!vol->UNC)
1142 return -ENOMEM;
1143
1144 convert_delimiter(vol->UNC, '\\');
1145
Sachin Prabhu11e31642016-02-08 13:44:01 +05301146 /* skip any delimiter */
1147 if (*pos == '/' || *pos == '\\')
1148 pos++;
1149
1150 /* If pos is NULL then no prepath */
1151 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001152 return 0;
1153
1154 vol->prepath = kstrdup(pos, GFP_KERNEL);
1155 if (!vol->prepath)
1156 return -ENOMEM;
1157
1158 return 0;
1159}
1160
Jeff Layton23db65f2012-05-15 12:20:51 -04001161static int
Sean Finneyb9468452011-04-11 13:19:32 +00001162cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001163 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001165 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001166 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 unsigned int temp_len, i, j;
1168 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001169 short int override_uid = -1;
1170 short int override_gid = -1;
1171 bool uid_specified = false;
1172 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001173 bool sloppy = false;
1174 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001175 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001176 char *string = NULL;
1177 char *tmp_end, *value;
1178 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001179 bool got_ip = false;
1180 unsigned short port = 0;
1181 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
1183 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001184 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001185 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
Jeff Layton6ee95422012-11-26 11:09:57 -05001187 /* ensure we always start with zeroed-out smb_vol */
1188 memset(vol, 0, sizeof(*vol));
1189
Jeff Layton88463992010-11-22 15:31:03 -05001190 /*
1191 * does not have to be perfect mapping since field is
1192 * informational, only used for servers that do not support
1193 * port 445 and it can be overridden at mount time
1194 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001195 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1196 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001197 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1198
Jeff Layton1397f2e2011-01-07 11:30:28 -05001199 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001200 /* null target name indicates to use *SMBSERVR default called name
1201 if we end up sending RFC1001 session initialize */
1202 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001203 vol->cred_uid = current_uid();
1204 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001205 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001206
Steve French2baa2682014-09-27 02:19:01 -05001207 /*
1208 * default to SFM style remapping of seven reserved characters
1209 * unless user overrides it or we negotiate CIFS POSIX where
1210 * it is unnecessary. Can not simultaneously use more than one mapping
1211 * since then readdir could list files that open could not open
1212 */
1213 vol->remap = true;
1214
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001215 /* default to only allowing write access to owner of the mount */
1216 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
1218 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001219 /* default is always to request posix paths. */
1220 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001221 /* default to using server inode numbers where available */
1222 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001223
Jeff Layton1b359202012-09-19 15:20:27 -07001224 /* default is to use strict cifs caching semantics */
1225 vol->strict_io = true;
1226
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301227 vol->actimeo = CIFS_DEF_ACTIMEO;
1228
Jeff Layton23db65f2012-05-15 12:20:51 -04001229 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1230 vol->ops = &smb1_operations;
1231 vol->vals = &smb1_values;
1232
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001233 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1234
Sean Finneyb9468452011-04-11 13:19:32 +00001235 if (!mountdata)
1236 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Sean Finneyb9468452011-04-11 13:19:32 +00001238 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1239 if (!mountdata_copy)
1240 goto cifs_parse_mount_err;
1241
1242 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001243 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001244
Steve French50c2f752007-07-13 00:33:32 +00001245 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001246 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 separator[0] = options[4];
1248 options += 5;
1249 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001250 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 }
1252 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001253 vol->backupuid_specified = false; /* no backup intent for a user */
1254 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001255
Jeff Layton37d4f992013-05-24 07:40:05 -04001256 switch (cifs_parse_devname(devname, vol)) {
1257 case 0:
1258 break;
1259 case -ENOMEM:
1260 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1261 goto cifs_parse_mount_err;
1262 case -EINVAL:
1263 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1264 goto cifs_parse_mount_err;
1265 default:
1266 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1267 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001268 }
1269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001271 substring_t args[MAX_OPT_ARGS];
1272 unsigned long option;
1273 int token;
1274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 if (!*data)
1276 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001278 token = match_token(data, cifs_mount_option_tokens, args);
1279
1280 switch (token) {
1281
1282 /* Ingnore the following */
1283 case Opt_ignore:
1284 break;
1285
1286 /* Boolean values */
1287 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001289 break;
1290 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001292 break;
1293 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001294 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001295 break;
1296 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001297 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001298 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001299 case Opt_forcegid:
1300 override_gid = 1;
1301 break;
1302 case Opt_noforcegid:
1303 override_gid = 0;
1304 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001305 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001306 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001307 break;
1308 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001309 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001310 break;
1311 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001313 break;
1314 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001316 break;
1317 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001319 break;
1320 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001322 break;
1323 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001324 vol->sfu_remap = true;
1325 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001326 break;
1327 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001328 vol->sfu_remap = false;
1329 break;
1330 case Opt_mapposix:
1331 vol->remap = true;
1332 vol->sfu_remap = false; /* disable SFU mapping */
1333 break;
1334 case Opt_nomapposix:
1335 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001336 break;
1337 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001338 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001339 break;
1340 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001341 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001342 break;
1343 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001344 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001345 break;
1346 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001347 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001348 break;
1349 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001350 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001351 break;
1352 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001353 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001354 break;
1355 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001356 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001357 break;
1358 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001359 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001360 break;
1361 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001362 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001363 /*
1364 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001365 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001366 * local vfs will do advisory
1367 */
Steve French50c2f752007-07-13 00:33:32 +00001368 if (vol->file_mode ==
1369 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001370 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371 break;
1372 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001373 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001374 break;
1375 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001377 break;
1378 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
Steve French95932652016-09-23 01:36:34 -05001381 case Opt_setuidfromacl:
1382 vol->setuidfromacl = 1;
1383 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001384 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001385 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001388 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
1390 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 break;
1393 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001395 break;
1396 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001398 break;
1399 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001401 break;
1402 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001403 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001404 break;
1405 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001406 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001407 break;
1408 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001410 break;
1411 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001413 break;
1414 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001415 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001416 break;
1417 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001418 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001419 break;
1420 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001421 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001422 break;
1423 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001425 break;
1426 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001428 break;
1429 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001430 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001431 break;
1432 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001433 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001434 break;
1435 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001436 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001437 * is a per tree connection (mount) not a per socket
1438 * or per-smb connection option in the protocol
1439 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1440 */
Steve French95b1cb92008-05-15 16:44:38 +00001441 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001443 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001444 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301447#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001448 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001449 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301450#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301451 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001452 break;
1453 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001454 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001455 break;
1456 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001457 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001458 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001459 case Opt_sloppy:
1460 sloppy = true;
1461 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001462 case Opt_nosharesock:
1463 vol->nosharesock = true;
1464 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001465 case Opt_nopersistent:
1466 vol->nopersistent = true;
1467 if (vol->persistent) {
1468 cifs_dbg(VFS,
1469 "persistenthandles mount options conflict\n");
1470 goto cifs_parse_mount_err;
1471 }
1472 break;
1473 case Opt_persistent:
1474 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001475 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001476 cifs_dbg(VFS,
1477 "persistenthandles mount options conflict\n");
1478 goto cifs_parse_mount_err;
1479 }
1480 break;
Steve French592fafe2015-11-03 10:08:53 -06001481 case Opt_resilient:
1482 vol->resilient = true;
1483 if (vol->persistent) {
1484 cifs_dbg(VFS,
1485 "persistenthandles mount options conflict\n");
1486 goto cifs_parse_mount_err;
1487 }
1488 break;
1489 case Opt_noresilient:
1490 vol->resilient = false; /* already the default */
1491 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001492
1493 /* Numeric Values */
1494 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001495 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001496 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1497 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001498 goto cifs_parse_mount_err;
1499 }
1500 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001501 break;
1502 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001503 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001504 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1505 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001506 goto cifs_parse_mount_err;
1507 }
1508 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001509 break;
1510 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001511 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001512 cifs_dbg(VFS, "%s: Invalid uid value\n",
1513 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001514 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001516 uid_specified = true;
1517 break;
1518 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001519 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001520 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1521 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001522 goto cifs_parse_mount_err;
1523 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001524 break;
1525 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001526 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001527 cifs_dbg(VFS, "%s: Invalid gid value\n",
1528 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001529 goto cifs_parse_mount_err;
1530 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001531 gid_specified = true;
1532 break;
1533 case Opt_file_mode:
1534 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001535 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1536 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001537 goto cifs_parse_mount_err;
1538 }
1539 vol->file_mode = option;
1540 break;
1541 case Opt_dirmode:
1542 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001543 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1544 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001545 goto cifs_parse_mount_err;
1546 }
1547 vol->dir_mode = option;
1548 break;
1549 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001550 if (get_option_ul(args, &option) ||
1551 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001552 cifs_dbg(VFS, "%s: Invalid port value\n",
1553 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001554 goto cifs_parse_mount_err;
1555 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001556 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001557 break;
1558 case Opt_rsize:
1559 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001560 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1561 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001562 goto cifs_parse_mount_err;
1563 }
1564 vol->rsize = option;
1565 break;
1566 case Opt_wsize:
1567 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001568 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1569 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001570 goto cifs_parse_mount_err;
1571 }
1572 vol->wsize = option;
1573 break;
1574 case Opt_actimeo:
1575 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001576 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1577 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001578 goto cifs_parse_mount_err;
1579 }
1580 vol->actimeo = HZ * option;
1581 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001582 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001583 goto cifs_parse_mount_err;
1584 }
1585 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06001586 case Opt_echo_interval:
1587 if (get_option_ul(args, &option)) {
1588 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
1589 __func__);
1590 goto cifs_parse_mount_err;
1591 }
1592 vol->echo_interval = option;
1593 break;
Steve French141891f2016-09-23 00:44:16 -05001594 case Opt_max_credits:
1595 if (get_option_ul(args, &option) || (option < 20) ||
1596 (option > 60000)) {
1597 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
1598 __func__);
1599 goto cifs_parse_mount_err;
1600 }
1601 vol->max_credits = option;
1602 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001603
1604 /* String Arguments */
1605
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001606 case Opt_blank_user:
1607 /* null user, ie. anonymous authentication */
1608 vol->nullauth = 1;
1609 vol->username = NULL;
1610 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001611 case Opt_user:
1612 string = match_strdup(args);
1613 if (string == NULL)
1614 goto out_nomem;
1615
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001616 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1617 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001618 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001619 goto cifs_parse_mount_err;
1620 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001621
1622 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001623 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001624 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001625 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001626 break;
1627 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001628 /* passwords have to be handled differently
1629 * to allow the character used for deliminator
1630 * to be passed within them
1631 */
1632
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001633 /*
1634 * Check if this is a case where the password
1635 * starts with a delimiter
1636 */
1637 tmp_end = strchr(data, '=');
1638 tmp_end++;
1639 if (!(tmp_end < end && tmp_end[1] == delim)) {
1640 /* No it is not. Set the password to NULL */
Namjae Jeond6ccf492014-08-21 19:11:20 +09001641 kfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001642 vol->password = NULL;
1643 break;
1644 }
1645 /* Yes it is. Drop down to Opt_pass below.*/
1646 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001647 /* Obtain the value string */
1648 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001649 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001650
1651 /* Set tmp_end to end of the string */
1652 tmp_end = (char *) value + strlen(value);
1653
1654 /* Check if following character is the deliminator
1655 * If yes, we have encountered a double deliminator
1656 * reset the NULL character to the deliminator
1657 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301658 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001659 tmp_end[0] = delim;
1660
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301661 /* Keep iterating until we get to a single
1662 * deliminator OR the end
1663 */
1664 while ((tmp_end = strchr(tmp_end, delim))
1665 != NULL && (tmp_end[1] == delim)) {
1666 tmp_end = (char *) &tmp_end[2];
1667 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001668
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301669 /* Reset var options to point to next element */
1670 if (tmp_end) {
1671 tmp_end[0] = '\0';
1672 options = (char *) &tmp_end[1];
1673 } else
1674 /* Reached the end of the mount option
1675 * string */
1676 options = end;
1677 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001678
Namjae Jeond6ccf492014-08-21 19:11:20 +09001679 kfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001680 /* Now build new password string */
1681 temp_len = strlen(value);
1682 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1683 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001684 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001685 goto cifs_parse_mount_err;
1686 }
1687
1688 for (i = 0, j = 0; i < temp_len; i++, j++) {
1689 vol->password[j] = value[i];
1690 if ((value[i] == delim) &&
1691 value[i+1] == delim)
1692 /* skip the second deliminator */
1693 i++;
1694 }
1695 vol->password[j] = '\0';
1696 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001697 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001698 /* FIXME: should this be an error instead? */
1699 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001700 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001701 case Opt_ip:
1702 string = match_strdup(args);
1703 if (string == NULL)
1704 goto out_nomem;
1705
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001706 if (!cifs_convert_address(dstaddr, string,
1707 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001708 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001709 goto cifs_parse_mount_err;
1710 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001711 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001712 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001713 case Opt_domain:
1714 string = match_strdup(args);
1715 if (string == NULL)
1716 goto out_nomem;
1717
Chen Gang057d6332013-07-19 09:01:36 +08001718 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
1719 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001720 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001721 goto cifs_parse_mount_err;
1722 }
1723
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001724 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001725 vol->domainname = kstrdup(string, GFP_KERNEL);
1726 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001727 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001728 goto cifs_parse_mount_err;
1729 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001730 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001731 break;
1732 case Opt_srcaddr:
1733 string = match_strdup(args);
1734 if (string == NULL)
1735 goto out_nomem;
1736
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001737 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001738 (struct sockaddr *)&vol->srcaddr,
1739 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001740 pr_warn("CIFS: Could not parse srcaddr: %s\n",
1741 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001742 goto cifs_parse_mount_err;
1743 }
1744 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 case Opt_iocharset:
1746 string = match_strdup(args);
1747 if (string == NULL)
1748 goto out_nomem;
1749
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001750 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001751 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001752 goto cifs_parse_mount_err;
1753 }
1754
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001755 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001756 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001757 vol->iocharset = kstrdup(string,
1758 GFP_KERNEL);
1759 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001760 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001761 goto cifs_parse_mount_err;
1762 }
1763 }
1764 /* if iocharset not set then load_nls_default
1765 * is used by caller
1766 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001767 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001768 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001769 case Opt_netbiosname:
1770 string = match_strdup(args);
1771 if (string == NULL)
1772 goto out_nomem;
1773
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001774 memset(vol->source_rfc1001_name, 0x20,
1775 RFC1001_NAME_LEN);
1776 /*
1777 * FIXME: are there cases in which a comma can
1778 * be valid in workstation netbios name (and
1779 * need special handling)?
1780 */
1781 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1782 /* don't ucase netbiosname for user */
1783 if (string[i] == 0)
1784 break;
1785 vol->source_rfc1001_name[i] = string[i];
1786 }
1787 /* The string has 16th byte zero still from
1788 * set at top of the function
1789 */
1790 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001791 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 break;
1793 case Opt_servern:
1794 /* servernetbiosname specified override *SMBSERVER */
1795 string = match_strdup(args);
1796 if (string == NULL)
1797 goto out_nomem;
1798
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001799 /* last byte, type, is 0x20 for servr type */
1800 memset(vol->target_rfc1001_name, 0x20,
1801 RFC1001_NAME_LEN_WITH_NULL);
1802
1803 /* BB are there cases in which a comma can be
1804 valid in this workstation netbios name
1805 (and need special handling)? */
1806
1807 /* user or mount helper must uppercase the
1808 netbios name */
1809 for (i = 0; i < 15; i++) {
1810 if (string[i] == 0)
1811 break;
1812 vol->target_rfc1001_name[i] = string[i];
1813 }
1814 /* The string has 16th byte zero still from
1815 set at top of the function */
1816 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001817 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001818 break;
1819 case Opt_ver:
1820 string = match_strdup(args);
1821 if (string == NULL)
1822 goto out_nomem;
1823
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001824 if (strncasecmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001825 /* This is the default */
1826 break;
1827 }
1828 /* For all other value, error */
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001829 pr_warn("CIFS: Invalid version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001830 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001831 case Opt_vers:
1832 string = match_strdup(args);
1833 if (string == NULL)
1834 goto out_nomem;
1835
1836 if (cifs_parse_smb_version(string, vol) != 0)
1837 goto cifs_parse_mount_err;
1838 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001839 case Opt_sec:
1840 string = match_strdup(args);
1841 if (string == NULL)
1842 goto out_nomem;
1843
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001844 if (cifs_parse_security_flavors(string, vol) != 0)
1845 goto cifs_parse_mount_err;
1846 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001847 case Opt_cache:
1848 string = match_strdup(args);
1849 if (string == NULL)
1850 goto out_nomem;
1851
1852 if (cifs_parse_cache_flavor(string, vol) != 0)
1853 goto cifs_parse_mount_err;
1854 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001855 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001856 /*
1857 * An option we don't recognize. Save it off for later
1858 * if we haven't already found one
1859 */
1860 if (!invalid)
1861 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001862 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001864 /* Free up any allocated string */
1865 kfree(string);
1866 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001868
Jeff Laytond8162552012-03-23 14:40:56 -04001869 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001870 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04001871 goto cifs_parse_mount_err;
1872 }
1873
Jeff Layton8a8798a2012-01-17 16:09:15 -05001874#ifndef CONFIG_KEYS
1875 /* Muliuser mounts require CONFIG_KEYS support */
1876 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001877 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001878 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001879 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001880#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001881 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04001882 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001883 goto cifs_parse_mount_err;
1884 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001885
Jeff Layton62a1a432012-12-10 06:10:45 -05001886 /* make sure UNC has a share name */
1887 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001888 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05001889 goto cifs_parse_mount_err;
1890 }
1891
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001892 if (!got_ip) {
1893 /* No ip= option specified? Try to get it from UNC */
1894 if (!cifs_convert_address(dstaddr, &vol->UNC[2],
1895 strlen(&vol->UNC[2]))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001896 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001897 goto cifs_parse_mount_err;
1898 }
1899 }
1900
1901 /* set the port that we got earlier */
1902 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001904 if (uid_specified)
1905 vol->override_uid = override_uid;
1906 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001907 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001908
1909 if (gid_specified)
1910 vol->override_gid = override_gid;
1911 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001912 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001913
Sean Finneyb9468452011-04-11 13:19:32 +00001914 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001916
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001917out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001918 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001919cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001920 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001921 kfree(mountdata_copy);
1922 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923}
1924
Ben Greear3eb9a882010-09-01 17:06:02 -07001925/** Returns true if srcaddr isn't specified and rhs isn't
1926 * specified, or if srcaddr is specified and
1927 * matches the IP address of the rhs argument.
1928 */
Jeff Layton45151482010-07-06 20:43:02 -04001929static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001930srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1931{
1932 switch (srcaddr->sa_family) {
1933 case AF_UNSPEC:
1934 return (rhs->sa_family == AF_UNSPEC);
1935 case AF_INET: {
1936 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1937 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1938 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1939 }
1940 case AF_INET6: {
1941 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05001942 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07001943 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1944 }
1945 default:
1946 WARN_ON(1);
1947 return false; /* don't expect to be here */
1948 }
1949}
1950
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001951/*
1952 * If no port is specified in addr structure, we try to match with 445 port
1953 * and if it fails - with 139 ports. It should be called only if address
1954 * families of server and addr are equal.
1955 */
1956static bool
1957match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1958{
Steve French6da97912011-03-13 18:55:55 +00001959 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001960
1961 switch (addr->sa_family) {
1962 case AF_INET:
1963 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1964 port = ((struct sockaddr_in *) addr)->sin_port;
1965 break;
1966 case AF_INET6:
1967 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1968 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1969 break;
1970 default:
1971 WARN_ON(1);
1972 return false;
1973 }
1974
1975 if (!port) {
1976 port = htons(CIFS_PORT);
1977 if (port == *sport)
1978 return true;
1979
1980 port = htons(RFC1001_PORT);
1981 }
1982
1983 return port == *sport;
1984}
Ben Greear3eb9a882010-09-01 17:06:02 -07001985
1986static bool
1987match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
1988 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989{
Jeff Layton45151482010-07-06 20:43:02 -04001990 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001991 case AF_INET: {
1992 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1993 struct sockaddr_in *srv_addr4 =
1994 (struct sockaddr_in *)&server->dstaddr;
1995
1996 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04001997 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001998 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001999 }
2000 case AF_INET6: {
2001 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2002 struct sockaddr_in6 *srv_addr6 =
2003 (struct sockaddr_in6 *)&server->dstaddr;
2004
Jeff Layton45151482010-07-06 20:43:02 -04002005 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002006 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002007 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002008 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002009 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002010 break;
2011 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002012 default:
2013 WARN_ON(1);
2014 return false; /* don't expect to be here */
2015 }
Jeff Layton45151482010-07-06 20:43:02 -04002016
Ben Greear3eb9a882010-09-01 17:06:02 -07002017 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2018 return false;
2019
Jeff Layton45151482010-07-06 20:43:02 -04002020 return true;
2021}
2022
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002023static bool
2024match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2025{
Jeff Layton3f618222013-06-12 19:52:14 -05002026 /*
2027 * The select_sectype function should either return the vol->sectype
2028 * that was specified, or "Unspecified" if that sectype was not
2029 * compatible with the given NEGOTIATE request.
2030 */
2031 if (select_sectype(server, vol->sectype) == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002032 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002033
Jeff Layton3f618222013-06-12 19:52:14 -05002034 /*
2035 * Now check if signing mode is acceptable. No need to check
2036 * global_secflags at this point since if MUST_SIGN is set then
2037 * the server->sign had better be too.
2038 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002039 if (vol->sign && !server->sign)
2040 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002041
2042 return true;
2043}
2044
Jeff Layton9fa114f2012-11-26 11:09:57 -05002045static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002046{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002047 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2048
Jeff Laytona0b3df52013-05-24 07:40:59 -04002049 if (vol->nosharesock)
2050 return 0;
2051
Jeff Layton23db65f2012-05-15 12:20:51 -04002052 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2053 return 0;
2054
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002055 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2056 return 0;
2057
2058 if (!match_address(server, addr,
2059 (struct sockaddr *)&vol->srcaddr))
2060 return 0;
2061
2062 if (!match_port(server, addr))
2063 return 0;
2064
2065 if (!match_security(server, vol))
2066 return 0;
2067
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002068 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002069 return 0;
2070
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002071 return 1;
2072}
2073
Jeff Layton45151482010-07-06 20:43:02 -04002074static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002075cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002076{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002077 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302079 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002080 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002081 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002082 continue;
2083
Jeff Laytone7ddee92008-11-14 13:44:38 -05002084 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302085 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002086 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002087 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302089 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 return NULL;
2091}
2092
Jeff Layton14fbf502008-11-14 13:53:46 -05002093static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002094cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002096 struct task_struct *task;
2097
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302098 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002099 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302100 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002101 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002103
Rob Landleyf1d0c992011-01-22 15:44:05 -06002104 put_net(cifs_net_ns(server));
2105
Jeff Laytone7ddee92008-11-14 13:44:38 -05002106 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302107 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002108
Jeff Laytonc74093b2011-01-11 07:24:23 -05002109 cancel_delayed_work_sync(&server->echo);
2110
Jeff Laytone7ddee92008-11-14 13:44:38 -05002111 spin_lock(&GlobalMid_Lock);
2112 server->tcpStatus = CifsExiting;
2113 spin_unlock(&GlobalMid_Lock);
2114
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002115 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302116 cifs_fscache_release_client_cookie(server);
2117
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002118 kfree(server->session_key.response);
2119 server->session_key.response = NULL;
2120 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002121
2122 task = xchg(&server->tsk, NULL);
2123 if (task)
2124 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125}
2126
Jeff Layton63c038c2008-12-01 18:41:46 -05002127static struct TCP_Server_Info *
2128cifs_get_tcp_session(struct smb_vol *volume_info)
2129{
2130 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002131 int rc;
2132
Joe Perchesf96637b2013-05-04 22:12:25 -05002133 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002134
2135 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002136 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002137 if (tcp_ses)
2138 return tcp_ses;
2139
2140 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2141 if (!tcp_ses) {
2142 rc = -ENOMEM;
2143 goto out_err;
2144 }
2145
Jeff Layton23db65f2012-05-15 12:20:51 -04002146 tcp_ses->ops = volume_info->ops;
2147 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002148 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002149 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2150 if (IS_ERR(tcp_ses->hostname)) {
2151 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002152 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002153 }
2154
2155 tcp_ses->noblocksnd = volume_info->noblocksnd;
2156 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002157 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002158 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002159 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002160 init_waitqueue_head(&tcp_ses->response_q);
2161 init_waitqueue_head(&tcp_ses->request_q);
2162 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2163 mutex_init(&tcp_ses->srv_mutex);
2164 memcpy(tcp_ses->workstation_RFC1001_name,
2165 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2166 memcpy(tcp_ses->server_RFC1001_name,
2167 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002168 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002169 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002170 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002171 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002172 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2173 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002174 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002175 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2176 sizeof(tcp_ses->srcaddr));
2177 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2178 sizeof(tcp_ses->dstaddr));
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002179#ifdef CONFIG_CIFS_SMB2
Steve Frenchfa70b872016-09-22 00:39:34 -05002180 generate_random_uuid(tcp_ses->client_guid);
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002181#endif
Jeff Layton63c038c2008-12-01 18:41:46 -05002182 /*
2183 * at this point we are the only ones with the pointer
2184 * to the struct since the kernel thread not created yet
2185 * no need to spinlock this init of tcpStatus or srv_count
2186 */
2187 tcp_ses->tcpStatus = CifsNew;
2188 ++tcp_ses->srv_count;
2189
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002190 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2191 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2192 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2193 else
2194 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
2195
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002196 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002197 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002198 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002199 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002200 }
2201
2202 /*
2203 * since we're in a cifs function already, we know that
2204 * this will succeed. No need for try_module_get().
2205 */
2206 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002207 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002208 tcp_ses, "cifsd");
2209 if (IS_ERR(tcp_ses->tsk)) {
2210 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002211 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002212 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002213 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002214 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002215 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002216
2217 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302218 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002219 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302220 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002221
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302222 cifs_fscache_get_client_cookie(tcp_ses);
2223
Jeff Laytonc74093b2011-01-11 07:24:23 -05002224 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002225 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002226
Jeff Layton63c038c2008-12-01 18:41:46 -05002227 return tcp_ses;
2228
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002229out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002230 cifs_crypto_shash_release(tcp_ses);
2231
Rob Landleyf1d0c992011-01-22 15:44:05 -06002232 put_net(cifs_net_ns(tcp_ses));
2233
Jeff Layton63c038c2008-12-01 18:41:46 -05002234out_err:
2235 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002236 if (!IS_ERR(tcp_ses->hostname))
2237 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002238 if (tcp_ses->ssocket)
2239 sock_release(tcp_ses->ssocket);
2240 kfree(tcp_ses);
2241 }
2242 return ERR_PTR(rc);
2243}
2244
Steve French96daf2b2011-05-27 04:34:02 +00002245static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002246{
Jeff Layton3f618222013-06-12 19:52:14 -05002247 if (vol->sectype != Unspecified &&
2248 vol->sectype != ses->sectype)
2249 return 0;
2250
2251 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002252 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002253 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002254 return 0;
2255 break;
2256 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002257 /* NULL username means anonymous session */
2258 if (ses->user_name == NULL) {
2259 if (!vol->nullauth)
2260 return 0;
2261 break;
2262 }
2263
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002264 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002265 if (strncmp(ses->user_name,
2266 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002267 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002268 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002269 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002270 ses->password != NULL &&
2271 strncmp(ses->password,
2272 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002273 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002274 return 0;
2275 }
2276 return 1;
2277}
2278
Steve French96daf2b2011-05-27 04:34:02 +00002279static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002280cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281{
Steve French96daf2b2011-05-27 04:34:02 +00002282 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302284 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002285 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002286 if (ses->status == CifsExiting)
2287 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002288 if (!match_session(ses, vol))
2289 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002290 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302291 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002292 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302294 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 return NULL;
2296}
2297
Jeff Layton14fbf502008-11-14 13:53:46 -05002298static void
Steve French96daf2b2011-05-27 04:34:02 +00002299cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002300{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002301 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002302 struct TCP_Server_Info *server = ses->server;
2303
Joe Perchesf96637b2013-05-04 22:12:25 -05002304 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002305
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302306 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002307 if (ses->status == CifsExiting) {
2308 spin_unlock(&cifs_tcp_ses_lock);
2309 return;
2310 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002311 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302312 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002313 return;
2314 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002315 if (ses->status == CifsGood)
2316 ses->status = CifsExiting;
2317 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002318
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002319 if (ses->status == CifsExiting && server->ops->logoff) {
2320 xid = get_xid();
2321 rc = server->ops->logoff(xid, ses);
2322 if (rc)
2323 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2324 __func__, rc);
2325 _free_xid(xid);
2326 }
2327
2328 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002329 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302330 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002331
Jeff Layton14fbf502008-11-14 13:53:46 -05002332 sesInfoFree(ses);
2333 cifs_put_tcp_session(server);
2334}
2335
Jeff Layton8a8798a2012-01-17 16:09:15 -05002336#ifdef CONFIG_KEYS
2337
Chen Gang057d6332013-07-19 09:01:36 +08002338/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2339#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002340
2341/* Populate username and pw fields from keyring if possible */
2342static int
2343cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2344{
2345 int rc = 0;
David Howells146aa8b2015-10-21 14:04:48 +01002346 const char *delim, *payload;
2347 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002348 ssize_t len;
2349 struct key *key;
2350 struct TCP_Server_Info *server = ses->server;
2351 struct sockaddr_in *sa;
2352 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01002353 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002354
2355 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2356 if (!desc)
2357 return -ENOMEM;
2358
2359 /* try to find an address key first */
2360 switch (server->dstaddr.ss_family) {
2361 case AF_INET:
2362 sa = (struct sockaddr_in *)&server->dstaddr;
2363 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2364 break;
2365 case AF_INET6:
2366 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2367 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2368 break;
2369 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002370 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2371 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002372 rc = -EINVAL;
2373 goto out_err;
2374 }
2375
Joe Perchesf96637b2013-05-04 22:12:25 -05002376 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002377 key = request_key(&key_type_logon, desc, "");
2378 if (IS_ERR(key)) {
2379 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002380 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002381 rc = PTR_ERR(key);
2382 goto out_err;
2383 }
2384
2385 /* didn't work, try to find a domain key */
2386 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002387 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002388 key = request_key(&key_type_logon, desc, "");
2389 if (IS_ERR(key)) {
2390 rc = PTR_ERR(key);
2391 goto out_err;
2392 }
2393 }
2394
2395 down_read(&key->sem);
David Howells146aa8b2015-10-21 14:04:48 +01002396 upayload = user_key_payload(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002397 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002398 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002399 goto out_key_put;
2400 }
2401
2402 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01002403 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002404 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002405 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002406 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002407 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2408 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002409 rc = -EINVAL;
2410 goto out_key_put;
2411 }
2412
2413 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002414 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002415 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2416 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002417 rc = -EINVAL;
2418 goto out_key_put;
2419 }
2420
2421 vol->username = kstrndup(payload, len, GFP_KERNEL);
2422 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002423 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2424 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002425 rc = -ENOMEM;
2426 goto out_key_put;
2427 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002428 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002429
2430 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002431 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002432 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002433 rc = -EINVAL;
2434 kfree(vol->username);
2435 vol->username = NULL;
2436 goto out_key_put;
2437 }
2438
2439 ++delim;
2440 vol->password = kstrndup(delim, len, GFP_KERNEL);
2441 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002442 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2443 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002444 rc = -ENOMEM;
2445 kfree(vol->username);
2446 vol->username = NULL;
2447 goto out_key_put;
2448 }
2449
2450out_key_put:
2451 up_read(&key->sem);
2452 key_put(key);
2453out_err:
2454 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002455 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002456 return rc;
2457}
2458#else /* ! CONFIG_KEYS */
2459static inline int
2460cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2461 struct cifs_ses *ses __attribute__((unused)))
2462{
2463 return -ENOSYS;
2464}
2465#endif /* CONFIG_KEYS */
2466
Steve French96daf2b2011-05-27 04:34:02 +00002467static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002468cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2469{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002470 int rc = -ENOMEM;
2471 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002472 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002473 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2474 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002475
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002476 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002477
Jeff Layton4ff67b72010-07-06 20:43:02 -04002478 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002479 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002480 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2481 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002482
Jeff Layton36988c72010-04-24 07:57:43 -04002483 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002484 rc = cifs_negotiate_protocol(xid, ses);
2485 if (rc) {
2486 mutex_unlock(&ses->session_mutex);
2487 /* problem -- put our ses reference */
2488 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002489 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002490 return ERR_PTR(rc);
2491 }
Jeff Layton36988c72010-04-24 07:57:43 -04002492 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002493 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002494 rc = cifs_setup_session(xid, ses,
2495 volume_info->local_nls);
2496 if (rc) {
2497 mutex_unlock(&ses->session_mutex);
2498 /* problem -- put our reference */
2499 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002500 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002501 return ERR_PTR(rc);
2502 }
2503 }
2504 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002505
2506 /* existing SMB ses has a server reference already */
2507 cifs_put_tcp_session(server);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002508 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002509 return ses;
2510 }
2511
Joe Perchesf96637b2013-05-04 22:12:25 -05002512 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002513 ses = sesInfoAlloc();
2514 if (ses == NULL)
2515 goto get_ses_fail;
2516
2517 /* new SMB session uses our server ref */
2518 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002519 if (server->dstaddr.ss_family == AF_INET6)
2520 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002521 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002522 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002523
Steve French8727c8a2011-02-25 01:11:56 -06002524 if (volume_info->username) {
2525 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2526 if (!ses->user_name)
2527 goto get_ses_fail;
2528 }
Jeff Layton36988c72010-04-24 07:57:43 -04002529
2530 /* volume_info->password freed at unmount */
2531 if (volume_info->password) {
2532 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2533 if (!ses->password)
2534 goto get_ses_fail;
2535 }
2536 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002537 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2538 if (!ses->domainName)
2539 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002540 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002541 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002542 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002543
Jeff Layton28e11bd2013-05-26 07:01:00 -04002544 ses->sectype = volume_info->sectype;
2545 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04002546
2547 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002548 rc = cifs_negotiate_protocol(xid, ses);
2549 if (!rc)
2550 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002551 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002552 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002553 goto get_ses_fail;
2554
2555 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302556 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002557 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302558 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002559
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002560 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002561 return ses;
2562
2563get_ses_fail:
2564 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002565 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002566 return ERR_PTR(rc);
2567}
2568
Steve French96daf2b2011-05-27 04:34:02 +00002569static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002570{
2571 if (tcon->tidStatus == CifsExiting)
2572 return 0;
2573 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2574 return 0;
2575 return 1;
2576}
2577
Steve French96daf2b2011-05-27 04:34:02 +00002578static struct cifs_tcon *
2579cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580{
2581 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002582 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302584 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002585 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002586 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002587 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002588 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002589 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302590 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 return tcon;
2592 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302593 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 return NULL;
2595}
2596
Jeff Laytonf1987b42008-11-15 11:12:47 -05002597static void
Steve French96daf2b2011-05-27 04:34:02 +00002598cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002599{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002600 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002601 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002602
Joe Perchesf96637b2013-05-04 22:12:25 -05002603 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302604 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002605 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302606 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002607 return;
2608 }
2609
2610 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302611 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002612
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002613 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002614 if (ses->server->ops->tree_disconnect)
2615 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002616 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002617
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302618 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002619 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002620 cifs_put_smb_ses(ses);
2621}
2622
Steve French96daf2b2011-05-27 04:34:02 +00002623static struct cifs_tcon *
2624cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002625{
2626 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002627 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002628
2629 tcon = cifs_find_tcon(ses, volume_info->UNC);
2630 if (tcon) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002631 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002632 /* existing tcon already has a reference */
2633 cifs_put_smb_ses(ses);
2634 if (tcon->seal != volume_info->seal)
Joe Perchesf96637b2013-05-04 22:12:25 -05002635 cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002636 return tcon;
2637 }
2638
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002639 if (!ses->server->ops->tree_connect) {
2640 rc = -ENOSYS;
2641 goto out_fail;
2642 }
2643
Jeff Laytond00c28d2010-04-24 07:57:44 -04002644 tcon = tconInfoAlloc();
2645 if (tcon == NULL) {
2646 rc = -ENOMEM;
2647 goto out_fail;
2648 }
2649
2650 tcon->ses = ses;
2651 if (volume_info->password) {
2652 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2653 if (!tcon->password) {
2654 rc = -ENOMEM;
2655 goto out_fail;
2656 }
2657 }
2658
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002659 /*
2660 * BB Do we need to wrap session_mutex around this TCon call and Unix
2661 * SetFS as we do on SessSetup and reconnect?
2662 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002663 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002664 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2665 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002666 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002667 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002668 if (rc)
2669 goto out_fail;
2670
2671 if (volume_info->nodfs) {
2672 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002673 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002674 }
2675 tcon->seal = volume_info->seal;
Steve Frenchb618f002015-11-03 09:15:03 -06002676 tcon->use_persistent = false;
2677 /* check if SMB2 or later, CIFS does not support persistent handles */
2678 if (volume_info->persistent) {
2679 if (ses->server->vals->protocol_id == 0) {
2680 cifs_dbg(VFS,
2681 "SMB3 or later required for persistent handles\n");
2682 rc = -EOPNOTSUPP;
2683 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002684#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002685 } else if (ses->server->capabilities &
2686 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2687 tcon->use_persistent = true;
2688 else /* persistent handles requested but not supported */ {
2689 cifs_dbg(VFS,
2690 "Persistent handles not supported on share\n");
2691 rc = -EOPNOTSUPP;
2692 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002693#endif /* CONFIG_CIFS_SMB2 */
Steve Frenchb618f002015-11-03 09:15:03 -06002694 }
Steve French592fafe2015-11-03 10:08:53 -06002695#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002696 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
2697 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2698 && (volume_info->nopersistent == false)) {
2699 cifs_dbg(FYI, "enabling persistent handles\n");
2700 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06002701#endif /* CONFIG_CIFS_SMB2 */
2702 } else if (volume_info->resilient) {
2703 if (ses->server->vals->protocol_id == 0) {
2704 cifs_dbg(VFS,
2705 "SMB2.1 or later required for resilient handles\n");
2706 rc = -EOPNOTSUPP;
2707 goto out_fail;
2708 }
2709 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06002710 }
2711
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002712 /*
2713 * We can have only one retry value for a connection to a share so for
2714 * resources mounted more than once to the same server share the last
2715 * value passed in for the retry flag is used.
2716 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04002717 tcon->retry = volume_info->retry;
2718 tcon->nocase = volume_info->nocase;
2719 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07002720 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002721
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302722 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002723 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302724 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002725
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302726 cifs_fscache_get_super_cookie(tcon);
2727
Jeff Laytond00c28d2010-04-24 07:57:44 -04002728 return tcon;
2729
2730out_fail:
2731 tconInfoFree(tcon);
2732 return ERR_PTR(rc);
2733}
2734
Jeff Layton9d002df2010-10-06 19:51:11 -04002735void
2736cifs_put_tlink(struct tcon_link *tlink)
2737{
2738 if (!tlink || IS_ERR(tlink))
2739 return;
2740
2741 if (!atomic_dec_and_test(&tlink->tl_count) ||
2742 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2743 tlink->tl_time = jiffies;
2744 return;
2745 }
2746
2747 if (!IS_ERR(tlink_tcon(tlink)))
2748 cifs_put_tcon(tlink_tcon(tlink));
2749 kfree(tlink);
2750 return;
2751}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002752
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002753static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002754cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2755{
2756 return cifs_sb->master_tlink;
2757}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002758
2759static int
2760compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2761{
2762 struct cifs_sb_info *old = CIFS_SB(sb);
2763 struct cifs_sb_info *new = mnt_data->cifs_sb;
2764
2765 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2766 return 0;
2767
2768 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2769 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2770 return 0;
2771
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002772 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002773 * We want to share sb only if we don't specify an r/wsize or
2774 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002775 */
2776 if (new->wsize && new->wsize < old->wsize)
2777 return 0;
2778
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002779 if (new->rsize && new->rsize < old->rsize)
2780 return 0;
2781
Eric W. Biederman1f682332013-02-06 01:20:20 -08002782 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002783 return 0;
2784
2785 if (old->mnt_file_mode != new->mnt_file_mode ||
2786 old->mnt_dir_mode != new->mnt_dir_mode)
2787 return 0;
2788
2789 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2790 return 0;
2791
2792 if (old->actimeo != new->actimeo)
2793 return 0;
2794
2795 return 1;
2796}
2797
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002798static int
2799match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2800{
2801 struct cifs_sb_info *old = CIFS_SB(sb);
2802 struct cifs_sb_info *new = mnt_data->cifs_sb;
2803
2804 if (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) {
2805 if (!(new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH))
2806 return 0;
2807 /* The prepath should be null terminated strings */
2808 if (strcmp(new->prepath, old->prepath))
2809 return 0;
2810
2811 return 1;
2812 }
2813 return 0;
2814}
2815
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002816int
2817cifs_match_super(struct super_block *sb, void *data)
2818{
2819 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2820 struct smb_vol *volume_info;
2821 struct cifs_sb_info *cifs_sb;
2822 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002823 struct cifs_ses *ses;
2824 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002825 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002826 int rc = 0;
2827
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002828 spin_lock(&cifs_tcp_ses_lock);
2829 cifs_sb = CIFS_SB(sb);
2830 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2831 if (IS_ERR(tlink)) {
2832 spin_unlock(&cifs_tcp_ses_lock);
2833 return rc;
2834 }
2835 tcon = tlink_tcon(tlink);
2836 ses = tcon->ses;
2837 tcp_srv = ses->server;
2838
2839 volume_info = mnt_data->vol;
2840
Jeff Layton9fa114f2012-11-26 11:09:57 -05002841 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002842 !match_session(ses, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01002843 !match_tcon(tcon, volume_info->UNC) ||
2844 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002845 rc = 0;
2846 goto out;
2847 }
2848
2849 rc = compare_mount_options(sb, mnt_data);
2850out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002851 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002852 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002853 return rc;
2854}
2855
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002857get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002858 const struct nls_table *nls_codepage, unsigned int *num_referrals,
2859 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
2861 char *temp_unc;
2862 int rc = 0;
2863
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002864 if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002865 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002867 *num_referrals = 0;
2868 *referrals = NULL;
2869
2870 if (ses->ipc_tid == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 temp_unc = kmalloc(2 /* for slashes */ +
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002872 strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
2873 + 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 if (temp_unc == NULL)
2875 return -ENOMEM;
2876 temp_unc[0] = '\\';
2877 temp_unc[1] = '\\';
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002878 strcpy(temp_unc + 2, ses->serverName);
2879 strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
2880 rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
2881 nls_codepage);
Joe Perchesf96637b2013-05-04 22:12:25 -05002882 cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 kfree(temp_unc);
2884 }
2885 if (rc == 0)
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002886 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
2887 referrals, num_referrals,
2888 nls_codepage, remap);
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002889 /*
2890 * BB - map targetUNCs to dfs_info3 structures, here or in
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002891 * ses->server->ops->get_dfs_refer.
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002892 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893
2894 return rc;
2895}
2896
Jeff Layton09e50d52008-07-23 10:11:19 -04002897#ifdef CONFIG_DEBUG_LOCK_ALLOC
2898static struct lock_class_key cifs_key[2];
2899static struct lock_class_key cifs_slock_key[2];
2900
2901static inline void
2902cifs_reclassify_socket4(struct socket *sock)
2903{
2904 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02002905 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04002906 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2907 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2908}
2909
2910static inline void
2911cifs_reclassify_socket6(struct socket *sock)
2912{
2913 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02002914 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04002915 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2916 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2917}
2918#else
2919static inline void
2920cifs_reclassify_socket4(struct socket *sock)
2921{
2922}
2923
2924static inline void
2925cifs_reclassify_socket6(struct socket *sock)
2926{
2927}
2928#endif
2929
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002931static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932{
Steve French50c2f752007-07-13 00:33:32 +00002933 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934
Steve French50c2f752007-07-13 00:33:32 +00002935 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 /* mask a nibble at a time and encode */
2937 target[j] = 'A' + (0x0F & (source[i] >> 4));
2938 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002939 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 }
2941
2942}
2943
Ben Greear3eb9a882010-09-01 17:06:02 -07002944static int
2945bind_socket(struct TCP_Server_Info *server)
2946{
2947 int rc = 0;
2948 if (server->srcaddr.ss_family != AF_UNSPEC) {
2949 /* Bind to the specified local IP address */
2950 struct socket *socket = server->ssocket;
2951 rc = socket->ops->bind(socket,
2952 (struct sockaddr *) &server->srcaddr,
2953 sizeof(server->srcaddr));
2954 if (rc < 0) {
2955 struct sockaddr_in *saddr4;
2956 struct sockaddr_in6 *saddr6;
2957 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2958 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2959 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05002960 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
2961 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002962 else
Joe Perchesf96637b2013-05-04 22:12:25 -05002963 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
2964 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002965 }
2966 }
2967 return rc;
2968}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969
2970static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002971ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972{
2973 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002974 /*
2975 * some servers require RFC1001 sessinit before sending
2976 * negprot - BB check reconnection in case where second
2977 * sessinit is sent but no second negprot
2978 */
2979 struct rfc1002_session_packet *ses_init_buf;
2980 struct smb_hdr *smb_buf;
2981 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2982 GFP_KERNEL);
2983 if (ses_init_buf) {
2984 ses_init_buf->trailer.session_req.called_len = 32;
2985
Colin Ian King997152f2016-01-25 16:25:54 +00002986 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002987 rfc1002mangle(ses_init_buf->trailer.
2988 session_req.called_name,
2989 server->server_RFC1001_name,
2990 RFC1001_NAME_LEN_WITH_NULL);
2991 else
2992 rfc1002mangle(ses_init_buf->trailer.
2993 session_req.called_name,
2994 DEFAULT_CIFS_CALLED_NAME,
2995 RFC1001_NAME_LEN_WITH_NULL);
2996
2997 ses_init_buf->trailer.session_req.calling_len = 32;
2998
2999 /*
3000 * calling name ends in null (byte 16) from old smb
3001 * convention.
3002 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003003 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003004 rfc1002mangle(ses_init_buf->trailer.
3005 session_req.calling_name,
3006 server->workstation_RFC1001_name,
3007 RFC1001_NAME_LEN_WITH_NULL);
3008 else
3009 rfc1002mangle(ses_init_buf->trailer.
3010 session_req.calling_name,
3011 "LINUX_CIFS_CLNT",
3012 RFC1001_NAME_LEN_WITH_NULL);
3013
3014 ses_init_buf->trailer.session_req.scope1 = 0;
3015 ses_init_buf->trailer.session_req.scope2 = 0;
3016 smb_buf = (struct smb_hdr *)ses_init_buf;
3017
3018 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003019 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003020 rc = smb_send(server, smb_buf, 0x44);
3021 kfree(ses_init_buf);
3022 /*
3023 * RFC1001 layer in at least one server
3024 * requires very short break before negprot
3025 * presumably because not expecting negprot
3026 * to follow so fast. This is a simple
3027 * solution that works without
3028 * complicating the code and causes no
3029 * significant slowing down on mount
3030 * for everyone else
3031 */
3032 usleep_range(1000, 2000);
3033 }
3034 /*
3035 * else the negprot may still work without this
3036 * even though malloc failed
3037 */
3038
3039 return rc;
3040}
3041
3042static int
3043generic_ip_connect(struct TCP_Server_Info *server)
3044{
3045 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003046 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003047 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003048 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003049 struct sockaddr *saddr;
3050
3051 saddr = (struct sockaddr *) &server->dstaddr;
3052
3053 if (server->dstaddr.ss_family == AF_INET6) {
3054 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3055 slen = sizeof(struct sockaddr_in6);
3056 sfamily = AF_INET6;
3057 } else {
3058 sport = ((struct sockaddr_in *) saddr)->sin_port;
3059 slen = sizeof(struct sockaddr_in);
3060 sfamily = AF_INET;
3061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003063 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003064 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3065 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003067 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003068 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003071
3072 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003073 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003074 server->ssocket = socket;
3075 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003076 if (sfamily == AF_INET6)
3077 cifs_reclassify_socket6(socket);
3078 else
3079 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 }
3081
Ben Greear3eb9a882010-09-01 17:06:02 -07003082 rc = bind_socket(server);
3083 if (rc < 0)
3084 return rc;
3085
Jeff Laytond5c56052008-12-01 18:42:33 -05003086 /*
3087 * Eventually check for other socket options to change from
3088 * the default. sock_setsockopt not used because it expects
3089 * user space buffer
3090 */
3091 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003092 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003093
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003094 /* make the bufsizes depend on wsize/rsize and max requests */
3095 if (server->noautotune) {
3096 if (socket->sk->sk_sndbuf < (200 * 1024))
3097 socket->sk->sk_sndbuf = 200 * 1024;
3098 if (socket->sk->sk_rcvbuf < (140 * 1024))
3099 socket->sk->sk_rcvbuf = 140 * 1024;
3100 }
3101
Steve French6a5fa2362010-01-01 01:28:43 +00003102 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003103 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003104 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3105 (char *)&val, sizeof(val));
3106 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003107 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3108 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003109 }
3110
Joe Perchesf96637b2013-05-04 22:12:25 -05003111 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003112 socket->sk->sk_sndbuf,
3113 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3114
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003115 rc = socket->ops->connect(socket, saddr, slen, 0);
3116 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003117 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003118 sock_release(socket);
3119 server->ssocket = NULL;
3120 return rc;
3121 }
3122
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003123 if (sport == htons(RFC1001_PORT))
3124 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003125
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 return rc;
3127}
3128
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003129static int
3130ip_connect(struct TCP_Server_Info *server)
3131{
Steve French6da97912011-03-13 18:55:55 +00003132 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003133 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3134 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3135
3136 if (server->dstaddr.ss_family == AF_INET6)
3137 sport = &addr6->sin6_port;
3138 else
3139 sport = &addr->sin_port;
3140
3141 if (*sport == 0) {
3142 int rc;
3143
3144 /* try with 445 port at first */
3145 *sport = htons(CIFS_PORT);
3146
3147 rc = generic_ip_connect(server);
3148 if (rc >= 0)
3149 return rc;
3150
3151 /* if it failed, try with 139 port */
3152 *sport = htons(RFC1001_PORT);
3153 }
3154
3155 return generic_ip_connect(server);
3156}
3157
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003158void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003159 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003160{
3161 /* if we are reconnecting then should we check to see if
3162 * any requested capabilities changed locally e.g. via
3163 * remount but we can not do much about it here
3164 * if they have (even if we could detect it by the following)
3165 * Perhaps we could add a backpointer to array of sb from tcon
3166 * or if we change to make all sb to same share the same
3167 * sb as NFS - then we only have one backpointer to sb.
3168 * What if we wanted to mount the server share twice once with
3169 * and once without posixacls or posix paths? */
3170 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003171
Steve Frenchc18c8422007-07-18 23:21:09 +00003172 if (vol_info && vol_info->no_linux_ext) {
3173 tcon->fsUnixInfo.Capability = 0;
3174 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003175 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003176 return;
3177 } else if (vol_info)
3178 tcon->unix_ext = 1; /* Unix Extensions supported */
3179
3180 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003181 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003182 return;
3183 }
Steve French50c2f752007-07-13 00:33:32 +00003184
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003185 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003186 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003187 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003188 /* check for reconnect case in which we do not
3189 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003190 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003191 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003192 originally at mount time */
3193 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3194 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003195 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3196 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003197 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003198 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003199 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003200 cifs_dbg(VFS, "possible reconnect error\n");
3201 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003202 }
Steve French8af18972007-02-14 04:42:51 +00003203 }
Steve French50c2f752007-07-13 00:33:32 +00003204
Steve French6848b732011-05-26 18:38:54 +00003205 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003206 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003207
Steve French8af18972007-02-14 04:42:51 +00003208 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003209 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003210 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003211 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003212 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003213 if (cifs_sb)
3214 cifs_sb->mnt_cifs_flags |=
3215 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003216 }
3217
Steve French75865f8c2007-06-24 18:30:48 +00003218 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003219 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003220 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003221 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003222 if (cifs_sb)
3223 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003224 CIFS_MOUNT_POSIX_PATHS;
3225 }
Steve French50c2f752007-07-13 00:33:32 +00003226
Joe Perchesf96637b2013-05-04 22:12:25 -05003227 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003228#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003229 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003230 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003231 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003232 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003233 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003234 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003235 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003236 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003237 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003238 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003239 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003240 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003241 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003242 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003243 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003244 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003245 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003246 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003247#endif /* CIFS_DEBUG2 */
3248 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003249 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003250 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003251 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003252 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 +00003253
Steve French8af18972007-02-14 04:42:51 +00003254 }
3255 }
3256}
3257
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003258int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003259 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003260{
Jeff Layton2de970f2010-10-06 19:51:12 -04003261 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3262
Al Viro2ced6f62011-06-17 09:20:04 -04003263 spin_lock_init(&cifs_sb->tlink_tree_lock);
3264 cifs_sb->tlink_tree = RB_ROOT;
3265
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003266 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003267 * Temporarily set r/wsize for matching superblock. If we end up using
3268 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003269 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003270 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003271 cifs_sb->wsize = pvolume_info->wsize;
3272
Steve French3b795212008-11-13 19:45:32 +00003273 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3274 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3275 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3276 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003277 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3278 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003279
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303280 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003281 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303282
Steve French3b795212008-11-13 19:45:32 +00003283 if (pvolume_info->noperm)
3284 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3285 if (pvolume_info->setuids)
3286 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05003287 if (pvolume_info->setuidfromacl)
3288 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00003289 if (pvolume_info->server_ino)
3290 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3291 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003292 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3293 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003294 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3295 if (pvolume_info->no_xattr)
3296 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3297 if (pvolume_info->sfu_emul)
3298 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3299 if (pvolume_info->nobrl)
3300 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003301 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003302 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003303 if (pvolume_info->mand_lock)
3304 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003305 if (pvolume_info->rwpidforward)
3306 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003307 if (pvolume_info->cifs_acl)
3308 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003309 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003310 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003311 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3312 }
3313 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003314 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003315 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3316 }
Steve French3b795212008-11-13 19:45:32 +00003317 if (pvolume_info->override_uid)
3318 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3319 if (pvolume_info->override_gid)
3320 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3321 if (pvolume_info->dynperm)
3322 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303323 if (pvolume_info->fsc)
3324 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003325 if (pvolume_info->multiuser)
3326 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3327 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003328 if (pvolume_info->strict_io)
3329 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003330 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003331 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003332 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3333 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003334 if (pvolume_info->mfsymlinks) {
3335 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003336 /*
3337 * Our SFU ("Services for Unix" emulation does not allow
3338 * creating symlinks but does allow reading existing SFU
3339 * symlinks (it does allow both creating and reading SFU
3340 * style mknod and FIFOs though). When "mfsymlinks" and
3341 * "sfu" are both enabled at the same time, it allows
3342 * reading both types of symlinks, but will only create
3343 * them with mfsymlinks format. This allows better
3344 * Apple compatibility (probably better for Samba too)
3345 * while still recognizing old Windows style symlinks.
3346 */
3347 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003348 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003349 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003350 }
Steve French3b795212008-11-13 19:45:32 +00003351
3352 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003353 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01003354
3355 if (pvolume_info->prepath) {
3356 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
3357 if (cifs_sb->prepath == NULL)
3358 return -ENOMEM;
3359 }
3360
3361 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003362}
3363
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003364static void
3365cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003366{
Sean Finneyb9468452011-04-11 13:19:32 +00003367 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003368 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003369 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003370 kfree(volume_info->domainname);
3371 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003372 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003373}
3374
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003375void
3376cifs_cleanup_volume_info(struct smb_vol *volume_info)
3377{
3378 if (!volume_info)
3379 return;
3380 cleanup_volume_info_contents(volume_info);
3381 kfree(volume_info);
3382}
3383
3384
Steve French2d6d5892009-04-09 00:36:44 +00003385#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003386/*
3387 * cifs_build_path_to_root returns full path to root when we do not have an
3388 * exiting connection (tcon)
3389 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003390static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003391build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003392 const struct cifs_sb_info *cifs_sb)
3393{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003394 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003395 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003396 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003397
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003398 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003399 if (full_path == NULL)
3400 return ERR_PTR(-ENOMEM);
3401
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003402 strncpy(full_path, vol->UNC, unc_len);
3403 pos = full_path + unc_len;
3404
3405 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003406 *pos = CIFS_DIR_SEP(cifs_sb);
3407 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003408 pos += pplen;
3409 }
3410
3411 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003412 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003413 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003414 return full_path;
3415}
Sean Finneydd613942011-04-11 13:19:30 +00003416
3417/*
3418 * Perform a dfs referral query for a share and (optionally) prefix
3419 *
Sean Finney046462a2011-04-11 13:19:33 +00003420 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3421 * to a string containing updated options for the submount. Otherwise it
3422 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003423 *
3424 * Returns the rc from get_dfs_path to the caller, which can be used to
3425 * determine whether there were referrals.
3426 */
3427static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003428expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003429 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003430 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003431{
3432 int rc;
3433 unsigned int num_referrals = 0;
3434 struct dfs_info3_param *referrals = NULL;
3435 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3436
3437 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3438 if (IS_ERR(full_path))
3439 return PTR_ERR(full_path);
3440
3441 /* For DFS paths, skip the first '\' of the UNC */
3442 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3443
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003444 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003445 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003446
3447 if (!rc && num_referrals > 0) {
3448 char *fake_devname = NULL;
3449
3450 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3451 full_path + 1, referrals,
3452 &fake_devname);
3453
3454 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003455
Sean Finneydd613942011-04-11 13:19:30 +00003456 if (IS_ERR(mdata)) {
3457 rc = PTR_ERR(mdata);
3458 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003459 } else {
3460 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003461 rc = cifs_setup_volume_info(volume_info, mdata,
3462 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003463 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003464 kfree(fake_devname);
3465 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003466 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003467 }
3468 kfree(full_path);
3469 return rc;
3470}
Steve French2d6d5892009-04-09 00:36:44 +00003471#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003472
Jeff Layton04db79b2011-07-06 08:10:38 -04003473static int
3474cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3475 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003477 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003478
Jeff Layton04db79b2011-07-06 08:10:38 -04003479 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3480 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481
Jeff Layton7586b762008-12-01 18:41:49 -05003482 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003483 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003484 kfree(volume_info->username);
3485 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003486 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003488 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003490 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003491 /* In userspace mount helper we can get user name from alternate
3492 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003493 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 }
3495
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003497 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003498 /* load_nls_default cannot return null */
3499 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003501 volume_info->local_nls = load_nls(volume_info->iocharset);
3502 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003503 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003504 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003505 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 }
3507 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003508
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003509 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003510}
3511
3512struct smb_vol *
3513cifs_get_volume_info(char *mount_data, const char *devname)
3514{
3515 int rc;
3516 struct smb_vol *volume_info;
3517
Jeff Layton6ee95422012-11-26 11:09:57 -05003518 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003519 if (!volume_info)
3520 return ERR_PTR(-ENOMEM);
3521
3522 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3523 if (rc) {
3524 cifs_cleanup_volume_info(volume_info);
3525 volume_info = ERR_PTR(rc);
3526 }
3527
3528 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003529}
3530
Aurelien Aptela6b50582016-05-25 19:59:09 +02003531static int
3532cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
3533 unsigned int xid,
3534 struct cifs_tcon *tcon,
3535 struct cifs_sb_info *cifs_sb,
3536 char *full_path)
3537{
3538 int rc;
3539 char *s;
3540 char sep, tmp;
3541
3542 sep = CIFS_DIR_SEP(cifs_sb);
3543 s = full_path;
3544
3545 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
3546 while (rc == 0) {
3547 /* skip separators */
3548 while (*s == sep)
3549 s++;
3550 if (!*s)
3551 break;
3552 /* next separator */
3553 while (*s && *s != sep)
3554 s++;
3555
3556 /*
3557 * temporarily null-terminate the path at the end of
3558 * the current component
3559 */
3560 tmp = *s;
3561 *s = 0;
3562 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3563 full_path);
3564 *s = tmp;
3565 }
3566 return rc;
3567}
3568
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003569int
Al Viro2c6292a2011-06-17 09:05:48 -04003570cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003571{
Jeff Layton1daaae82012-03-21 06:30:40 -04003572 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003573 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003574 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003575 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003576 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003577 char *full_path;
3578 struct tcon_link *tlink;
3579#ifdef CONFIG_CIFS_DFS_UPCALL
3580 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003581#endif
Al Virodd854462011-06-17 08:24:42 -04003582
Christoph Hellwigb4caecd2015-01-14 10:42:32 +01003583 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs");
Al Virodd854462011-06-17 08:24:42 -04003584 if (rc)
3585 return rc;
3586
Jeff Layton20547492011-07-09 12:21:07 -04003587#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003588try_mount_again:
3589 /* cleanup activities if we're chasing a referral */
3590 if (referral_walks_count) {
3591 if (tcon)
3592 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003593 else if (ses)
3594 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003595
Sachin Prabhu1dfd18d2015-06-16 16:36:17 +01003596 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3597
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003598 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003599 }
3600#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003601 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003602 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003603 ses = NULL;
3604 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003605 full_path = NULL;
3606 tlink = NULL;
3607
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003608 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609
Jeff Layton63c038c2008-12-01 18:41:46 -05003610 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003611 server = cifs_get_tcp_session(volume_info);
3612 if (IS_ERR(server)) {
3613 rc = PTR_ERR(server);
Al Virodd854462011-06-17 08:24:42 -04003614 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003615 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 }
Steve French141891f2016-09-23 00:44:16 -05003617 if ((volume_info->max_credits < 20) ||
3618 (volume_info->max_credits > 60000))
3619 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
3620 else
3621 server->max_credits = volume_info->max_credits;
Jeff Layton36988c72010-04-24 07:57:43 -04003622 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003623 ses = cifs_get_smb_ses(server, volume_info);
3624 if (IS_ERR(ses)) {
3625 rc = PTR_ERR(ses);
3626 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003627 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 }
Steve French50c2f752007-07-13 00:33:32 +00003629
Steve French592fafe2015-11-03 10:08:53 -06003630#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06003631 if ((volume_info->persistent == true) && ((ses->server->capabilities &
3632 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
3633 cifs_dbg(VFS, "persistent handles not supported by server\n");
3634 rc = -EOPNOTSUPP;
3635 goto mount_fail_check;
3636 }
Steve French592fafe2015-11-03 10:08:53 -06003637#endif /* CONFIG_CIFS_SMB2*/
3638
Jeff Laytond00c28d2010-04-24 07:57:44 -04003639 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003640 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003641 if (IS_ERR(tcon)) {
3642 rc = PTR_ERR(tcon);
3643 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003644 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003645 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003646
Steve French6848b732011-05-26 18:38:54 +00003647 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003648 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003649 /* reset of caps checks mount to see if unix extensions
3650 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003651 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003652 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3653 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3654 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3655 rc = -EACCES;
3656 goto mount_fail_check;
3657 }
3658 } else
3659 tcon->unix_ext = 0; /* server does not support them */
3660
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003661 /* do not care if a following call succeed - informational */
3662 if (!tcon->ipc && server->ops->qfs_tcon)
3663 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003664
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003665 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3666 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003667
Jeff Layton66bfaad2011-10-19 15:30:35 -04003668 /* tune readahead according to rsize */
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03003669 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003670
Igor Mammedove4cce942009-02-10 14:10:26 +03003671remote_path_check:
3672#ifdef CONFIG_CIFS_DFS_UPCALL
3673 /*
3674 * Perform an unconditional check for whether there are DFS
3675 * referrals for this path without prefix, to provide support
3676 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003677 * with PATH_NOT_COVERED to requests that include the prefix.
3678 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003679 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003680 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003681 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3682 false);
Steve Frencheeac8042006-01-13 21:34:58 -08003683 if (!refrc) {
Steve French4523cc32007-04-30 20:13:06 +00003684 referral_walks_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 goto try_mount_again;
3686 }
3687 }
3688#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003689
Steve Frenchf87d39d2011-05-27 03:50:55 +00003690 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003692 if (!server->ops->is_path_accessible) {
3693 rc = -ENOSYS;
3694 goto mount_fail_check;
3695 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003696 /*
3697 * cifs_build_path_to_root works only when we have a valid tcon
3698 */
3699 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 if (full_path == NULL) {
3701 rc = -ENOMEM;
3702 goto mount_fail_check;
3703 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003704 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3705 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 if (rc != 0 && rc != -EREMOTE) {
3707 kfree(full_path);
3708 goto mount_fail_check;
3709 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02003710
Sachin Prabhud1713562016-09-06 13:22:34 +01003711 if (rc != -EREMOTE) {
3712 rc = cifs_are_all_path_components_accessible(server,
Aurelien Aptela6b50582016-05-25 19:59:09 +02003713 xid, tcon, cifs_sb,
3714 full_path);
Sachin Prabhud1713562016-09-06 13:22:34 +01003715 if (rc != 0) {
3716 cifs_dbg(VFS, "cannot query dirs between root and final path, "
3717 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
3718 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
3719 rc = 0;
3720 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02003721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 kfree(full_path);
3723 }
3724
3725 /* get referral if needed */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003726 if (rc == -EREMOTE) {
3727#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003728 if (referral_walks_count > MAX_NESTED_LINKS) {
3729 /*
3730 * BB: when we implement proper loop detection,
3731 * we will remove this check. But now we need it
3732 * to prevent an indefinite loop if 'DFS tree' is
3733 * misconfigured (i.e. has loops).
3734 */
3735 rc = -ELOOP;
3736 goto mount_fail_check;
3737 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003738
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003739 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003740
Sean Finneydd613942011-04-11 13:19:30 +00003741 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003742 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003743 goto try_mount_again;
3744 }
Sean Finneydd613942011-04-11 13:19:30 +00003745 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003746#else /* No DFS support, return error on mount */
3747 rc = -EOPNOTSUPP;
3748#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003749 }
3750
Jeff Layton9d002df2010-10-06 19:51:11 -04003751 if (rc)
3752 goto mount_fail_check;
3753
3754 /* now, hang the tcon off of the superblock */
3755 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3756 if (tlink == NULL) {
3757 rc = -ENOMEM;
3758 goto mount_fail_check;
3759 }
3760
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003761 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003762 tlink->tl_tcon = tcon;
3763 tlink->tl_time = jiffies;
3764 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3765 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3766
Jeff Layton413e6612010-10-28 13:33:38 -04003767 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003768 spin_lock(&cifs_sb->tlink_tree_lock);
3769 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3770 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003771
Jeff Laytonda472fc2012-03-23 14:40:53 -04003772 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003773 TLINK_IDLE_EXPIRE);
3774
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003775mount_fail_check:
3776 /* on error free sesinfo and tcon struct if needed */
3777 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003778 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003779 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003780 if (tcon)
3781 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003782 else if (ses)
3783 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003784 else
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003785 cifs_put_tcp_session(server);
Al Virodd854462011-06-17 08:24:42 -04003786 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003787 }
3788
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003790 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 return rc;
3792}
3793
Jeff Layton8d1bca32011-06-11 21:17:10 -04003794/*
3795 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3796 * pointer may be NULL.
3797 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003799CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00003800 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 const struct nls_table *nls_codepage)
3802{
3803 struct smb_hdr *smb_buffer;
3804 struct smb_hdr *smb_buffer_response;
3805 TCONX_REQ *pSMB;
3806 TCONX_RSP *pSMBr;
3807 unsigned char *bcc_ptr;
3808 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003809 int length;
3810 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811
3812 if (ses == NULL)
3813 return -EIO;
3814
3815 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003816 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003818
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 smb_buffer_response = smb_buffer;
3820
3821 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3822 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003823
Pavel Shilovsky88257362012-05-23 14:01:59 +04003824 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 smb_buffer->Uid = ses->Suid;
3826 pSMB = (TCONX_REQ *) smb_buffer;
3827 pSMBr = (TCONX_RSP *) smb_buffer_response;
3828
3829 pSMB->AndXCommand = 0xFF;
3830 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003832 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003833 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003834 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003835 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003836 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003837 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003838 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003839 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3840 specified as required (when that support is added to
3841 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003842 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003843 by Samba (not sure whether other servers allow
3844 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003845#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003846 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05003847 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003848 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003849 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003850 SECMODE_PW_ENCRYPT ? true : false,
3851 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003852 else
3853#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003854 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003855 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05003856 if (rc) {
3857 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
3858 __func__, rc);
3859 cifs_buf_release(smb_buffer);
3860 return rc;
3861 }
Steve Frencheeac8042006-01-13 21:34:58 -08003862
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003863 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003864 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003865 /* must align unicode strings */
3866 *bcc_ptr = 0; /* null byte password */
3867 bcc_ptr++;
3868 }
Steve Frencheeac8042006-01-13 21:34:58 -08003869 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Jeff Layton38d77c52013-05-26 07:01:00 -04003871 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3873
3874 if (ses->capabilities & CAP_STATUS32) {
3875 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3876 }
3877 if (ses->capabilities & CAP_DFS) {
3878 smb_buffer->Flags2 |= SMBFLG2_DFS;
3879 }
3880 if (ses->capabilities & CAP_UNICODE) {
3881 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3882 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003883 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003884 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003885 (/* server len*/ + 256 /* share len */), nls_codepage);
3886 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 bcc_ptr += 2; /* skip trailing null */
3888 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 strcpy(bcc_ptr, tree);
3890 bcc_ptr += strlen(tree) + 1;
3891 }
3892 strcpy(bcc_ptr, "?????");
3893 bcc_ptr += strlen("?????");
3894 bcc_ptr += 1;
3895 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003896 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3897 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 pSMB->ByteCount = cpu_to_le16(count);
3899
Steve French133672e2007-11-13 22:41:37 +00003900 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003901 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 /* above now done in SendReceive */
3904 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003905 bool is_unicode;
3906
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003908 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909 tcon->tid = smb_buffer_response->Tid;
3910 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003911 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003912 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003913 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
3914 is_unicode = true;
3915 else
3916 is_unicode = false;
3917
Jeff Laytoncc20c032009-04-30 07:16:21 -04003918
Steve French50c2f752007-07-13 00:33:32 +00003919 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00003920 if (length == 3) {
3921 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3922 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003923 cifs_dbg(FYI, "IPC connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003924 tcon->ipc = 1;
3925 }
3926 } else if (length == 2) {
3927 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3928 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05003929 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003930 }
3931 }
Steve French50c2f752007-07-13 00:33:32 +00003932 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04003933 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05003934 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04003935
3936 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04003937 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06003938 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00003939 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04003940 nls_codepage);
3941
Joe Perchesf96637b2013-05-04 22:12:25 -05003942 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003943
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003944 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00003945 (smb_buffer_response->WordCount == 7))
3946 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00003947 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3948 else
3949 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05003950 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003952 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 ses->ipc_tid = smb_buffer_response->Tid;
3954 }
3955
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00003956 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 return rc;
3958}
3959
Al Viro2e32cf52013-10-03 12:53:37 -04003960static void delayed_free(struct rcu_head *p)
3961{
3962 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
3963 unload_nls(sbi->local_nls);
3964 kfree(sbi);
3965}
3966
Al Viro2a9b9952011-06-17 09:27:16 -04003967void
3968cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969{
Jeff Laytonb647c352010-10-28 11:16:44 -04003970 struct rb_root *root = &cifs_sb->tlink_tree;
3971 struct rb_node *node;
3972 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973
Jeff Layton2de970f2010-10-06 19:51:12 -04003974 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
3975
Jeff Laytonb647c352010-10-28 11:16:44 -04003976 spin_lock(&cifs_sb->tlink_tree_lock);
3977 while ((node = rb_first(root))) {
3978 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3979 cifs_get_tlink(tlink);
3980 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3981 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00003982
Jeff Laytonb647c352010-10-28 11:16:44 -04003983 spin_unlock(&cifs_sb->tlink_tree_lock);
3984 cifs_put_tlink(tlink);
3985 spin_lock(&cifs_sb->tlink_tree_lock);
3986 }
3987 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003988
Al Virodd854462011-06-17 08:24:42 -04003989 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04003990 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02003991 kfree(cifs_sb->prepath);
Al Viro2e32cf52013-10-03 12:53:37 -04003992 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00003993}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003995int
3996cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997{
3998 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04003999 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004001 if (!server->ops->need_neg || !server->ops->negotiate)
4002 return -ENOSYS;
4003
Jeff Layton198b5682010-04-24 07:57:48 -04004004 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004005 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04004006 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Pavel Shilovsky45275782012-05-17 17:53:29 +04004008 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04004009
4010 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04004011 if (rc == 0) {
4012 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004013 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004014 server->tcpStatus = CifsGood;
4015 else
4016 rc = -EHOSTDOWN;
4017 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 }
Steve French26b994f2008-08-06 05:11:33 +00004019
Jeff Layton198b5682010-04-24 07:57:48 -04004020 return rc;
4021}
Steve French26b994f2008-08-06 05:11:33 +00004022
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004023int
4024cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
4025 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04004026{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004027 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04004028 struct TCP_Server_Info *server = ses->server;
4029
Jeff Layton198b5682010-04-24 07:57:48 -04004030 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004031 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004032 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00004033
Joe Perchesf96637b2013-05-04 22:12:25 -05004034 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00004035 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004036
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04004037 if (server->ops->sess_setup)
4038 rc = server->ops->sess_setup(xid, ses, nls_info);
4039
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05004040 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05004041 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004042
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043 return rc;
4044}
4045
Jeff Layton8a8798a2012-01-17 16:09:15 -05004046static int
4047cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4048{
Jeff Layton3f618222013-06-12 19:52:14 -05004049 vol->sectype = ses->sectype;
4050
4051 /* krb5 is special, since we don't need username or pw */
4052 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05004053 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05004054
4055 return cifs_set_cifscreds(vol, ses);
4056}
4057
Steve French96daf2b2011-05-27 04:34:02 +00004058static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004059cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04004060{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004061 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004062 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4063 struct cifs_ses *ses;
4064 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004065 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004066
4067 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004068 if (vol_info == NULL)
4069 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004070
Jeff Layton9d002df2010-10-06 19:51:11 -04004071 vol_info->local_nls = cifs_sb->local_nls;
4072 vol_info->linux_uid = fsuid;
4073 vol_info->cred_uid = fsuid;
4074 vol_info->UNC = master_tcon->treeName;
4075 vol_info->retry = master_tcon->retry;
4076 vol_info->nocase = master_tcon->nocase;
4077 vol_info->local_lease = master_tcon->local_lease;
4078 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004079 vol_info->sectype = master_tcon->ses->sectype;
4080 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004081
Jeff Layton8a8798a2012-01-17 16:09:15 -05004082 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4083 if (rc) {
4084 tcon = ERR_PTR(rc);
4085 goto out;
4086 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004087
4088 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304089 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004090 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304091 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004092
4093 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4094 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004095 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004096 cifs_put_tcp_session(master_tcon->ses->server);
4097 goto out;
4098 }
4099
4100 tcon = cifs_get_tcon(ses, vol_info);
4101 if (IS_ERR(tcon)) {
4102 cifs_put_smb_ses(ses);
4103 goto out;
4104 }
4105
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004106 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004107 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4108out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004109 kfree(vol_info->username);
4110 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004111 kfree(vol_info);
4112
4113 return tcon;
4114}
4115
Steve French96daf2b2011-05-27 04:34:02 +00004116struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004117cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4118{
4119 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4120}
4121
Jeff Laytonb647c352010-10-28 11:16:44 -04004122/* find and return a tlink with given uid */
4123static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004124tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004125{
4126 struct rb_node *node = root->rb_node;
4127 struct tcon_link *tlink;
4128
4129 while (node) {
4130 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4131
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004132 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004133 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004134 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004135 node = node->rb_right;
4136 else
4137 return tlink;
4138 }
4139 return NULL;
4140}
4141
4142/* insert a tcon_link into the tree */
4143static void
4144tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4145{
4146 struct rb_node **new = &(root->rb_node), *parent = NULL;
4147 struct tcon_link *tlink;
4148
4149 while (*new) {
4150 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4151 parent = *new;
4152
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004153 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004154 new = &((*new)->rb_left);
4155 else
4156 new = &((*new)->rb_right);
4157 }
4158
4159 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4160 rb_insert_color(&new_tlink->tl_rbnode, root);
4161}
4162
Jeff Layton9d002df2010-10-06 19:51:11 -04004163/*
4164 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4165 * current task.
4166 *
4167 * If the superblock doesn't refer to a multiuser mount, then just return
4168 * the master tcon for the mount.
4169 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304170 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004171 * exists, then check to see if it's pending construction. If it is then wait
4172 * for construction to complete. Once it's no longer pending, check to see if
4173 * it failed and either return an error or retry construction, depending on
4174 * the timeout.
4175 *
4176 * If one doesn't exist then insert a new tcon_link struct into the tree and
4177 * try to construct a new one.
4178 */
4179struct tcon_link *
4180cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4181{
4182 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004183 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004184 struct tcon_link *tlink, *newtlink;
4185
4186 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4187 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4188
4189 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004190 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004191 if (tlink)
4192 cifs_get_tlink(tlink);
4193 spin_unlock(&cifs_sb->tlink_tree_lock);
4194
4195 if (tlink == NULL) {
4196 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4197 if (newtlink == NULL)
4198 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004199 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004200 newtlink->tl_tcon = ERR_PTR(-EACCES);
4201 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4202 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4203 cifs_get_tlink(newtlink);
4204
Jeff Layton9d002df2010-10-06 19:51:11 -04004205 spin_lock(&cifs_sb->tlink_tree_lock);
4206 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004207 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004208 if (tlink) {
4209 cifs_get_tlink(tlink);
4210 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004211 kfree(newtlink);
4212 goto wait_for_construction;
4213 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004214 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004215 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4216 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004217 } else {
4218wait_for_construction:
4219 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004220 TASK_INTERRUPTIBLE);
4221 if (ret) {
4222 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004223 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004224 }
4225
4226 /* if it's good, return it */
4227 if (!IS_ERR(tlink->tl_tcon))
4228 return tlink;
4229
4230 /* return error if we tried this already recently */
4231 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4232 cifs_put_tlink(tlink);
4233 return ERR_PTR(-EACCES);
4234 }
4235
4236 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4237 goto wait_for_construction;
4238 }
4239
4240 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4241 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4242 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4243
4244 if (IS_ERR(tlink->tl_tcon)) {
4245 cifs_put_tlink(tlink);
4246 return ERR_PTR(-EACCES);
4247 }
4248
4249 return tlink;
4250}
Jeff Layton2de970f2010-10-06 19:51:12 -04004251
4252/*
4253 * periodic workqueue job that scans tcon_tree for a superblock and closes
4254 * out tcons.
4255 */
4256static void
4257cifs_prune_tlinks(struct work_struct *work)
4258{
4259 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4260 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004261 struct rb_root *root = &cifs_sb->tlink_tree;
4262 struct rb_node *node = rb_first(root);
4263 struct rb_node *tmp;
4264 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004265
Jeff Laytonb647c352010-10-28 11:16:44 -04004266 /*
4267 * Because we drop the spinlock in the loop in order to put the tlink
4268 * it's not guarded against removal of links from the tree. The only
4269 * places that remove entries from the tree are this function and
4270 * umounts. Because this function is non-reentrant and is canceled
4271 * before umount can proceed, this is safe.
4272 */
4273 spin_lock(&cifs_sb->tlink_tree_lock);
4274 node = rb_first(root);
4275 while (node != NULL) {
4276 tmp = node;
4277 node = rb_next(tmp);
4278 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4279
4280 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4281 atomic_read(&tlink->tl_count) != 0 ||
4282 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4283 continue;
4284
4285 cifs_get_tlink(tlink);
4286 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4287 rb_erase(tmp, root);
4288
Jeff Layton2de970f2010-10-06 19:51:12 -04004289 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004290 cifs_put_tlink(tlink);
4291 spin_lock(&cifs_sb->tlink_tree_lock);
4292 }
4293 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004294
Jeff Laytonda472fc2012-03-23 14:40:53 -04004295 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004296 TLINK_IDLE_EXPIRE);
4297}