blob: 4042996ddc7c6f6a7ccc5c389b20c5147751800b [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>
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "cifspdu.h"
46#include "cifsglob.h"
47#include "cifsproto.h"
48#include "cifs_unicode.h"
49#include "cifs_debug.h"
50#include "cifs_fs_sb.h"
51#include "ntlmssp.h"
52#include "nterr.h"
53#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053054#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#define CIFS_PORT 445
57#define RFC1001_PORT 139
58
Linus Torvalds1da177e2005-04-16 15:20:36 -070059extern mempool_t *cifs_req_poolp;
60
Jeff Layton2de970f2010-10-06 19:51:12 -040061/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040062#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040063#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040064
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040065enum {
66
67 /* 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,
79 Opt_forcemandatorylock, Opt_setuids,
80 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,
98
99 /* Mount options which take string value */
100 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400101 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400102 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400103 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400104
105 /* Mount options to be ignored */
106 Opt_ignore,
107
108 /* Options which could be blank */
109 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100110 Opt_blank_user,
111 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400112
113 Opt_err
114};
115
116static const match_table_t cifs_mount_option_tokens = {
117
118 { Opt_user_xattr, "user_xattr" },
119 { Opt_nouser_xattr, "nouser_xattr" },
120 { Opt_forceuid, "forceuid" },
121 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400122 { Opt_forcegid, "forcegid" },
123 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400124 { Opt_noblocksend, "noblocksend" },
125 { Opt_noautotune, "noautotune" },
126 { Opt_hard, "hard" },
127 { Opt_soft, "soft" },
128 { Opt_perm, "perm" },
129 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500130 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400131 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500132 { Opt_mapposix, "mapposix" }, /* SFM style */
133 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400134 { Opt_sfu, "sfu" },
135 { Opt_nosfu, "nosfu" },
136 { Opt_nodfs, "nodfs" },
137 { Opt_posixpaths, "posixpaths" },
138 { Opt_noposixpaths, "noposixpaths" },
139 { Opt_nounix, "nounix" },
140 { Opt_nounix, "nolinux" },
141 { Opt_nocase, "nocase" },
142 { Opt_nocase, "ignorecase" },
143 { Opt_brl, "brl" },
144 { Opt_nobrl, "nobrl" },
145 { Opt_nobrl, "nolock" },
146 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400147 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400148 { Opt_setuids, "setuids" },
149 { Opt_nosetuids, "nosetuids" },
150 { Opt_dynperm, "dynperm" },
151 { Opt_nodynperm, "nodynperm" },
152 { Opt_nohard, "nohard" },
153 { Opt_nosoft, "nosoft" },
154 { Opt_nointr, "nointr" },
155 { Opt_intr, "intr" },
156 { Opt_nostrictsync, "nostrictsync" },
157 { Opt_strictsync, "strictsync" },
158 { Opt_serverino, "serverino" },
159 { Opt_noserverino, "noserverino" },
160 { Opt_rwpidforward, "rwpidforward" },
161 { Opt_cifsacl, "cifsacl" },
162 { Opt_nocifsacl, "nocifsacl" },
163 { Opt_acl, "acl" },
164 { Opt_noacl, "noacl" },
165 { Opt_locallease, "locallease" },
166 { Opt_sign, "sign" },
167 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400168 { Opt_noac, "noac" },
169 { Opt_fsc, "fsc" },
170 { Opt_mfsymlinks, "mfsymlinks" },
171 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400172 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400173 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500174 { Opt_persistent, "persistenthandles"},
175 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600176 { Opt_resilient, "resilienthandles"},
177 { Opt_noresilient, "noresilienthandles"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400178
179 { Opt_backupuid, "backupuid=%s" },
180 { Opt_backupgid, "backupgid=%s" },
181 { Opt_uid, "uid=%s" },
182 { Opt_cruid, "cruid=%s" },
183 { Opt_gid, "gid=%s" },
184 { Opt_file_mode, "file_mode=%s" },
185 { Opt_dirmode, "dirmode=%s" },
186 { Opt_dirmode, "dir_mode=%s" },
187 { Opt_port, "port=%s" },
188 { Opt_rsize, "rsize=%s" },
189 { Opt_wsize, "wsize=%s" },
190 { Opt_actimeo, "actimeo=%s" },
191
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100192 { Opt_blank_user, "user=" },
193 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400194 { Opt_user, "user=%s" },
195 { Opt_user, "username=%s" },
196 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100197 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400198 { Opt_pass, "pass=%s" },
199 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100200 { Opt_blank_ip, "ip=" },
201 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400202 { Opt_ip, "ip=%s" },
203 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400204 { Opt_ignore, "unc=%s" },
205 { Opt_ignore, "target=%s" },
206 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400207 { Opt_domain, "dom=%s" },
208 { Opt_domain, "domain=%s" },
209 { Opt_domain, "workgroup=%s" },
210 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400211 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400212 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400213 { Opt_netbiosname, "netbiosname=%s" },
214 { Opt_servern, "servern=%s" },
215 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400216 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400217 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400218 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400219
220 { Opt_ignore, "cred" },
221 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400222 { Opt_ignore, "cred=%s" },
223 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400224 { Opt_ignore, "guest" },
225 { Opt_ignore, "rw" },
226 { Opt_ignore, "ro" },
227 { Opt_ignore, "suid" },
228 { Opt_ignore, "nosuid" },
229 { Opt_ignore, "exec" },
230 { Opt_ignore, "noexec" },
231 { Opt_ignore, "nodev" },
232 { Opt_ignore, "noauto" },
233 { Opt_ignore, "dev" },
234 { Opt_ignore, "mand" },
235 { Opt_ignore, "nomand" },
236 { Opt_ignore, "_netdev" },
237
238 { Opt_err, NULL }
239};
240
241enum {
242 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
243 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400244 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
245 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400246 Opt_sec_none,
247
248 Opt_sec_err
249};
250
251static const match_table_t cifs_secflavor_tokens = {
252 { Opt_sec_krb5, "krb5" },
253 { Opt_sec_krb5i, "krb5i" },
254 { Opt_sec_krb5p, "krb5p" },
255 { Opt_sec_ntlmsspi, "ntlmsspi" },
256 { Opt_sec_ntlmssp, "ntlmssp" },
257 { Opt_ntlm, "ntlm" },
258 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400259 { Opt_sec_ntlmv2, "nontlm" },
260 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400261 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400262 { Opt_sec_lanman, "lanman" },
263 { Opt_sec_none, "none" },
264
265 { Opt_sec_err, NULL }
266};
267
Jeff Layton15b6a472012-05-16 07:50:15 -0400268/* cache flavors */
269enum {
270 Opt_cache_loose,
271 Opt_cache_strict,
272 Opt_cache_none,
273 Opt_cache_err
274};
275
276static const match_table_t cifs_cacheflavor_tokens = {
277 { Opt_cache_loose, "loose" },
278 { Opt_cache_strict, "strict" },
279 { Opt_cache_none, "none" },
280 { Opt_cache_err, NULL }
281};
282
Jeff Layton23db65f2012-05-15 12:20:51 -0400283static const match_table_t cifs_smb_version_tokens = {
284 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600285 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000286 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500287 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500288 { Smb_302, SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600289#ifdef CONFIG_CIFS_SMB311
290 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500291 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600292#endif /* SMB311 */
293 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400294};
295
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300296static int ip_connect(struct TCP_Server_Info *server);
297static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400298static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400299static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400300static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
301 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Jeff Laytond5c56052008-12-01 18:42:33 -0500303/*
304 * cifs tcp session reconnection
305 *
306 * mark tcp session as reconnecting so temporarily locked
307 * mark all smb sessions as reconnecting for tcp session
308 * reconnect tcp session
309 * wake up waiters on reconnection? - (not needed currently)
310 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400311int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312cifs_reconnect(struct TCP_Server_Info *server)
313{
314 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500315 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000316 struct cifs_ses *ses;
317 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000318 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400319 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000320
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000322 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000323 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 next time through the loop */
325 spin_unlock(&GlobalMid_Lock);
326 return rc;
327 } else
328 server->tcpStatus = CifsNeedReconnect;
329 spin_unlock(&GlobalMid_Lock);
330 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400331#ifdef CONFIG_CIFS_SMB2
332 server->max_read = 0;
333#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Joe Perchesf96637b2013-05-04 22:12:25 -0500335 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337 /* before reconnecting the tcp session, mark the smb session (uid)
338 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500339 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
340 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530341 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500342 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000343 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500344 ses->need_reconnect = true;
345 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500346 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000347 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500348 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530351 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500354 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500355 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000356 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500357 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
358 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800359 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500360 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
361 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 sock_release(server->ssocket);
363 server->ssocket = NULL;
364 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500365 server->sequence_number = 0;
366 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500367 kfree(server->session_key.response);
368 server->session_key.response = NULL;
369 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000370 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500371 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500373 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400374 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500375 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500377 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
378 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400379 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
380 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400381 list_move(&mid_entry->qhead, &retry_list);
382 }
383 spin_unlock(&GlobalMid_Lock);
384
Joe Perchesf96637b2013-05-04 22:12:25 -0500385 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400386 list_for_each_safe(tmp, tmp2, &retry_list) {
387 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500388 list_del_init(&mid_entry->qhead);
389 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400392 do {
Steve French6c3d8902006-07-31 22:46:20 +0000393 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300394
395 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400396 mutex_lock(&server->srv_mutex);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300397 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000398 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500399 cifs_dbg(FYI, "reconnect error %d\n", rc);
Federico Sauter4afe2602015-03-17 17:45:28 +0100400 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700401 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 } else {
403 atomic_inc(&tcpSesReconnectCount);
404 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000405 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000406 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000407 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100408 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400410 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 return rc;
413}
414
Jeff Laytonc74093b2011-01-11 07:24:23 -0500415static void
416cifs_echo_request(struct work_struct *work)
417{
418 int rc;
419 struct TCP_Server_Info *server = container_of(work,
420 struct TCP_Server_Info, echo.work);
421
Jeff Layton247ec9b2011-02-04 17:09:50 -0500422 /*
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400423 * We cannot send an echo if it is disabled or until the
424 * NEGOTIATE_PROTOCOL request is done, which is indicated by
425 * server->ops->need_neg() == true. Also, no need to ping if
426 * we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500427 */
Pavel Shilovsky286170a2012-05-25 10:43:58 +0400428 if (!server->ops->need_neg || server->ops->need_neg(server) ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400429 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Jeff Layton247ec9b2011-02-04 17:09:50 -0500430 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500431 goto requeue_echo;
432
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400433 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500434 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500435 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
436 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500437
438requeue_echo:
Jeff Laytonda472fc2012-03-23 14:40:53 -0400439 queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500440}
441
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400442static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400443allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400444{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400445 if (!server->bigbuf) {
446 server->bigbuf = (char *)cifs_buf_get();
447 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500448 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400449 msleep(3000);
450 /* retry will check if exiting */
451 return false;
452 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400453 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400454 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400455 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400456 }
457
Jeff Layton2a37ef92011-10-19 15:29:23 -0400458 if (!server->smallbuf) {
459 server->smallbuf = (char *)cifs_small_buf_get();
460 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500461 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400462 msleep(1000);
463 /* retry will check if exiting */
464 return false;
465 }
466 /* beginning of smb buffer is cleared in our buf_get */
467 } else {
468 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400469 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400470 }
471
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400472 return true;
473}
474
Jeff Laytonba749e62011-10-11 06:41:32 -0400475static bool
476server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400477{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300478 /*
479 * We need to wait 2 echo intervals to make sure we handle such
480 * situations right:
481 * 1s client sends a normal SMB request
482 * 2s client gets a response
483 * 30s echo workqueue job pops, and decides we got a response recently
484 * and don't need to send another
485 * ...
486 * 65s kernel_recvmsg times out, and we see that we haven't gotten
487 * a response in >60s.
488 */
489 if (server->tcpStatus == CifsGood &&
490 time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500491 cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n",
492 server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400493 cifs_reconnect(server);
494 wake_up(&server->response_q);
495 return true;
496 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400497
Jeff Laytonba749e62011-10-11 06:41:32 -0400498 return false;
499}
500
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400501/*
502 * kvec_array_init - clone a kvec array, and advance into it
503 * @new: pointer to memory for cloned array
504 * @iov: pointer to original array
505 * @nr_segs: number of members in original array
506 * @bytes: number of bytes to advance into the cloned array
507 *
508 * This function will copy the array provided in iov to a section of memory
509 * and advance the specified number of bytes into the new array. It returns
510 * the number of segments in the new array. "new" must be at least as big as
511 * the original iov array.
512 */
513static unsigned int
514kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
515 size_t bytes)
516{
517 size_t base = 0;
518
519 while (bytes || !iov->iov_len) {
520 int copy = min(bytes, iov->iov_len);
521
522 bytes -= copy;
523 base += copy;
524 if (iov->iov_len == base) {
525 iov++;
526 nr_segs--;
527 base = 0;
528 }
529 }
530 memcpy(new, iov, sizeof(*iov) * nr_segs);
531 new->iov_base += base;
532 new->iov_len -= base;
533 return nr_segs;
534}
535
Jeff Layton1041e3f2011-10-19 15:28:27 -0400536static struct kvec *
537get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
538{
539 struct kvec *new_iov;
540
541 if (server->iov && nr_segs <= server->nr_iov)
542 return server->iov;
543
544 /* not big enough -- allocate a new one and release the old */
545 new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
546 if (new_iov) {
547 kfree(server->iov);
548 server->iov = new_iov;
549 server->nr_iov = nr_segs;
550 }
551 return new_iov;
552}
553
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400554int
555cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
556 unsigned int nr_segs, unsigned int to_read)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400557{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400558 int length = 0;
559 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400560 unsigned int segs;
Jeff Laytone831e6c2011-10-11 06:41:32 -0400561 struct msghdr smb_msg;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400562 struct kvec *iov;
563
Jeff Layton1041e3f2011-10-19 15:28:27 -0400564 iov = get_server_iovec(server, nr_segs);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400565 if (!iov)
566 return -ENOMEM;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400567
Jeff Laytone831e6c2011-10-11 06:41:32 -0400568 smb_msg.msg_control = NULL;
569 smb_msg.msg_controllen = 0;
570
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400571 for (total_read = 0; to_read; total_read += length, to_read -= length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500572 try_to_freeze();
573
Jeff Laytonba749e62011-10-11 06:41:32 -0400574 if (server_unresponsive(server)) {
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400575 total_read = -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400576 break;
577 }
578
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400579 segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
580
581 length = kernel_recvmsg(server->ssocket, &smb_msg,
582 iov, segs, to_read, 0);
583
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400584 if (server->tcpStatus == CifsExiting) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400585 total_read = -ESHUTDOWN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400586 break;
587 } else if (server->tcpStatus == CifsNeedReconnect) {
588 cifs_reconnect(server);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400589 total_read = -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400590 break;
591 } else if (length == -ERESTARTSYS ||
592 length == -EAGAIN ||
593 length == -EINTR) {
594 /*
595 * Minimum sleep to prevent looping, allowing socket
596 * to clear and app threads to set tcpStatus
597 * CifsNeedReconnect if server hung.
598 */
599 usleep_range(1000, 2000);
600 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400601 continue;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400602 } else if (length <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500603 cifs_dbg(FYI, "Received no data or error: expecting %d\n"
604 "got %d", to_read, length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400605 cifs_reconnect(server);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400606 total_read = -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400607 break;
608 }
609 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400610 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400611}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400612
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400613int
614cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
615 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400616{
617 struct kvec iov;
618
619 iov.iov_base = buf;
620 iov.iov_len = to_read;
621
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400622 return cifs_readv_from_socket(server, &iov, 1, to_read);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400623}
624
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400625static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400626is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400627{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400628 /*
629 * The first byte big endian of the length field,
630 * is actually not part of the length but the type
631 * with the most common, zero, as regular data.
632 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400633 switch (type) {
634 case RFC1002_SESSION_MESSAGE:
635 /* Regular SMB response */
636 return true;
637 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500638 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400639 break;
640 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500641 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400642 break;
643 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400644 /*
645 * We get this from Windows 98 instead of an error on
646 * SMB negprot response.
647 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500648 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400649 /* give server a second to clean up */
650 msleep(1000);
651 /*
652 * Always try 445 first on reconnect since we get NACK
653 * on some if we ever connected to port 139 (the NACK
654 * is since we do not begin with RFC1001 session
655 * initialize frame).
656 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400657 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400658 cifs_reconnect(server);
659 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400660 break;
661 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500662 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400663 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400664 }
665
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400666 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400667}
668
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400669void
670dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400671{
672#ifdef CONFIG_CIFS_STATS2
673 mid->when_received = jiffies;
674#endif
675 spin_lock(&GlobalMid_Lock);
676 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400677 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400678 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400679 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400680 list_del_init(&mid->qhead);
681 spin_unlock(&GlobalMid_Lock);
682}
683
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400684static void
685handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400686 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400687{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400688 if (server->ops->check_trans2 &&
689 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400690 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400691 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400692 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400693 /* Was previous buf put in mpx struct for multi-rsp? */
694 if (!mid->multiRsp) {
695 /* smb buffer will be freed by user thread */
696 if (server->large_buf)
697 server->bigbuf = NULL;
698 else
699 server->smallbuf = NULL;
700 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400701 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400702}
703
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400704static void clean_demultiplex_info(struct TCP_Server_Info *server)
705{
706 int length;
707
708 /* take it off the list, if it's not already */
709 spin_lock(&cifs_tcp_ses_lock);
710 list_del_init(&server->tcp_ses_list);
711 spin_unlock(&cifs_tcp_ses_lock);
712
713 spin_lock(&GlobalMid_Lock);
714 server->tcpStatus = CifsExiting;
715 spin_unlock(&GlobalMid_Lock);
716 wake_up_all(&server->response_q);
717
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400718 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300719 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400720 if (server->credits <= 0)
721 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300722 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400723 /*
724 * Although there should not be any requests blocked on this queue it
725 * can not hurt to be paranoid and try to wake up requests that may
726 * haven been blocked when more than 50 at time were on the wire to the
727 * same server - they now will see the session is in exit state and get
728 * out of SendReceive.
729 */
730 wake_up_all(&server->request_q);
731 /* give those requests time to exit */
732 msleep(125);
733
734 if (server->ssocket) {
735 sock_release(server->ssocket);
736 server->ssocket = NULL;
737 }
738
739 if (!list_empty(&server->pending_mid_q)) {
740 struct list_head dispose_list;
741 struct mid_q_entry *mid_entry;
742 struct list_head *tmp, *tmp2;
743
744 INIT_LIST_HEAD(&dispose_list);
745 spin_lock(&GlobalMid_Lock);
746 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
747 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500748 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400749 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400750 list_move(&mid_entry->qhead, &dispose_list);
751 }
752 spin_unlock(&GlobalMid_Lock);
753
754 /* now walk dispose list and issue callbacks */
755 list_for_each_safe(tmp, tmp2, &dispose_list) {
756 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500757 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400758 list_del_init(&mid_entry->qhead);
759 mid_entry->callback(mid_entry);
760 }
761 /* 1/8th of sec is more than enough time for them to exit */
762 msleep(125);
763 }
764
765 if (!list_empty(&server->pending_mid_q)) {
766 /*
767 * mpx threads have not exited yet give them at least the smb
768 * send timeout time for long ops.
769 *
770 * Due to delays on oplock break requests, we need to wait at
771 * least 45 seconds before giving up on a request getting a
772 * response and going ahead and killing cifsd.
773 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500774 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400775 msleep(46000);
776 /*
777 * If threads still have not exited they are probably never
778 * coming home not much else we can do but free the memory.
779 */
780 }
781
782 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400783 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400784 kfree(server);
785
786 length = atomic_dec_return(&tcpSesAllocCount);
787 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700788 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400789}
790
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400791static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400792standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
793{
794 int length;
795 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400796 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400797
798 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400799 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500800 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400801 cifs_reconnect(server);
802 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400803 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400804 }
805
806 /* switch to large buffer if too big for a small one */
807 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
808 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400809 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400810 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400811 }
812
813 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400814 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
815 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400816 if (length < 0)
817 return length;
818 server->total_read += length;
819
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400820 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400821
822 /*
823 * We know that we received enough to get to the MID as we
824 * checked the pdu_length earlier. Now check to see
825 * if the rest of the header is OK. We borrow the length
826 * var for the rest of the loop to avoid a new stack var.
827 *
828 * 48 bytes is enough to display the header and a little bit
829 * into the payload for debugging purposes.
830 */
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400831 length = server->ops->check_message(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400832 if (length != 0)
833 cifs_dump_mem("Bad SMB: ", buf,
834 min_t(unsigned int, server->total_read, 48));
835
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700836 if (server->ops->is_status_pending &&
837 server->ops->is_status_pending(buf, server, length))
838 return -1;
839
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500840 if (!mid)
841 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400842
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400843 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500844 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400845}
846
847static int
Al Viro7c97c202011-06-21 08:51:28 -0400848cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849{
850 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400851 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400852 unsigned int pdu_length;
853 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500854 struct task_struct *task_to_wake = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500858 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400859
860 length = atomic_inc_return(&tcpSesAllocCount);
861 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700862 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700864 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000865 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700866 if (try_to_freeze())
867 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700868
Jeff Layton2a37ef92011-10-19 15:29:23 -0400869 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400870 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700871
Jeff Layton2a37ef92011-10-19 15:29:23 -0400872 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400873 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000874 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000875
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400876 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400877 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000878 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400879 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700880
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400881 /*
882 * The right amount was read from socket - 4 bytes,
883 * so we can now interpret the length field.
884 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400885 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700886
Joe Perchesf96637b2013-05-04 22:12:25 -0500887 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400888 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000889 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700890
Jeff Layton89482a52011-10-19 15:28:57 -0400891 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400892 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500893 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
894 pdu_length);
Jeff Layton89482a52011-10-19 15:28:57 -0400895 cifs_reconnect(server);
896 wake_up(&server->response_q);
897 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700898 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400899
Jeff Layton89482a52011-10-19 15:28:57 -0400900 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400901 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400902 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -0400903 if (length < 0)
904 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400905 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400906
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400907 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400908
Jeff Layton44d22d82011-10-19 15:29:49 -0400909 if (!mid_entry || !mid_entry->receive)
910 length = standard_receive3(server, mid_entry);
911 else
912 length = mid_entry->receive(server, mid_entry);
913
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400914 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700915 continue;
916
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400917 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400918 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700919
Steve Frenchfda35942011-01-20 18:06:34 +0000920 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500921 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -0400922 if (!mid_entry->multiRsp || mid_entry->multiEnd)
923 mid_entry->callback(mid_entry);
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400924 } else if (!server->ops->is_oplock_break ||
925 !server->ops->is_oplock_break(buf, server)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500926 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
927 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400928 cifs_dump_mem("Received Data is: ", buf,
929 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000930#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400931 if (server->ops->dump_detail)
932 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +0000933 cifs_dump_mids(server);
934#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000935
Steve Frenche4eb2952005-04-28 22:41:09 -0700936 }
937 } /* end while !EXITING */
938
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800939 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400940 cifs_buf_release(server->bigbuf);
941 if (server->smallbuf) /* no sense logging a debug message if NULL */
942 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500944 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400945 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500946
947 /* if server->tsk was NULL then wait for a signal before exiting */
948 if (!task_to_wake) {
949 set_current_state(TASK_INTERRUPTIBLE);
950 while (!signal_pending(current)) {
951 schedule();
952 set_current_state(TASK_INTERRUPTIBLE);
953 }
954 set_current_state(TASK_RUNNING);
955 }
956
Jeff Layton0468a2c2008-12-01 07:09:35 -0500957 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958}
959
Jeff Laytonc359cf32007-11-16 22:22:06 +0000960/* extract the host portion of the UNC string */
961static char *
962extract_hostname(const char *unc)
963{
964 const char *src;
965 char *dst, *delim;
966 unsigned int len;
967
968 /* skip double chars at beginning of string */
969 /* BB: check validity of these bytes? */
970 src = unc + 2;
971
972 /* delimiter between hostname and sharename is always '\\' now */
973 delim = strchr(src, '\\');
974 if (!delim)
975 return ERR_PTR(-EINVAL);
976
977 len = delim - src;
978 dst = kmalloc((len + 1), GFP_KERNEL);
979 if (dst == NULL)
980 return ERR_PTR(-ENOMEM);
981
982 memcpy(dst, src, len);
983 dst[len] = '\0';
984
985 return dst;
986}
987
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400988static int get_option_ul(substring_t args[], unsigned long *option)
989{
990 int rc;
991 char *string;
992
993 string = match_strdup(args);
994 if (string == NULL)
995 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +0100996 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400997 kfree(string);
998
999 return rc;
1000}
1001
Eric W. Biederman3da46562013-02-06 01:37:39 -08001002static int get_option_uid(substring_t args[], kuid_t *result)
1003{
1004 unsigned long value;
1005 kuid_t uid;
1006 int rc;
1007
1008 rc = get_option_ul(args, &value);
1009 if (rc)
1010 return rc;
1011
1012 uid = make_kuid(current_user_ns(), value);
1013 if (!uid_valid(uid))
1014 return -EINVAL;
1015
1016 *result = uid;
1017 return 0;
1018}
1019
1020static int get_option_gid(substring_t args[], kgid_t *result)
1021{
1022 unsigned long value;
1023 kgid_t gid;
1024 int rc;
1025
1026 rc = get_option_ul(args, &value);
1027 if (rc)
1028 return rc;
1029
1030 gid = make_kgid(current_user_ns(), value);
1031 if (!gid_valid(gid))
1032 return -EINVAL;
1033
1034 *result = gid;
1035 return 0;
1036}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001037
1038static int cifs_parse_security_flavors(char *value,
1039 struct smb_vol *vol)
1040{
1041
1042 substring_t args[MAX_OPT_ARGS];
1043
Jeff Layton1e3cc572013-06-10 17:12:23 -05001044 /*
1045 * With mount options, the last one should win. Reset any existing
1046 * settings back to default.
1047 */
1048 vol->sectype = Unspecified;
1049 vol->sign = false;
1050
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001051 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001052 case Opt_sec_krb5p:
1053 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1054 return 1;
1055 case Opt_sec_krb5i:
1056 vol->sign = true;
1057 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001058 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001059 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001060 break;
1061 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001062 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001063 /* Fallthrough */
1064 case Opt_sec_ntlmssp:
1065 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001066 break;
1067 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001068 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001069 /* Fallthrough */
1070 case Opt_ntlm:
1071 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001072 break;
1073 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001074 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001075 /* Fallthrough */
1076 case Opt_sec_ntlmv2:
1077 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001078 break;
1079#ifdef CONFIG_CIFS_WEAK_PW_HASH
1080 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001081 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001082 break;
1083#endif
1084 case Opt_sec_none:
1085 vol->nullauth = 1;
1086 break;
1087 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001088 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001089 return 1;
1090 }
1091
1092 return 0;
1093}
1094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001096cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1097{
1098 substring_t args[MAX_OPT_ARGS];
1099
1100 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1101 case Opt_cache_loose:
1102 vol->direct_io = false;
1103 vol->strict_io = false;
1104 break;
1105 case Opt_cache_strict:
1106 vol->direct_io = false;
1107 vol->strict_io = true;
1108 break;
1109 case Opt_cache_none:
1110 vol->direct_io = true;
1111 vol->strict_io = false;
1112 break;
1113 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001114 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001115 return 1;
1116 }
1117 return 0;
1118}
1119
1120static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001121cifs_parse_smb_version(char *value, struct smb_vol *vol)
1122{
1123 substring_t args[MAX_OPT_ARGS];
1124
1125 switch (match_token(value, cifs_smb_version_tokens, args)) {
1126 case Smb_1:
1127 vol->ops = &smb1_operations;
1128 vol->vals = &smb1_values;
1129 break;
Steve French1080ef72011-02-24 18:07:19 +00001130#ifdef CONFIG_CIFS_SMB2
Steve Frenchdd446b12012-11-28 23:21:06 -06001131 case Smb_20:
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001132 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001133 vol->vals = &smb20_values;
1134 break;
Steve French1080ef72011-02-24 18:07:19 +00001135 case Smb_21:
1136 vol->ops = &smb21_operations;
1137 vol->vals = &smb21_values;
1138 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001139 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001140 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001141 vol->vals = &smb30_values;
1142 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001143 case Smb_302:
1144 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1145 vol->vals = &smb302_values;
1146 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001147#ifdef CONFIG_CIFS_SMB311
1148 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001149 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001150 vol->vals = &smb311_values;
1151 break;
1152#endif /* SMB311 */
Steve French1080ef72011-02-24 18:07:19 +00001153#endif
Jeff Layton23db65f2012-05-15 12:20:51 -04001154 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001155 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001156 return 1;
1157 }
1158 return 0;
1159}
1160
Jeff Laytond387a5c2012-12-10 06:10:46 -05001161/*
1162 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1163 * fields with the result. Returns 0 on success and an error otherwise.
1164 */
1165static int
1166cifs_parse_devname(const char *devname, struct smb_vol *vol)
1167{
1168 char *pos;
1169 const char *delims = "/\\";
1170 size_t len;
1171
1172 /* make sure we have a valid UNC double delimiter prefix */
1173 len = strspn(devname, delims);
1174 if (len != 2)
1175 return -EINVAL;
1176
1177 /* find delimiter between host and sharename */
1178 pos = strpbrk(devname + 2, delims);
1179 if (!pos)
1180 return -EINVAL;
1181
1182 /* skip past delimiter */
1183 ++pos;
1184
1185 /* now go until next delimiter or end of string */
1186 len = strcspn(pos, delims);
1187
1188 /* move "pos" up to delimiter or NULL */
1189 pos += len;
1190 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1191 if (!vol->UNC)
1192 return -ENOMEM;
1193
1194 convert_delimiter(vol->UNC, '\\');
1195
1196 /* If pos is NULL, or is a bogus trailing delimiter then no prepath */
1197 if (!*pos++ || !*pos)
1198 return 0;
1199
1200 vol->prepath = kstrdup(pos, GFP_KERNEL);
1201 if (!vol->prepath)
1202 return -ENOMEM;
1203
1204 return 0;
1205}
1206
Jeff Layton23db65f2012-05-15 12:20:51 -04001207static int
Sean Finneyb9468452011-04-11 13:19:32 +00001208cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001209 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001211 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001212 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 unsigned int temp_len, i, j;
1214 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001215 short int override_uid = -1;
1216 short int override_gid = -1;
1217 bool uid_specified = false;
1218 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001219 bool sloppy = false;
1220 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001221 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001222 char *string = NULL;
1223 char *tmp_end, *value;
1224 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001225 bool got_ip = false;
1226 unsigned short port = 0;
1227 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001230 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001231 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
Jeff Layton6ee95422012-11-26 11:09:57 -05001233 /* ensure we always start with zeroed-out smb_vol */
1234 memset(vol, 0, sizeof(*vol));
1235
Jeff Layton88463992010-11-22 15:31:03 -05001236 /*
1237 * does not have to be perfect mapping since field is
1238 * informational, only used for servers that do not support
1239 * port 445 and it can be overridden at mount time
1240 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001241 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1242 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001243 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1244
Jeff Layton1397f2e2011-01-07 11:30:28 -05001245 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001246 /* null target name indicates to use *SMBSERVR default called name
1247 if we end up sending RFC1001 session initialize */
1248 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001249 vol->cred_uid = current_uid();
1250 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001251 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001252
Steve French2baa2682014-09-27 02:19:01 -05001253 /*
1254 * default to SFM style remapping of seven reserved characters
1255 * unless user overrides it or we negotiate CIFS POSIX where
1256 * it is unnecessary. Can not simultaneously use more than one mapping
1257 * since then readdir could list files that open could not open
1258 */
1259 vol->remap = true;
1260
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001261 /* default to only allowing write access to owner of the mount */
1262 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
1264 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001265 /* default is always to request posix paths. */
1266 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001267 /* default to using server inode numbers where available */
1268 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001269
Jeff Layton1b359202012-09-19 15:20:27 -07001270 /* default is to use strict cifs caching semantics */
1271 vol->strict_io = true;
1272
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301273 vol->actimeo = CIFS_DEF_ACTIMEO;
1274
Jeff Layton23db65f2012-05-15 12:20:51 -04001275 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1276 vol->ops = &smb1_operations;
1277 vol->vals = &smb1_values;
1278
Sean Finneyb9468452011-04-11 13:19:32 +00001279 if (!mountdata)
1280 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Sean Finneyb9468452011-04-11 13:19:32 +00001282 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1283 if (!mountdata_copy)
1284 goto cifs_parse_mount_err;
1285
1286 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001287 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001288
Steve French50c2f752007-07-13 00:33:32 +00001289 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001290 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 separator[0] = options[4];
1292 options += 5;
1293 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001294 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 }
1296 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001297 vol->backupuid_specified = false; /* no backup intent for a user */
1298 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001299
Jeff Layton37d4f992013-05-24 07:40:05 -04001300 switch (cifs_parse_devname(devname, vol)) {
1301 case 0:
1302 break;
1303 case -ENOMEM:
1304 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1305 goto cifs_parse_mount_err;
1306 case -EINVAL:
1307 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1308 goto cifs_parse_mount_err;
1309 default:
1310 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1311 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001312 }
1313
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001315 substring_t args[MAX_OPT_ARGS];
1316 unsigned long option;
1317 int token;
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 if (!*data)
1320 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001322 token = match_token(data, cifs_mount_option_tokens, args);
1323
1324 switch (token) {
1325
1326 /* Ingnore the following */
1327 case Opt_ignore:
1328 break;
1329
1330 /* Boolean values */
1331 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001333 break;
1334 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001336 break;
1337 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001338 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001339 break;
1340 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001341 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001342 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001343 case Opt_forcegid:
1344 override_gid = 1;
1345 break;
1346 case Opt_noforcegid:
1347 override_gid = 0;
1348 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001349 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001350 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001351 break;
1352 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001353 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001354 break;
1355 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001357 break;
1358 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001360 break;
1361 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001363 break;
1364 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001366 break;
1367 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001368 vol->sfu_remap = true;
1369 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001370 break;
1371 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001372 vol->sfu_remap = false;
1373 break;
1374 case Opt_mapposix:
1375 vol->remap = true;
1376 vol->sfu_remap = false; /* disable SFU mapping */
1377 break;
1378 case Opt_nomapposix:
1379 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
1381 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001382 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001385 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001388 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
1390 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001391 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 break;
1393 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001394 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001395 break;
1396 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001397 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001398 break;
1399 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001400 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001401 break;
1402 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001403 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001404 break;
1405 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001406 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001407 /*
1408 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001409 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001410 * local vfs will do advisory
1411 */
Steve French50c2f752007-07-13 00:33:32 +00001412 if (vol->file_mode ==
1413 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001414 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001417 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
1425 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001426 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 break;
1428 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001429 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001439 break;
1440 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
1443 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001444 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001447 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 break;
1452 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001454 break;
1455 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001456 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001457 break;
1458 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001459 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 break;
1461 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001462 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001463 break;
1464 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001466 break;
1467 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001469 break;
1470 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001471 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001472 break;
1473 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001474 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001475 break;
1476 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001477 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001478 * is a per tree connection (mount) not a per socket
1479 * or per-smb connection option in the protocol
1480 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1481 */
Steve French95b1cb92008-05-15 16:44:38 +00001482 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001483 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001484 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001485 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001486 break;
1487 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301488#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001489 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001490 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301491#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301492 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001493 break;
1494 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001495 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001496 break;
1497 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001498 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001499 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001500 case Opt_sloppy:
1501 sloppy = true;
1502 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001503 case Opt_nosharesock:
1504 vol->nosharesock = true;
1505 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001506 case Opt_nopersistent:
1507 vol->nopersistent = true;
1508 if (vol->persistent) {
1509 cifs_dbg(VFS,
1510 "persistenthandles mount options conflict\n");
1511 goto cifs_parse_mount_err;
1512 }
1513 break;
1514 case Opt_persistent:
1515 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001516 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001517 cifs_dbg(VFS,
1518 "persistenthandles mount options conflict\n");
1519 goto cifs_parse_mount_err;
1520 }
1521 break;
Steve French592fafe2015-11-03 10:08:53 -06001522 case Opt_resilient:
1523 vol->resilient = true;
1524 if (vol->persistent) {
1525 cifs_dbg(VFS,
1526 "persistenthandles mount options conflict\n");
1527 goto cifs_parse_mount_err;
1528 }
1529 break;
1530 case Opt_noresilient:
1531 vol->resilient = false; /* already the default */
1532 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001533
1534 /* Numeric Values */
1535 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001536 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001537 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1538 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001539 goto cifs_parse_mount_err;
1540 }
1541 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001542 break;
1543 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001544 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001545 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1546 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001547 goto cifs_parse_mount_err;
1548 }
1549 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001550 break;
1551 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001552 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001553 cifs_dbg(VFS, "%s: Invalid uid value\n",
1554 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001555 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001557 uid_specified = true;
1558 break;
1559 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001560 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001561 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1562 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001563 goto cifs_parse_mount_err;
1564 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001565 break;
1566 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001567 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001568 cifs_dbg(VFS, "%s: Invalid gid value\n",
1569 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001570 goto cifs_parse_mount_err;
1571 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001572 gid_specified = true;
1573 break;
1574 case Opt_file_mode:
1575 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001576 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1577 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001578 goto cifs_parse_mount_err;
1579 }
1580 vol->file_mode = option;
1581 break;
1582 case Opt_dirmode:
1583 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001584 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1585 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001586 goto cifs_parse_mount_err;
1587 }
1588 vol->dir_mode = option;
1589 break;
1590 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001591 if (get_option_ul(args, &option) ||
1592 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001593 cifs_dbg(VFS, "%s: Invalid port value\n",
1594 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001595 goto cifs_parse_mount_err;
1596 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001597 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001598 break;
1599 case Opt_rsize:
1600 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001601 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1602 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001603 goto cifs_parse_mount_err;
1604 }
1605 vol->rsize = option;
1606 break;
1607 case Opt_wsize:
1608 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001609 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1610 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001611 goto cifs_parse_mount_err;
1612 }
1613 vol->wsize = option;
1614 break;
1615 case Opt_actimeo:
1616 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001617 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1618 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001619 goto cifs_parse_mount_err;
1620 }
1621 vol->actimeo = HZ * option;
1622 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001623 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001624 goto cifs_parse_mount_err;
1625 }
1626 break;
1627
1628 /* String Arguments */
1629
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001630 case Opt_blank_user:
1631 /* null user, ie. anonymous authentication */
1632 vol->nullauth = 1;
1633 vol->username = NULL;
1634 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001635 case Opt_user:
1636 string = match_strdup(args);
1637 if (string == NULL)
1638 goto out_nomem;
1639
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001640 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1641 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001642 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001643 goto cifs_parse_mount_err;
1644 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001645
1646 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001647 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001648 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001649 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001650 break;
1651 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001652 /* passwords have to be handled differently
1653 * to allow the character used for deliminator
1654 * to be passed within them
1655 */
1656
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001657 /*
1658 * Check if this is a case where the password
1659 * starts with a delimiter
1660 */
1661 tmp_end = strchr(data, '=');
1662 tmp_end++;
1663 if (!(tmp_end < end && tmp_end[1] == delim)) {
1664 /* No it is not. Set the password to NULL */
Namjae Jeond6ccf492014-08-21 19:11:20 +09001665 kfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001666 vol->password = NULL;
1667 break;
1668 }
1669 /* Yes it is. Drop down to Opt_pass below.*/
1670 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001671 /* Obtain the value string */
1672 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001673 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001674
1675 /* Set tmp_end to end of the string */
1676 tmp_end = (char *) value + strlen(value);
1677
1678 /* Check if following character is the deliminator
1679 * If yes, we have encountered a double deliminator
1680 * reset the NULL character to the deliminator
1681 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301682 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001683 tmp_end[0] = delim;
1684
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301685 /* Keep iterating until we get to a single
1686 * deliminator OR the end
1687 */
1688 while ((tmp_end = strchr(tmp_end, delim))
1689 != NULL && (tmp_end[1] == delim)) {
1690 tmp_end = (char *) &tmp_end[2];
1691 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001692
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301693 /* Reset var options to point to next element */
1694 if (tmp_end) {
1695 tmp_end[0] = '\0';
1696 options = (char *) &tmp_end[1];
1697 } else
1698 /* Reached the end of the mount option
1699 * string */
1700 options = end;
1701 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001702
Namjae Jeond6ccf492014-08-21 19:11:20 +09001703 kfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001704 /* Now build new password string */
1705 temp_len = strlen(value);
1706 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1707 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001708 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001709 goto cifs_parse_mount_err;
1710 }
1711
1712 for (i = 0, j = 0; i < temp_len; i++, j++) {
1713 vol->password[j] = value[i];
1714 if ((value[i] == delim) &&
1715 value[i+1] == delim)
1716 /* skip the second deliminator */
1717 i++;
1718 }
1719 vol->password[j] = '\0';
1720 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001721 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001722 /* FIXME: should this be an error instead? */
1723 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001724 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001725 case Opt_ip:
1726 string = match_strdup(args);
1727 if (string == NULL)
1728 goto out_nomem;
1729
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001730 if (!cifs_convert_address(dstaddr, string,
1731 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001732 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 goto cifs_parse_mount_err;
1734 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001735 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001736 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001737 case Opt_domain:
1738 string = match_strdup(args);
1739 if (string == NULL)
1740 goto out_nomem;
1741
Chen Gang057d6332013-07-19 09:01:36 +08001742 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
1743 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001744 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 goto cifs_parse_mount_err;
1746 }
1747
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001748 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001749 vol->domainname = kstrdup(string, GFP_KERNEL);
1750 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001751 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001752 goto cifs_parse_mount_err;
1753 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001754 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001755 break;
1756 case Opt_srcaddr:
1757 string = match_strdup(args);
1758 if (string == NULL)
1759 goto out_nomem;
1760
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001761 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001762 (struct sockaddr *)&vol->srcaddr,
1763 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001764 pr_warn("CIFS: Could not parse srcaddr: %s\n",
1765 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001766 goto cifs_parse_mount_err;
1767 }
1768 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001769 case Opt_iocharset:
1770 string = match_strdup(args);
1771 if (string == NULL)
1772 goto out_nomem;
1773
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001774 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001775 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 goto cifs_parse_mount_err;
1777 }
1778
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001779 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001780 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001781 vol->iocharset = kstrdup(string,
1782 GFP_KERNEL);
1783 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001784 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001785 goto cifs_parse_mount_err;
1786 }
1787 }
1788 /* if iocharset not set then load_nls_default
1789 * is used by caller
1790 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001791 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001793 case Opt_netbiosname:
1794 string = match_strdup(args);
1795 if (string == NULL)
1796 goto out_nomem;
1797
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001798 memset(vol->source_rfc1001_name, 0x20,
1799 RFC1001_NAME_LEN);
1800 /*
1801 * FIXME: are there cases in which a comma can
1802 * be valid in workstation netbios name (and
1803 * need special handling)?
1804 */
1805 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1806 /* don't ucase netbiosname for user */
1807 if (string[i] == 0)
1808 break;
1809 vol->source_rfc1001_name[i] = string[i];
1810 }
1811 /* The string has 16th byte zero still from
1812 * set at top of the function
1813 */
1814 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001815 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 break;
1817 case Opt_servern:
1818 /* servernetbiosname specified override *SMBSERVER */
1819 string = match_strdup(args);
1820 if (string == NULL)
1821 goto out_nomem;
1822
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001823 /* last byte, type, is 0x20 for servr type */
1824 memset(vol->target_rfc1001_name, 0x20,
1825 RFC1001_NAME_LEN_WITH_NULL);
1826
1827 /* BB are there cases in which a comma can be
1828 valid in this workstation netbios name
1829 (and need special handling)? */
1830
1831 /* user or mount helper must uppercase the
1832 netbios name */
1833 for (i = 0; i < 15; i++) {
1834 if (string[i] == 0)
1835 break;
1836 vol->target_rfc1001_name[i] = string[i];
1837 }
1838 /* The string has 16th byte zero still from
1839 set at top of the function */
1840 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001841 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001842 break;
1843 case Opt_ver:
1844 string = match_strdup(args);
1845 if (string == NULL)
1846 goto out_nomem;
1847
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001848 if (strncasecmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001849 /* This is the default */
1850 break;
1851 }
1852 /* For all other value, error */
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001853 pr_warn("CIFS: Invalid version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001854 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001855 case Opt_vers:
1856 string = match_strdup(args);
1857 if (string == NULL)
1858 goto out_nomem;
1859
1860 if (cifs_parse_smb_version(string, vol) != 0)
1861 goto cifs_parse_mount_err;
1862 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001863 case Opt_sec:
1864 string = match_strdup(args);
1865 if (string == NULL)
1866 goto out_nomem;
1867
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001868 if (cifs_parse_security_flavors(string, vol) != 0)
1869 goto cifs_parse_mount_err;
1870 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001871 case Opt_cache:
1872 string = match_strdup(args);
1873 if (string == NULL)
1874 goto out_nomem;
1875
1876 if (cifs_parse_cache_flavor(string, vol) != 0)
1877 goto cifs_parse_mount_err;
1878 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001879 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001880 /*
1881 * An option we don't recognize. Save it off for later
1882 * if we haven't already found one
1883 */
1884 if (!invalid)
1885 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001886 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001888 /* Free up any allocated string */
1889 kfree(string);
1890 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001892
Jeff Laytond8162552012-03-23 14:40:56 -04001893 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001894 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04001895 goto cifs_parse_mount_err;
1896 }
1897
Jeff Layton8a8798a2012-01-17 16:09:15 -05001898#ifndef CONFIG_KEYS
1899 /* Muliuser mounts require CONFIG_KEYS support */
1900 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001901 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001902 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001903 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001904#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001905 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04001906 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001907 goto cifs_parse_mount_err;
1908 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001909
Jeff Layton62a1a432012-12-10 06:10:45 -05001910 /* make sure UNC has a share name */
1911 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001912 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05001913 goto cifs_parse_mount_err;
1914 }
1915
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001916 if (!got_ip) {
1917 /* No ip= option specified? Try to get it from UNC */
1918 if (!cifs_convert_address(dstaddr, &vol->UNC[2],
1919 strlen(&vol->UNC[2]))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001920 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001921 goto cifs_parse_mount_err;
1922 }
1923 }
1924
1925 /* set the port that we got earlier */
1926 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001928 if (uid_specified)
1929 vol->override_uid = override_uid;
1930 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001931 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001932
1933 if (gid_specified)
1934 vol->override_gid = override_gid;
1935 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001936 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001937
Sean Finneyb9468452011-04-11 13:19:32 +00001938 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001940
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001941out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001942 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001943cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001944 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001945 kfree(mountdata_copy);
1946 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947}
1948
Ben Greear3eb9a882010-09-01 17:06:02 -07001949/** Returns true if srcaddr isn't specified and rhs isn't
1950 * specified, or if srcaddr is specified and
1951 * matches the IP address of the rhs argument.
1952 */
Jeff Layton45151482010-07-06 20:43:02 -04001953static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001954srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1955{
1956 switch (srcaddr->sa_family) {
1957 case AF_UNSPEC:
1958 return (rhs->sa_family == AF_UNSPEC);
1959 case AF_INET: {
1960 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1961 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1962 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1963 }
1964 case AF_INET6: {
1965 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05001966 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07001967 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1968 }
1969 default:
1970 WARN_ON(1);
1971 return false; /* don't expect to be here */
1972 }
1973}
1974
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001975/*
1976 * If no port is specified in addr structure, we try to match with 445 port
1977 * and if it fails - with 139 ports. It should be called only if address
1978 * families of server and addr are equal.
1979 */
1980static bool
1981match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1982{
Steve French6da97912011-03-13 18:55:55 +00001983 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001984
1985 switch (addr->sa_family) {
1986 case AF_INET:
1987 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1988 port = ((struct sockaddr_in *) addr)->sin_port;
1989 break;
1990 case AF_INET6:
1991 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1992 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1993 break;
1994 default:
1995 WARN_ON(1);
1996 return false;
1997 }
1998
1999 if (!port) {
2000 port = htons(CIFS_PORT);
2001 if (port == *sport)
2002 return true;
2003
2004 port = htons(RFC1001_PORT);
2005 }
2006
2007 return port == *sport;
2008}
Ben Greear3eb9a882010-09-01 17:06:02 -07002009
2010static bool
2011match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2012 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
Jeff Layton45151482010-07-06 20:43:02 -04002014 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002015 case AF_INET: {
2016 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2017 struct sockaddr_in *srv_addr4 =
2018 (struct sockaddr_in *)&server->dstaddr;
2019
2020 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002021 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002022 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002023 }
2024 case AF_INET6: {
2025 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2026 struct sockaddr_in6 *srv_addr6 =
2027 (struct sockaddr_in6 *)&server->dstaddr;
2028
Jeff Layton45151482010-07-06 20:43:02 -04002029 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002030 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002031 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002032 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002033 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002034 break;
2035 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002036 default:
2037 WARN_ON(1);
2038 return false; /* don't expect to be here */
2039 }
Jeff Layton45151482010-07-06 20:43:02 -04002040
Ben Greear3eb9a882010-09-01 17:06:02 -07002041 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2042 return false;
2043
Jeff Layton45151482010-07-06 20:43:02 -04002044 return true;
2045}
2046
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002047static bool
2048match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2049{
Jeff Layton3f618222013-06-12 19:52:14 -05002050 /*
2051 * The select_sectype function should either return the vol->sectype
2052 * that was specified, or "Unspecified" if that sectype was not
2053 * compatible with the given NEGOTIATE request.
2054 */
2055 if (select_sectype(server, vol->sectype) == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002056 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002057
Jeff Layton3f618222013-06-12 19:52:14 -05002058 /*
2059 * Now check if signing mode is acceptable. No need to check
2060 * global_secflags at this point since if MUST_SIGN is set then
2061 * the server->sign had better be too.
2062 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002063 if (vol->sign && !server->sign)
2064 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002065
2066 return true;
2067}
2068
Jeff Layton9fa114f2012-11-26 11:09:57 -05002069static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002070{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002071 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2072
Jeff Laytona0b3df52013-05-24 07:40:59 -04002073 if (vol->nosharesock)
2074 return 0;
2075
Jeff Layton23db65f2012-05-15 12:20:51 -04002076 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2077 return 0;
2078
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002079 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2080 return 0;
2081
2082 if (!match_address(server, addr,
2083 (struct sockaddr *)&vol->srcaddr))
2084 return 0;
2085
2086 if (!match_port(server, addr))
2087 return 0;
2088
2089 if (!match_security(server, vol))
2090 return 0;
2091
2092 return 1;
2093}
2094
Jeff Layton45151482010-07-06 20:43:02 -04002095static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002096cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002097{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002098 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302100 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002101 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002102 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002103 continue;
2104
Jeff Laytone7ddee92008-11-14 13:44:38 -05002105 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302106 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002107 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002108 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302110 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 return NULL;
2112}
2113
Jeff Layton14fbf502008-11-14 13:53:46 -05002114static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002115cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002117 struct task_struct *task;
2118
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302119 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002120 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302121 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002122 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002124
Rob Landleyf1d0c992011-01-22 15:44:05 -06002125 put_net(cifs_net_ns(server));
2126
Jeff Laytone7ddee92008-11-14 13:44:38 -05002127 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302128 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002129
Jeff Laytonc74093b2011-01-11 07:24:23 -05002130 cancel_delayed_work_sync(&server->echo);
2131
Jeff Laytone7ddee92008-11-14 13:44:38 -05002132 spin_lock(&GlobalMid_Lock);
2133 server->tcpStatus = CifsExiting;
2134 spin_unlock(&GlobalMid_Lock);
2135
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002136 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302137 cifs_fscache_release_client_cookie(server);
2138
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002139 kfree(server->session_key.response);
2140 server->session_key.response = NULL;
2141 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002142
2143 task = xchg(&server->tsk, NULL);
2144 if (task)
2145 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146}
2147
Jeff Layton63c038c2008-12-01 18:41:46 -05002148static struct TCP_Server_Info *
2149cifs_get_tcp_session(struct smb_vol *volume_info)
2150{
2151 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002152 int rc;
2153
Joe Perchesf96637b2013-05-04 22:12:25 -05002154 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002155
2156 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002157 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002158 if (tcp_ses)
2159 return tcp_ses;
2160
2161 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2162 if (!tcp_ses) {
2163 rc = -ENOMEM;
2164 goto out_err;
2165 }
2166
Jeff Layton23db65f2012-05-15 12:20:51 -04002167 tcp_ses->ops = volume_info->ops;
2168 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002169 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002170 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2171 if (IS_ERR(tcp_ses->hostname)) {
2172 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002173 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002174 }
2175
2176 tcp_ses->noblocksnd = volume_info->noblocksnd;
2177 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002178 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002179 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002180 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002181 init_waitqueue_head(&tcp_ses->response_q);
2182 init_waitqueue_head(&tcp_ses->request_q);
2183 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2184 mutex_init(&tcp_ses->srv_mutex);
2185 memcpy(tcp_ses->workstation_RFC1001_name,
2186 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2187 memcpy(tcp_ses->server_RFC1001_name,
2188 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002189 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002190 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002191 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002192 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002193 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2194 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002195 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002196 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2197 sizeof(tcp_ses->srcaddr));
2198 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2199 sizeof(tcp_ses->dstaddr));
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002200#ifdef CONFIG_CIFS_SMB2
2201 get_random_bytes(tcp_ses->client_guid, SMB2_CLIENT_GUID_SIZE);
2202#endif
Jeff Layton63c038c2008-12-01 18:41:46 -05002203 /*
2204 * at this point we are the only ones with the pointer
2205 * to the struct since the kernel thread not created yet
2206 * no need to spinlock this init of tcpStatus or srv_count
2207 */
2208 tcp_ses->tcpStatus = CifsNew;
2209 ++tcp_ses->srv_count;
2210
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002211 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002212 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002213 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002214 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002215 }
2216
2217 /*
2218 * since we're in a cifs function already, we know that
2219 * this will succeed. No need for try_module_get().
2220 */
2221 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002222 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002223 tcp_ses, "cifsd");
2224 if (IS_ERR(tcp_ses->tsk)) {
2225 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002226 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002227 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002228 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002229 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002230 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002231
2232 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302233 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002234 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302235 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002236
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302237 cifs_fscache_get_client_cookie(tcp_ses);
2238
Jeff Laytonc74093b2011-01-11 07:24:23 -05002239 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002240 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002241
Jeff Layton63c038c2008-12-01 18:41:46 -05002242 return tcp_ses;
2243
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002244out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002245 cifs_crypto_shash_release(tcp_ses);
2246
Rob Landleyf1d0c992011-01-22 15:44:05 -06002247 put_net(cifs_net_ns(tcp_ses));
2248
Jeff Layton63c038c2008-12-01 18:41:46 -05002249out_err:
2250 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002251 if (!IS_ERR(tcp_ses->hostname))
2252 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002253 if (tcp_ses->ssocket)
2254 sock_release(tcp_ses->ssocket);
2255 kfree(tcp_ses);
2256 }
2257 return ERR_PTR(rc);
2258}
2259
Steve French96daf2b2011-05-27 04:34:02 +00002260static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002261{
Jeff Layton3f618222013-06-12 19:52:14 -05002262 if (vol->sectype != Unspecified &&
2263 vol->sectype != ses->sectype)
2264 return 0;
2265
2266 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002267 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002268 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002269 return 0;
2270 break;
2271 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002272 /* NULL username means anonymous session */
2273 if (ses->user_name == NULL) {
2274 if (!vol->nullauth)
2275 return 0;
2276 break;
2277 }
2278
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002279 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002280 if (strncmp(ses->user_name,
2281 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002282 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002283 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002284 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002285 ses->password != NULL &&
2286 strncmp(ses->password,
2287 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002288 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002289 return 0;
2290 }
2291 return 1;
2292}
2293
Steve French96daf2b2011-05-27 04:34:02 +00002294static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002295cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296{
Steve French96daf2b2011-05-27 04:34:02 +00002297 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302299 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002300 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002301 if (ses->status == CifsExiting)
2302 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002303 if (!match_session(ses, vol))
2304 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002305 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302306 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002307 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302309 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 return NULL;
2311}
2312
Jeff Layton14fbf502008-11-14 13:53:46 -05002313static void
Steve French96daf2b2011-05-27 04:34:02 +00002314cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002315{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002316 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002317 struct TCP_Server_Info *server = ses->server;
2318
Joe Perchesf96637b2013-05-04 22:12:25 -05002319 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002320
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302321 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002322 if (ses->status == CifsExiting) {
2323 spin_unlock(&cifs_tcp_ses_lock);
2324 return;
2325 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002326 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302327 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002328 return;
2329 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002330 if (ses->status == CifsGood)
2331 ses->status = CifsExiting;
2332 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002333
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002334 if (ses->status == CifsExiting && server->ops->logoff) {
2335 xid = get_xid();
2336 rc = server->ops->logoff(xid, ses);
2337 if (rc)
2338 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2339 __func__, rc);
2340 _free_xid(xid);
2341 }
2342
2343 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002344 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302345 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002346
Jeff Layton14fbf502008-11-14 13:53:46 -05002347 sesInfoFree(ses);
2348 cifs_put_tcp_session(server);
2349}
2350
Jeff Layton8a8798a2012-01-17 16:09:15 -05002351#ifdef CONFIG_KEYS
2352
Chen Gang057d6332013-07-19 09:01:36 +08002353/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2354#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002355
2356/* Populate username and pw fields from keyring if possible */
2357static int
2358cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2359{
2360 int rc = 0;
2361 char *desc, *delim, *payload;
2362 ssize_t len;
2363 struct key *key;
2364 struct TCP_Server_Info *server = ses->server;
2365 struct sockaddr_in *sa;
2366 struct sockaddr_in6 *sa6;
2367 struct user_key_payload *upayload;
2368
2369 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2370 if (!desc)
2371 return -ENOMEM;
2372
2373 /* try to find an address key first */
2374 switch (server->dstaddr.ss_family) {
2375 case AF_INET:
2376 sa = (struct sockaddr_in *)&server->dstaddr;
2377 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2378 break;
2379 case AF_INET6:
2380 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2381 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2382 break;
2383 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002384 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2385 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002386 rc = -EINVAL;
2387 goto out_err;
2388 }
2389
Joe Perchesf96637b2013-05-04 22:12:25 -05002390 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002391 key = request_key(&key_type_logon, desc, "");
2392 if (IS_ERR(key)) {
2393 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002394 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002395 rc = PTR_ERR(key);
2396 goto out_err;
2397 }
2398
2399 /* didn't work, try to find a domain key */
2400 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002401 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002402 key = request_key(&key_type_logon, desc, "");
2403 if (IS_ERR(key)) {
2404 rc = PTR_ERR(key);
2405 goto out_err;
2406 }
2407 }
2408
2409 down_read(&key->sem);
2410 upayload = key->payload.data;
2411 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002412 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002413 goto out_key_put;
2414 }
2415
2416 /* find first : in payload */
2417 payload = (char *)upayload->data;
2418 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002419 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002420 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002421 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2422 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002423 rc = -EINVAL;
2424 goto out_key_put;
2425 }
2426
2427 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002428 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002429 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2430 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002431 rc = -EINVAL;
2432 goto out_key_put;
2433 }
2434
2435 vol->username = kstrndup(payload, len, GFP_KERNEL);
2436 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002437 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2438 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002439 rc = -ENOMEM;
2440 goto out_key_put;
2441 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002442 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002443
2444 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002445 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002446 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002447 rc = -EINVAL;
2448 kfree(vol->username);
2449 vol->username = NULL;
2450 goto out_key_put;
2451 }
2452
2453 ++delim;
2454 vol->password = kstrndup(delim, len, GFP_KERNEL);
2455 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002456 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2457 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002458 rc = -ENOMEM;
2459 kfree(vol->username);
2460 vol->username = NULL;
2461 goto out_key_put;
2462 }
2463
2464out_key_put:
2465 up_read(&key->sem);
2466 key_put(key);
2467out_err:
2468 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002469 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002470 return rc;
2471}
2472#else /* ! CONFIG_KEYS */
2473static inline int
2474cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2475 struct cifs_ses *ses __attribute__((unused)))
2476{
2477 return -ENOSYS;
2478}
2479#endif /* CONFIG_KEYS */
2480
Steve French96daf2b2011-05-27 04:34:02 +00002481static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002482cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2483{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002484 int rc = -ENOMEM;
2485 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002486 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002487 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2488 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002489
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002490 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002491
Jeff Layton4ff67b72010-07-06 20:43:02 -04002492 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002493 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002494 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2495 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002496
Jeff Layton36988c72010-04-24 07:57:43 -04002497 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002498 rc = cifs_negotiate_protocol(xid, ses);
2499 if (rc) {
2500 mutex_unlock(&ses->session_mutex);
2501 /* problem -- put our ses reference */
2502 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002503 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002504 return ERR_PTR(rc);
2505 }
Jeff Layton36988c72010-04-24 07:57:43 -04002506 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002507 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002508 rc = cifs_setup_session(xid, ses,
2509 volume_info->local_nls);
2510 if (rc) {
2511 mutex_unlock(&ses->session_mutex);
2512 /* problem -- put our reference */
2513 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002514 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002515 return ERR_PTR(rc);
2516 }
2517 }
2518 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002519
2520 /* existing SMB ses has a server reference already */
2521 cifs_put_tcp_session(server);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002522 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002523 return ses;
2524 }
2525
Joe Perchesf96637b2013-05-04 22:12:25 -05002526 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002527 ses = sesInfoAlloc();
2528 if (ses == NULL)
2529 goto get_ses_fail;
2530
2531 /* new SMB session uses our server ref */
2532 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002533 if (server->dstaddr.ss_family == AF_INET6)
2534 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002535 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002536 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002537
Steve French8727c8a2011-02-25 01:11:56 -06002538 if (volume_info->username) {
2539 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2540 if (!ses->user_name)
2541 goto get_ses_fail;
2542 }
Jeff Layton36988c72010-04-24 07:57:43 -04002543
2544 /* volume_info->password freed at unmount */
2545 if (volume_info->password) {
2546 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2547 if (!ses->password)
2548 goto get_ses_fail;
2549 }
2550 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002551 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2552 if (!ses->domainName)
2553 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002554 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002555 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002556 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002557
Jeff Layton28e11bd2013-05-26 07:01:00 -04002558 ses->sectype = volume_info->sectype;
2559 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04002560
2561 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002562 rc = cifs_negotiate_protocol(xid, ses);
2563 if (!rc)
2564 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002565 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002566 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002567 goto get_ses_fail;
2568
2569 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302570 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002571 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302572 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002573
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002574 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002575 return ses;
2576
2577get_ses_fail:
2578 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002579 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002580 return ERR_PTR(rc);
2581}
2582
Steve French96daf2b2011-05-27 04:34:02 +00002583static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002584{
2585 if (tcon->tidStatus == CifsExiting)
2586 return 0;
2587 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2588 return 0;
2589 return 1;
2590}
2591
Steve French96daf2b2011-05-27 04:34:02 +00002592static struct cifs_tcon *
2593cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594{
2595 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002596 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302598 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002599 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002600 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002601 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002602 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002603 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302604 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 return tcon;
2606 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302607 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 return NULL;
2609}
2610
Jeff Laytonf1987b42008-11-15 11:12:47 -05002611static void
Steve French96daf2b2011-05-27 04:34:02 +00002612cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002613{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002614 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002615 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002616
Joe Perchesf96637b2013-05-04 22:12:25 -05002617 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302618 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002619 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302620 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002621 return;
2622 }
2623
2624 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302625 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002626
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002627 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002628 if (ses->server->ops->tree_disconnect)
2629 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002630 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002631
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302632 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002633 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002634 cifs_put_smb_ses(ses);
2635}
2636
Steve French96daf2b2011-05-27 04:34:02 +00002637static struct cifs_tcon *
2638cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002639{
2640 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002641 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002642
2643 tcon = cifs_find_tcon(ses, volume_info->UNC);
2644 if (tcon) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002645 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002646 /* existing tcon already has a reference */
2647 cifs_put_smb_ses(ses);
2648 if (tcon->seal != volume_info->seal)
Joe Perchesf96637b2013-05-04 22:12:25 -05002649 cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002650 return tcon;
2651 }
2652
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002653 if (!ses->server->ops->tree_connect) {
2654 rc = -ENOSYS;
2655 goto out_fail;
2656 }
2657
Jeff Laytond00c28d2010-04-24 07:57:44 -04002658 tcon = tconInfoAlloc();
2659 if (tcon == NULL) {
2660 rc = -ENOMEM;
2661 goto out_fail;
2662 }
2663
2664 tcon->ses = ses;
2665 if (volume_info->password) {
2666 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2667 if (!tcon->password) {
2668 rc = -ENOMEM;
2669 goto out_fail;
2670 }
2671 }
2672
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002673 /*
2674 * BB Do we need to wrap session_mutex around this TCon call and Unix
2675 * SetFS as we do on SessSetup and reconnect?
2676 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002677 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002678 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2679 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002680 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002681 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002682 if (rc)
2683 goto out_fail;
2684
2685 if (volume_info->nodfs) {
2686 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002687 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002688 }
2689 tcon->seal = volume_info->seal;
Steve Frenchb618f002015-11-03 09:15:03 -06002690 tcon->use_persistent = false;
2691 /* check if SMB2 or later, CIFS does not support persistent handles */
2692 if (volume_info->persistent) {
2693 if (ses->server->vals->protocol_id == 0) {
2694 cifs_dbg(VFS,
2695 "SMB3 or later required for persistent handles\n");
2696 rc = -EOPNOTSUPP;
2697 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002698#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002699 } else if (ses->server->capabilities &
2700 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2701 tcon->use_persistent = true;
2702 else /* persistent handles requested but not supported */ {
2703 cifs_dbg(VFS,
2704 "Persistent handles not supported on share\n");
2705 rc = -EOPNOTSUPP;
2706 goto out_fail;
Steve French592fafe2015-11-03 10:08:53 -06002707#endif /* CONFIG_CIFS_SMB2 */
Steve Frenchb618f002015-11-03 09:15:03 -06002708 }
Steve French592fafe2015-11-03 10:08:53 -06002709#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06002710 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
2711 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
2712 && (volume_info->nopersistent == false)) {
2713 cifs_dbg(FYI, "enabling persistent handles\n");
2714 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06002715#endif /* CONFIG_CIFS_SMB2 */
2716 } else if (volume_info->resilient) {
2717 if (ses->server->vals->protocol_id == 0) {
2718 cifs_dbg(VFS,
2719 "SMB2.1 or later required for resilient handles\n");
2720 rc = -EOPNOTSUPP;
2721 goto out_fail;
2722 }
2723 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06002724 }
2725
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002726 /*
2727 * We can have only one retry value for a connection to a share so for
2728 * resources mounted more than once to the same server share the last
2729 * value passed in for the retry flag is used.
2730 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04002731 tcon->retry = volume_info->retry;
2732 tcon->nocase = volume_info->nocase;
2733 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07002734 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002735
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302736 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002737 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302738 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002739
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302740 cifs_fscache_get_super_cookie(tcon);
2741
Jeff Laytond00c28d2010-04-24 07:57:44 -04002742 return tcon;
2743
2744out_fail:
2745 tconInfoFree(tcon);
2746 return ERR_PTR(rc);
2747}
2748
Jeff Layton9d002df2010-10-06 19:51:11 -04002749void
2750cifs_put_tlink(struct tcon_link *tlink)
2751{
2752 if (!tlink || IS_ERR(tlink))
2753 return;
2754
2755 if (!atomic_dec_and_test(&tlink->tl_count) ||
2756 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2757 tlink->tl_time = jiffies;
2758 return;
2759 }
2760
2761 if (!IS_ERR(tlink_tcon(tlink)))
2762 cifs_put_tcon(tlink_tcon(tlink));
2763 kfree(tlink);
2764 return;
2765}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002766
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002767static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002768cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2769{
2770 return cifs_sb->master_tlink;
2771}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002772
2773static int
2774compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2775{
2776 struct cifs_sb_info *old = CIFS_SB(sb);
2777 struct cifs_sb_info *new = mnt_data->cifs_sb;
2778
2779 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2780 return 0;
2781
2782 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2783 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2784 return 0;
2785
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002786 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002787 * We want to share sb only if we don't specify an r/wsize or
2788 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002789 */
2790 if (new->wsize && new->wsize < old->wsize)
2791 return 0;
2792
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002793 if (new->rsize && new->rsize < old->rsize)
2794 return 0;
2795
Eric W. Biederman1f682332013-02-06 01:20:20 -08002796 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002797 return 0;
2798
2799 if (old->mnt_file_mode != new->mnt_file_mode ||
2800 old->mnt_dir_mode != new->mnt_dir_mode)
2801 return 0;
2802
2803 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2804 return 0;
2805
2806 if (old->actimeo != new->actimeo)
2807 return 0;
2808
2809 return 1;
2810}
2811
2812int
2813cifs_match_super(struct super_block *sb, void *data)
2814{
2815 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2816 struct smb_vol *volume_info;
2817 struct cifs_sb_info *cifs_sb;
2818 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002819 struct cifs_ses *ses;
2820 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002821 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002822 int rc = 0;
2823
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002824 spin_lock(&cifs_tcp_ses_lock);
2825 cifs_sb = CIFS_SB(sb);
2826 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2827 if (IS_ERR(tlink)) {
2828 spin_unlock(&cifs_tcp_ses_lock);
2829 return rc;
2830 }
2831 tcon = tlink_tcon(tlink);
2832 ses = tcon->ses;
2833 tcp_srv = ses->server;
2834
2835 volume_info = mnt_data->vol;
2836
Jeff Layton9fa114f2012-11-26 11:09:57 -05002837 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002838 !match_session(ses, volume_info) ||
2839 !match_tcon(tcon, volume_info->UNC)) {
2840 rc = 0;
2841 goto out;
2842 }
2843
2844 rc = compare_mount_options(sb, mnt_data);
2845out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002846 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002847 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002848 return rc;
2849}
2850
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002852get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002853 const struct nls_table *nls_codepage, unsigned int *num_referrals,
2854 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855{
2856 char *temp_unc;
2857 int rc = 0;
2858
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002859 if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002860 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002862 *num_referrals = 0;
2863 *referrals = NULL;
2864
2865 if (ses->ipc_tid == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 temp_unc = kmalloc(2 /* for slashes */ +
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002867 strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
2868 + 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 if (temp_unc == NULL)
2870 return -ENOMEM;
2871 temp_unc[0] = '\\';
2872 temp_unc[1] = '\\';
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002873 strcpy(temp_unc + 2, ses->serverName);
2874 strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
2875 rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
2876 nls_codepage);
Joe Perchesf96637b2013-05-04 22:12:25 -05002877 cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 kfree(temp_unc);
2879 }
2880 if (rc == 0)
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002881 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
2882 referrals, num_referrals,
2883 nls_codepage, remap);
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002884 /*
2885 * BB - map targetUNCs to dfs_info3 structures, here or in
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002886 * ses->server->ops->get_dfs_refer.
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002887 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888
2889 return rc;
2890}
2891
Jeff Layton09e50d52008-07-23 10:11:19 -04002892#ifdef CONFIG_DEBUG_LOCK_ALLOC
2893static struct lock_class_key cifs_key[2];
2894static struct lock_class_key cifs_slock_key[2];
2895
2896static inline void
2897cifs_reclassify_socket4(struct socket *sock)
2898{
2899 struct sock *sk = sock->sk;
2900 BUG_ON(sock_owned_by_user(sk));
2901 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2902 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2903}
2904
2905static inline void
2906cifs_reclassify_socket6(struct socket *sock)
2907{
2908 struct sock *sk = sock->sk;
2909 BUG_ON(sock_owned_by_user(sk));
2910 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2911 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2912}
2913#else
2914static inline void
2915cifs_reclassify_socket4(struct socket *sock)
2916{
2917}
2918
2919static inline void
2920cifs_reclassify_socket6(struct socket *sock)
2921{
2922}
2923#endif
2924
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002926static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927{
Steve French50c2f752007-07-13 00:33:32 +00002928 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929
Steve French50c2f752007-07-13 00:33:32 +00002930 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 /* mask a nibble at a time and encode */
2932 target[j] = 'A' + (0x0F & (source[i] >> 4));
2933 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002934 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 }
2936
2937}
2938
Ben Greear3eb9a882010-09-01 17:06:02 -07002939static int
2940bind_socket(struct TCP_Server_Info *server)
2941{
2942 int rc = 0;
2943 if (server->srcaddr.ss_family != AF_UNSPEC) {
2944 /* Bind to the specified local IP address */
2945 struct socket *socket = server->ssocket;
2946 rc = socket->ops->bind(socket,
2947 (struct sockaddr *) &server->srcaddr,
2948 sizeof(server->srcaddr));
2949 if (rc < 0) {
2950 struct sockaddr_in *saddr4;
2951 struct sockaddr_in6 *saddr6;
2952 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2953 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2954 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05002955 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
2956 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002957 else
Joe Perchesf96637b2013-05-04 22:12:25 -05002958 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
2959 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002960 }
2961 }
2962 return rc;
2963}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
2965static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002966ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967{
2968 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002969 /*
2970 * some servers require RFC1001 sessinit before sending
2971 * negprot - BB check reconnection in case where second
2972 * sessinit is sent but no second negprot
2973 */
2974 struct rfc1002_session_packet *ses_init_buf;
2975 struct smb_hdr *smb_buf;
2976 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2977 GFP_KERNEL);
2978 if (ses_init_buf) {
2979 ses_init_buf->trailer.session_req.called_len = 32;
2980
2981 if (server->server_RFC1001_name &&
2982 server->server_RFC1001_name[0] != 0)
2983 rfc1002mangle(ses_init_buf->trailer.
2984 session_req.called_name,
2985 server->server_RFC1001_name,
2986 RFC1001_NAME_LEN_WITH_NULL);
2987 else
2988 rfc1002mangle(ses_init_buf->trailer.
2989 session_req.called_name,
2990 DEFAULT_CIFS_CALLED_NAME,
2991 RFC1001_NAME_LEN_WITH_NULL);
2992
2993 ses_init_buf->trailer.session_req.calling_len = 32;
2994
2995 /*
2996 * calling name ends in null (byte 16) from old smb
2997 * convention.
2998 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05002999 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003000 rfc1002mangle(ses_init_buf->trailer.
3001 session_req.calling_name,
3002 server->workstation_RFC1001_name,
3003 RFC1001_NAME_LEN_WITH_NULL);
3004 else
3005 rfc1002mangle(ses_init_buf->trailer.
3006 session_req.calling_name,
3007 "LINUX_CIFS_CLNT",
3008 RFC1001_NAME_LEN_WITH_NULL);
3009
3010 ses_init_buf->trailer.session_req.scope1 = 0;
3011 ses_init_buf->trailer.session_req.scope2 = 0;
3012 smb_buf = (struct smb_hdr *)ses_init_buf;
3013
3014 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003015 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003016 rc = smb_send(server, smb_buf, 0x44);
3017 kfree(ses_init_buf);
3018 /*
3019 * RFC1001 layer in at least one server
3020 * requires very short break before negprot
3021 * presumably because not expecting negprot
3022 * to follow so fast. This is a simple
3023 * solution that works without
3024 * complicating the code and causes no
3025 * significant slowing down on mount
3026 * for everyone else
3027 */
3028 usleep_range(1000, 2000);
3029 }
3030 /*
3031 * else the negprot may still work without this
3032 * even though malloc failed
3033 */
3034
3035 return rc;
3036}
3037
3038static int
3039generic_ip_connect(struct TCP_Server_Info *server)
3040{
3041 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003042 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003043 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003044 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003045 struct sockaddr *saddr;
3046
3047 saddr = (struct sockaddr *) &server->dstaddr;
3048
3049 if (server->dstaddr.ss_family == AF_INET6) {
3050 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3051 slen = sizeof(struct sockaddr_in6);
3052 sfamily = AF_INET6;
3053 } else {
3054 sport = ((struct sockaddr_in *) saddr)->sin_port;
3055 slen = sizeof(struct sockaddr_in);
3056 sfamily = AF_INET;
3057 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003059 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003060 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3061 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003063 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003064 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003067
3068 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003069 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003070 server->ssocket = socket;
3071 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003072 if (sfamily == AF_INET6)
3073 cifs_reclassify_socket6(socket);
3074 else
3075 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 }
3077
Ben Greear3eb9a882010-09-01 17:06:02 -07003078 rc = bind_socket(server);
3079 if (rc < 0)
3080 return rc;
3081
Jeff Laytond5c56052008-12-01 18:42:33 -05003082 /*
3083 * Eventually check for other socket options to change from
3084 * the default. sock_setsockopt not used because it expects
3085 * user space buffer
3086 */
3087 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003088 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003089
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003090 /* make the bufsizes depend on wsize/rsize and max requests */
3091 if (server->noautotune) {
3092 if (socket->sk->sk_sndbuf < (200 * 1024))
3093 socket->sk->sk_sndbuf = 200 * 1024;
3094 if (socket->sk->sk_rcvbuf < (140 * 1024))
3095 socket->sk->sk_rcvbuf = 140 * 1024;
3096 }
3097
Steve French6a5fa2362010-01-01 01:28:43 +00003098 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003099 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003100 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3101 (char *)&val, sizeof(val));
3102 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003103 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3104 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003105 }
3106
Joe Perchesf96637b2013-05-04 22:12:25 -05003107 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003108 socket->sk->sk_sndbuf,
3109 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3110
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003111 rc = socket->ops->connect(socket, saddr, slen, 0);
3112 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003113 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003114 sock_release(socket);
3115 server->ssocket = NULL;
3116 return rc;
3117 }
3118
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003119 if (sport == htons(RFC1001_PORT))
3120 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003121
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 return rc;
3123}
3124
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003125static int
3126ip_connect(struct TCP_Server_Info *server)
3127{
Steve French6da97912011-03-13 18:55:55 +00003128 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003129 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3130 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3131
3132 if (server->dstaddr.ss_family == AF_INET6)
3133 sport = &addr6->sin6_port;
3134 else
3135 sport = &addr->sin_port;
3136
3137 if (*sport == 0) {
3138 int rc;
3139
3140 /* try with 445 port at first */
3141 *sport = htons(CIFS_PORT);
3142
3143 rc = generic_ip_connect(server);
3144 if (rc >= 0)
3145 return rc;
3146
3147 /* if it failed, try with 139 port */
3148 *sport = htons(RFC1001_PORT);
3149 }
3150
3151 return generic_ip_connect(server);
3152}
3153
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003154void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003155 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003156{
3157 /* if we are reconnecting then should we check to see if
3158 * any requested capabilities changed locally e.g. via
3159 * remount but we can not do much about it here
3160 * if they have (even if we could detect it by the following)
3161 * Perhaps we could add a backpointer to array of sb from tcon
3162 * or if we change to make all sb to same share the same
3163 * sb as NFS - then we only have one backpointer to sb.
3164 * What if we wanted to mount the server share twice once with
3165 * and once without posixacls or posix paths? */
3166 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003167
Steve Frenchc18c8422007-07-18 23:21:09 +00003168 if (vol_info && vol_info->no_linux_ext) {
3169 tcon->fsUnixInfo.Capability = 0;
3170 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003171 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003172 return;
3173 } else if (vol_info)
3174 tcon->unix_ext = 1; /* Unix Extensions supported */
3175
3176 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003177 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003178 return;
3179 }
Steve French50c2f752007-07-13 00:33:32 +00003180
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003181 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003182 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003183 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003184 /* check for reconnect case in which we do not
3185 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003186 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003187 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003188 originally at mount time */
3189 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3190 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003191 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3192 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003193 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003194 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003195 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003196 cifs_dbg(VFS, "possible reconnect error\n");
3197 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003198 }
Steve French8af18972007-02-14 04:42:51 +00003199 }
Steve French50c2f752007-07-13 00:33:32 +00003200
Steve French6848b732011-05-26 18:38:54 +00003201 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003202 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003203
Steve French8af18972007-02-14 04:42:51 +00003204 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003205 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003206 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003207 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003208 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003209 if (cifs_sb)
3210 cifs_sb->mnt_cifs_flags |=
3211 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003212 }
3213
Steve French75865f8c2007-06-24 18:30:48 +00003214 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003215 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003216 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003217 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003218 if (cifs_sb)
3219 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003220 CIFS_MOUNT_POSIX_PATHS;
3221 }
Steve French50c2f752007-07-13 00:33:32 +00003222
Joe Perchesf96637b2013-05-04 22:12:25 -05003223 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003224#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003225 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003226 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003227 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003228 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003229 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003230 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003231 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003232 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003233 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003234 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003235 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003236 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003237 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003238 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003239 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003240 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003241 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003242 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003243#endif /* CIFS_DEBUG2 */
3244 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003245 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003246 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003247 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003248 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 +00003249
Steve French8af18972007-02-14 04:42:51 +00003250 }
3251 }
3252}
3253
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003254void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3255 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003256{
Jeff Layton2de970f2010-10-06 19:51:12 -04003257 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3258
Al Viro2ced6f62011-06-17 09:20:04 -04003259 spin_lock_init(&cifs_sb->tlink_tree_lock);
3260 cifs_sb->tlink_tree = RB_ROOT;
3261
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003262 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003263 * Temporarily set r/wsize for matching superblock. If we end up using
3264 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003265 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003266 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003267 cifs_sb->wsize = pvolume_info->wsize;
3268
Steve French3b795212008-11-13 19:45:32 +00003269 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3270 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3271 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3272 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003273 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3274 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003275
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303276 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003277 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303278
Steve French3b795212008-11-13 19:45:32 +00003279 if (pvolume_info->noperm)
3280 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3281 if (pvolume_info->setuids)
3282 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3283 if (pvolume_info->server_ino)
3284 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3285 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003286 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3287 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003288 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3289 if (pvolume_info->no_xattr)
3290 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3291 if (pvolume_info->sfu_emul)
3292 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3293 if (pvolume_info->nobrl)
3294 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003295 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003296 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003297 if (pvolume_info->mand_lock)
3298 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003299 if (pvolume_info->rwpidforward)
3300 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003301 if (pvolume_info->cifs_acl)
3302 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003303 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003304 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003305 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3306 }
3307 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003308 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003309 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3310 }
Steve French3b795212008-11-13 19:45:32 +00003311 if (pvolume_info->override_uid)
3312 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3313 if (pvolume_info->override_gid)
3314 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3315 if (pvolume_info->dynperm)
3316 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303317 if (pvolume_info->fsc)
3318 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003319 if (pvolume_info->multiuser)
3320 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3321 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003322 if (pvolume_info->strict_io)
3323 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003324 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003325 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003326 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3327 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003328 if (pvolume_info->mfsymlinks) {
3329 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003330 /*
3331 * Our SFU ("Services for Unix" emulation does not allow
3332 * creating symlinks but does allow reading existing SFU
3333 * symlinks (it does allow both creating and reading SFU
3334 * style mknod and FIFOs though). When "mfsymlinks" and
3335 * "sfu" are both enabled at the same time, it allows
3336 * reading both types of symlinks, but will only create
3337 * them with mfsymlinks format. This allows better
3338 * Apple compatibility (probably better for Samba too)
3339 * while still recognizing old Windows style symlinks.
3340 */
3341 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003342 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003343 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003344 }
Steve French3b795212008-11-13 19:45:32 +00003345
3346 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003347 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003348}
3349
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003350static void
3351cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003352{
Sean Finneyb9468452011-04-11 13:19:32 +00003353 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003354 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003355 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003356 kfree(volume_info->domainname);
3357 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003358 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003359}
3360
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003361void
3362cifs_cleanup_volume_info(struct smb_vol *volume_info)
3363{
3364 if (!volume_info)
3365 return;
3366 cleanup_volume_info_contents(volume_info);
3367 kfree(volume_info);
3368}
3369
3370
Steve French2d6d5892009-04-09 00:36:44 +00003371#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003372/*
3373 * cifs_build_path_to_root returns full path to root when we do not have an
3374 * exiting connection (tcon)
3375 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003376static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003377build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003378 const struct cifs_sb_info *cifs_sb)
3379{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003380 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003381 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003382 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003383
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003384 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003385 if (full_path == NULL)
3386 return ERR_PTR(-ENOMEM);
3387
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003388 strncpy(full_path, vol->UNC, unc_len);
3389 pos = full_path + unc_len;
3390
3391 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003392 *pos = CIFS_DIR_SEP(cifs_sb);
3393 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003394 pos += pplen;
3395 }
3396
3397 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003398 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003399 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003400 return full_path;
3401}
Sean Finneydd613942011-04-11 13:19:30 +00003402
3403/*
3404 * Perform a dfs referral query for a share and (optionally) prefix
3405 *
Sean Finney046462a2011-04-11 13:19:33 +00003406 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3407 * to a string containing updated options for the submount. Otherwise it
3408 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003409 *
3410 * Returns the rc from get_dfs_path to the caller, which can be used to
3411 * determine whether there were referrals.
3412 */
3413static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003414expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003415 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003416 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003417{
3418 int rc;
3419 unsigned int num_referrals = 0;
3420 struct dfs_info3_param *referrals = NULL;
3421 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3422
3423 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3424 if (IS_ERR(full_path))
3425 return PTR_ERR(full_path);
3426
3427 /* For DFS paths, skip the first '\' of the UNC */
3428 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3429
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003430 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003431 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003432
3433 if (!rc && num_referrals > 0) {
3434 char *fake_devname = NULL;
3435
3436 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3437 full_path + 1, referrals,
3438 &fake_devname);
3439
3440 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003441
Sean Finneydd613942011-04-11 13:19:30 +00003442 if (IS_ERR(mdata)) {
3443 rc = PTR_ERR(mdata);
3444 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003445 } else {
3446 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003447 rc = cifs_setup_volume_info(volume_info, mdata,
3448 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003449 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003450 kfree(fake_devname);
3451 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003452 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003453 }
3454 kfree(full_path);
3455 return rc;
3456}
Steve French2d6d5892009-04-09 00:36:44 +00003457#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003458
Jeff Layton04db79b2011-07-06 08:10:38 -04003459static int
3460cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3461 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003463 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003464
Jeff Layton04db79b2011-07-06 08:10:38 -04003465 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3466 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467
Jeff Layton7586b762008-12-01 18:41:49 -05003468 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003469 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003470 kfree(volume_info->username);
3471 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003472 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003474 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003476 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003477 /* In userspace mount helper we can get user name from alternate
3478 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003479 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 }
3481
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003483 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003484 /* load_nls_default cannot return null */
3485 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003487 volume_info->local_nls = load_nls(volume_info->iocharset);
3488 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003489 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003490 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003491 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 }
3493 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003494
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003495 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003496}
3497
3498struct smb_vol *
3499cifs_get_volume_info(char *mount_data, const char *devname)
3500{
3501 int rc;
3502 struct smb_vol *volume_info;
3503
Jeff Layton6ee95422012-11-26 11:09:57 -05003504 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003505 if (!volume_info)
3506 return ERR_PTR(-ENOMEM);
3507
3508 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3509 if (rc) {
3510 cifs_cleanup_volume_info(volume_info);
3511 volume_info = ERR_PTR(rc);
3512 }
3513
3514 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003515}
3516
3517int
Al Viro2c6292a2011-06-17 09:05:48 -04003518cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003519{
Jeff Layton1daaae82012-03-21 06:30:40 -04003520 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003521 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003522 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003523 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003524 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003525 char *full_path;
3526 struct tcon_link *tlink;
3527#ifdef CONFIG_CIFS_DFS_UPCALL
3528 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003529#endif
Al Virodd854462011-06-17 08:24:42 -04003530
Christoph Hellwigb4caecd2015-01-14 10:42:32 +01003531 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs");
Al Virodd854462011-06-17 08:24:42 -04003532 if (rc)
3533 return rc;
3534
Jeff Layton20547492011-07-09 12:21:07 -04003535#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003536try_mount_again:
3537 /* cleanup activities if we're chasing a referral */
3538 if (referral_walks_count) {
3539 if (tcon)
3540 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003541 else if (ses)
3542 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003543
Sachin Prabhu1dfd18d2015-06-16 16:36:17 +01003544 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
3545
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003546 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003547 }
3548#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003549 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003550 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003551 ses = NULL;
3552 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003553 full_path = NULL;
3554 tlink = NULL;
3555
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003556 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557
Jeff Layton63c038c2008-12-01 18:41:46 -05003558 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003559 server = cifs_get_tcp_session(volume_info);
3560 if (IS_ERR(server)) {
3561 rc = PTR_ERR(server);
Al Virodd854462011-06-17 08:24:42 -04003562 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003563 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 }
3565
Jeff Layton36988c72010-04-24 07:57:43 -04003566 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003567 ses = cifs_get_smb_ses(server, volume_info);
3568 if (IS_ERR(ses)) {
3569 rc = PTR_ERR(ses);
3570 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003571 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 }
Steve French50c2f752007-07-13 00:33:32 +00003573
Steve French592fafe2015-11-03 10:08:53 -06003574#ifdef CONFIG_CIFS_SMB2
Steve Frenchb618f002015-11-03 09:15:03 -06003575 if ((volume_info->persistent == true) && ((ses->server->capabilities &
3576 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
3577 cifs_dbg(VFS, "persistent handles not supported by server\n");
3578 rc = -EOPNOTSUPP;
3579 goto mount_fail_check;
3580 }
Steve French592fafe2015-11-03 10:08:53 -06003581#endif /* CONFIG_CIFS_SMB2*/
3582
Jeff Laytond00c28d2010-04-24 07:57:44 -04003583 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003584 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003585 if (IS_ERR(tcon)) {
3586 rc = PTR_ERR(tcon);
3587 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003588 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003589 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003590
Steve French6848b732011-05-26 18:38:54 +00003591 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003592 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003593 /* reset of caps checks mount to see if unix extensions
3594 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003595 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003596 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3597 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3598 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3599 rc = -EACCES;
3600 goto mount_fail_check;
3601 }
3602 } else
3603 tcon->unix_ext = 0; /* server does not support them */
3604
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003605 /* do not care if a following call succeed - informational */
3606 if (!tcon->ipc && server->ops->qfs_tcon)
3607 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003608
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003609 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3610 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003611
Jeff Layton66bfaad2011-10-19 15:30:35 -04003612 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003613 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003614
Igor Mammedove4cce942009-02-10 14:10:26 +03003615remote_path_check:
3616#ifdef CONFIG_CIFS_DFS_UPCALL
3617 /*
3618 * Perform an unconditional check for whether there are DFS
3619 * referrals for this path without prefix, to provide support
3620 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003621 * with PATH_NOT_COVERED to requests that include the prefix.
3622 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003623 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003624 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003625 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3626 false);
Steve Frencheeac8042006-01-13 21:34:58 -08003627 if (!refrc) {
Steve French4523cc32007-04-30 20:13:06 +00003628 referral_walks_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 goto try_mount_again;
3630 }
3631 }
3632#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003633
Steve Frenchf87d39d2011-05-27 03:50:55 +00003634 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003636 if (!server->ops->is_path_accessible) {
3637 rc = -ENOSYS;
3638 goto mount_fail_check;
3639 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003640 /*
3641 * cifs_build_path_to_root works only when we have a valid tcon
3642 */
3643 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 if (full_path == NULL) {
3645 rc = -ENOMEM;
3646 goto mount_fail_check;
3647 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003648 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3649 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650 if (rc != 0 && rc != -EREMOTE) {
3651 kfree(full_path);
3652 goto mount_fail_check;
3653 }
3654 kfree(full_path);
3655 }
3656
3657 /* get referral if needed */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003658 if (rc == -EREMOTE) {
3659#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003660 if (referral_walks_count > MAX_NESTED_LINKS) {
3661 /*
3662 * BB: when we implement proper loop detection,
3663 * we will remove this check. But now we need it
3664 * to prevent an indefinite loop if 'DFS tree' is
3665 * misconfigured (i.e. has loops).
3666 */
3667 rc = -ELOOP;
3668 goto mount_fail_check;
3669 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003670
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003671 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003672
Sean Finneydd613942011-04-11 13:19:30 +00003673 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003674 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003675 goto try_mount_again;
3676 }
Sean Finneydd613942011-04-11 13:19:30 +00003677 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003678#else /* No DFS support, return error on mount */
3679 rc = -EOPNOTSUPP;
3680#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003681 }
3682
Jeff Layton9d002df2010-10-06 19:51:11 -04003683 if (rc)
3684 goto mount_fail_check;
3685
3686 /* now, hang the tcon off of the superblock */
3687 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3688 if (tlink == NULL) {
3689 rc = -ENOMEM;
3690 goto mount_fail_check;
3691 }
3692
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003693 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003694 tlink->tl_tcon = tcon;
3695 tlink->tl_time = jiffies;
3696 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3697 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3698
Jeff Layton413e6612010-10-28 13:33:38 -04003699 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003700 spin_lock(&cifs_sb->tlink_tree_lock);
3701 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3702 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003703
Jeff Laytonda472fc2012-03-23 14:40:53 -04003704 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003705 TLINK_IDLE_EXPIRE);
3706
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003707mount_fail_check:
3708 /* on error free sesinfo and tcon struct if needed */
3709 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003710 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003711 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003712 if (tcon)
3713 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003714 else if (ses)
3715 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003716 else
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003717 cifs_put_tcp_session(server);
Al Virodd854462011-06-17 08:24:42 -04003718 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003719 }
3720
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003722 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 return rc;
3724}
3725
Jeff Layton8d1bca32011-06-11 21:17:10 -04003726/*
3727 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3728 * pointer may be NULL.
3729 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003731CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00003732 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 const struct nls_table *nls_codepage)
3734{
3735 struct smb_hdr *smb_buffer;
3736 struct smb_hdr *smb_buffer_response;
3737 TCONX_REQ *pSMB;
3738 TCONX_RSP *pSMBr;
3739 unsigned char *bcc_ptr;
3740 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003741 int length;
3742 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
3744 if (ses == NULL)
3745 return -EIO;
3746
3747 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003748 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003750
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 smb_buffer_response = smb_buffer;
3752
3753 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3754 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003755
Pavel Shilovsky88257362012-05-23 14:01:59 +04003756 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757 smb_buffer->Uid = ses->Suid;
3758 pSMB = (TCONX_REQ *) smb_buffer;
3759 pSMBr = (TCONX_RSP *) smb_buffer_response;
3760
3761 pSMB->AndXCommand = 0xFF;
3762 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003764 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003765 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003766 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003767 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003768 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003769 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003770 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003771 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3772 specified as required (when that support is added to
3773 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003774 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003775 by Samba (not sure whether other servers allow
3776 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003777#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003778 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05003779 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003780 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003781 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003782 SECMODE_PW_ENCRYPT ? true : false,
3783 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003784 else
3785#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003786 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003787 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05003788 if (rc) {
3789 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
3790 __func__, rc);
3791 cifs_buf_release(smb_buffer);
3792 return rc;
3793 }
Steve Frencheeac8042006-01-13 21:34:58 -08003794
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003795 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003796 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003797 /* must align unicode strings */
3798 *bcc_ptr = 0; /* null byte password */
3799 bcc_ptr++;
3800 }
Steve Frencheeac8042006-01-13 21:34:58 -08003801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802
Jeff Layton38d77c52013-05-26 07:01:00 -04003803 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3805
3806 if (ses->capabilities & CAP_STATUS32) {
3807 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3808 }
3809 if (ses->capabilities & CAP_DFS) {
3810 smb_buffer->Flags2 |= SMBFLG2_DFS;
3811 }
3812 if (ses->capabilities & CAP_UNICODE) {
3813 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3814 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003815 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003816 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003817 (/* server len*/ + 256 /* share len */), nls_codepage);
3818 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 bcc_ptr += 2; /* skip trailing null */
3820 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 strcpy(bcc_ptr, tree);
3822 bcc_ptr += strlen(tree) + 1;
3823 }
3824 strcpy(bcc_ptr, "?????");
3825 bcc_ptr += strlen("?????");
3826 bcc_ptr += 1;
3827 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003828 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3829 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 pSMB->ByteCount = cpu_to_le16(count);
3831
Steve French133672e2007-11-13 22:41:37 +00003832 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003833 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 /* above now done in SendReceive */
3836 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003837 bool is_unicode;
3838
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003840 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 tcon->tid = smb_buffer_response->Tid;
3842 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003843 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003844 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003845 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
3846 is_unicode = true;
3847 else
3848 is_unicode = false;
3849
Jeff Laytoncc20c032009-04-30 07:16:21 -04003850
Steve French50c2f752007-07-13 00:33:32 +00003851 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00003852 if (length == 3) {
3853 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3854 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003855 cifs_dbg(FYI, "IPC connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003856 tcon->ipc = 1;
3857 }
3858 } else if (length == 2) {
3859 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3860 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05003861 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003862 }
3863 }
Steve French50c2f752007-07-13 00:33:32 +00003864 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04003865 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05003866 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04003867
3868 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04003869 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06003870 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00003871 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04003872 nls_codepage);
3873
Joe Perchesf96637b2013-05-04 22:12:25 -05003874 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003875
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003876 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00003877 (smb_buffer_response->WordCount == 7))
3878 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00003879 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3880 else
3881 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05003882 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003884 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 ses->ipc_tid = smb_buffer_response->Tid;
3886 }
3887
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00003888 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 return rc;
3890}
3891
Al Viro2e32cf52013-10-03 12:53:37 -04003892static void delayed_free(struct rcu_head *p)
3893{
3894 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
3895 unload_nls(sbi->local_nls);
3896 kfree(sbi);
3897}
3898
Al Viro2a9b9952011-06-17 09:27:16 -04003899void
3900cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901{
Jeff Laytonb647c352010-10-28 11:16:44 -04003902 struct rb_root *root = &cifs_sb->tlink_tree;
3903 struct rb_node *node;
3904 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Jeff Layton2de970f2010-10-06 19:51:12 -04003906 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
3907
Jeff Laytonb647c352010-10-28 11:16:44 -04003908 spin_lock(&cifs_sb->tlink_tree_lock);
3909 while ((node = rb_first(root))) {
3910 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3911 cifs_get_tlink(tlink);
3912 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3913 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00003914
Jeff Laytonb647c352010-10-28 11:16:44 -04003915 spin_unlock(&cifs_sb->tlink_tree_lock);
3916 cifs_put_tlink(tlink);
3917 spin_lock(&cifs_sb->tlink_tree_lock);
3918 }
3919 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003920
Al Virodd854462011-06-17 08:24:42 -04003921 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04003922 kfree(cifs_sb->mountdata);
Al Viro2e32cf52013-10-03 12:53:37 -04003923 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00003924}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003926int
3927cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928{
3929 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04003930 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003932 if (!server->ops->need_neg || !server->ops->negotiate)
3933 return -ENOSYS;
3934
Jeff Layton198b5682010-04-24 07:57:48 -04003935 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003936 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04003937 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938
Pavel Shilovsky45275782012-05-17 17:53:29 +04003939 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003940
3941 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04003942 if (rc == 0) {
3943 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04003944 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04003945 server->tcpStatus = CifsGood;
3946 else
3947 rc = -EHOSTDOWN;
3948 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 }
Steve French26b994f2008-08-06 05:11:33 +00003950
Jeff Layton198b5682010-04-24 07:57:48 -04003951 return rc;
3952}
Steve French26b994f2008-08-06 05:11:33 +00003953
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003954int
3955cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
3956 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04003957{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003958 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04003959 struct TCP_Server_Info *server = ses->server;
3960
Jeff Layton198b5682010-04-24 07:57:48 -04003961 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00003962 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003963 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00003964
Joe Perchesf96637b2013-05-04 22:12:25 -05003965 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00003966 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04003967
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003968 if (server->ops->sess_setup)
3969 rc = server->ops->sess_setup(xid, ses, nls_info);
3970
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05003971 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003972 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003973
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 return rc;
3975}
3976
Jeff Layton8a8798a2012-01-17 16:09:15 -05003977static int
3978cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
3979{
Jeff Layton3f618222013-06-12 19:52:14 -05003980 vol->sectype = ses->sectype;
3981
3982 /* krb5 is special, since we don't need username or pw */
3983 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003984 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003985
3986 return cifs_set_cifscreds(vol, ses);
3987}
3988
Steve French96daf2b2011-05-27 04:34:02 +00003989static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003990cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04003991{
Jeff Layton8a8798a2012-01-17 16:09:15 -05003992 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00003993 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
3994 struct cifs_ses *ses;
3995 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04003996 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04003997
3998 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03003999 if (vol_info == NULL)
4000 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004001
Jeff Layton9d002df2010-10-06 19:51:11 -04004002 vol_info->local_nls = cifs_sb->local_nls;
4003 vol_info->linux_uid = fsuid;
4004 vol_info->cred_uid = fsuid;
4005 vol_info->UNC = master_tcon->treeName;
4006 vol_info->retry = master_tcon->retry;
4007 vol_info->nocase = master_tcon->nocase;
4008 vol_info->local_lease = master_tcon->local_lease;
4009 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04004010 vol_info->sectype = master_tcon->ses->sectype;
4011 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04004012
Jeff Layton8a8798a2012-01-17 16:09:15 -05004013 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4014 if (rc) {
4015 tcon = ERR_PTR(rc);
4016 goto out;
4017 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004018
4019 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304020 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004021 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304022 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004023
4024 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4025 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004026 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004027 cifs_put_tcp_session(master_tcon->ses->server);
4028 goto out;
4029 }
4030
4031 tcon = cifs_get_tcon(ses, vol_info);
4032 if (IS_ERR(tcon)) {
4033 cifs_put_smb_ses(ses);
4034 goto out;
4035 }
4036
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04004037 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04004038 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4039out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004040 kfree(vol_info->username);
4041 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004042 kfree(vol_info);
4043
4044 return tcon;
4045}
4046
Steve French96daf2b2011-05-27 04:34:02 +00004047struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004048cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4049{
4050 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4051}
4052
Jeff Laytonb647c352010-10-28 11:16:44 -04004053/* find and return a tlink with given uid */
4054static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004055tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04004056{
4057 struct rb_node *node = root->rb_node;
4058 struct tcon_link *tlink;
4059
4060 while (node) {
4061 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4062
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004063 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004064 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004065 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004066 node = node->rb_right;
4067 else
4068 return tlink;
4069 }
4070 return NULL;
4071}
4072
4073/* insert a tcon_link into the tree */
4074static void
4075tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4076{
4077 struct rb_node **new = &(root->rb_node), *parent = NULL;
4078 struct tcon_link *tlink;
4079
4080 while (*new) {
4081 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4082 parent = *new;
4083
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004084 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04004085 new = &((*new)->rb_left);
4086 else
4087 new = &((*new)->rb_right);
4088 }
4089
4090 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4091 rb_insert_color(&new_tlink->tl_rbnode, root);
4092}
4093
Jeff Layton9d002df2010-10-06 19:51:11 -04004094/*
4095 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4096 * current task.
4097 *
4098 * If the superblock doesn't refer to a multiuser mount, then just return
4099 * the master tcon for the mount.
4100 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304101 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004102 * exists, then check to see if it's pending construction. If it is then wait
4103 * for construction to complete. Once it's no longer pending, check to see if
4104 * it failed and either return an error or retry construction, depending on
4105 * the timeout.
4106 *
4107 * If one doesn't exist then insert a new tcon_link struct into the tree and
4108 * try to construct a new one.
4109 */
4110struct tcon_link *
4111cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4112{
4113 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004114 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004115 struct tcon_link *tlink, *newtlink;
4116
4117 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4118 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4119
4120 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004121 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004122 if (tlink)
4123 cifs_get_tlink(tlink);
4124 spin_unlock(&cifs_sb->tlink_tree_lock);
4125
4126 if (tlink == NULL) {
4127 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4128 if (newtlink == NULL)
4129 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004130 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004131 newtlink->tl_tcon = ERR_PTR(-EACCES);
4132 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4133 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4134 cifs_get_tlink(newtlink);
4135
Jeff Layton9d002df2010-10-06 19:51:11 -04004136 spin_lock(&cifs_sb->tlink_tree_lock);
4137 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004138 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004139 if (tlink) {
4140 cifs_get_tlink(tlink);
4141 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004142 kfree(newtlink);
4143 goto wait_for_construction;
4144 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004145 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004146 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4147 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004148 } else {
4149wait_for_construction:
4150 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004151 TASK_INTERRUPTIBLE);
4152 if (ret) {
4153 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004154 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004155 }
4156
4157 /* if it's good, return it */
4158 if (!IS_ERR(tlink->tl_tcon))
4159 return tlink;
4160
4161 /* return error if we tried this already recently */
4162 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4163 cifs_put_tlink(tlink);
4164 return ERR_PTR(-EACCES);
4165 }
4166
4167 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4168 goto wait_for_construction;
4169 }
4170
4171 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4172 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4173 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4174
4175 if (IS_ERR(tlink->tl_tcon)) {
4176 cifs_put_tlink(tlink);
4177 return ERR_PTR(-EACCES);
4178 }
4179
4180 return tlink;
4181}
Jeff Layton2de970f2010-10-06 19:51:12 -04004182
4183/*
4184 * periodic workqueue job that scans tcon_tree for a superblock and closes
4185 * out tcons.
4186 */
4187static void
4188cifs_prune_tlinks(struct work_struct *work)
4189{
4190 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4191 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004192 struct rb_root *root = &cifs_sb->tlink_tree;
4193 struct rb_node *node = rb_first(root);
4194 struct rb_node *tmp;
4195 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004196
Jeff Laytonb647c352010-10-28 11:16:44 -04004197 /*
4198 * Because we drop the spinlock in the loop in order to put the tlink
4199 * it's not guarded against removal of links from the tree. The only
4200 * places that remove entries from the tree are this function and
4201 * umounts. Because this function is non-reentrant and is canceled
4202 * before umount can proceed, this is safe.
4203 */
4204 spin_lock(&cifs_sb->tlink_tree_lock);
4205 node = rb_first(root);
4206 while (node != NULL) {
4207 tmp = node;
4208 node = rb_next(tmp);
4209 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4210
4211 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4212 atomic_read(&tlink->tl_count) != 0 ||
4213 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4214 continue;
4215
4216 cifs_get_tlink(tlink);
4217 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4218 rb_erase(tmp, root);
4219
Jeff Layton2de970f2010-10-06 19:51:12 -04004220 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004221 cifs_put_tlink(tlink);
4222 spin_lock(&cifs_sb->tlink_tree_lock);
4223 }
4224 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004225
Jeff Laytonda472fc2012-03-23 14:40:53 -04004226 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004227 TLINK_IDLE_EXPIRE);
4228}