blob: f3bfe08e177b6c86a4f1a99a8905f1b417f82af5 [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,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040090
91 /* Mount options which take numeric value */
92 Opt_backupuid, Opt_backupgid, Opt_uid,
93 Opt_cruid, Opt_gid, Opt_file_mode,
94 Opt_dirmode, Opt_port,
95 Opt_rsize, Opt_wsize, Opt_actimeo,
96
97 /* Mount options which take string value */
98 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -040099 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400100 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400101 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400102
103 /* Mount options to be ignored */
104 Opt_ignore,
105
106 /* Options which could be blank */
107 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100108 Opt_blank_user,
109 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400110
111 Opt_err
112};
113
114static const match_table_t cifs_mount_option_tokens = {
115
116 { Opt_user_xattr, "user_xattr" },
117 { Opt_nouser_xattr, "nouser_xattr" },
118 { Opt_forceuid, "forceuid" },
119 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400120 { Opt_forcegid, "forcegid" },
121 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400122 { Opt_noblocksend, "noblocksend" },
123 { Opt_noautotune, "noautotune" },
124 { Opt_hard, "hard" },
125 { Opt_soft, "soft" },
126 { Opt_perm, "perm" },
127 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500128 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400129 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500130 { Opt_mapposix, "mapposix" }, /* SFM style */
131 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400132 { Opt_sfu, "sfu" },
133 { Opt_nosfu, "nosfu" },
134 { Opt_nodfs, "nodfs" },
135 { Opt_posixpaths, "posixpaths" },
136 { Opt_noposixpaths, "noposixpaths" },
137 { Opt_nounix, "nounix" },
138 { Opt_nounix, "nolinux" },
139 { Opt_nocase, "nocase" },
140 { Opt_nocase, "ignorecase" },
141 { Opt_brl, "brl" },
142 { Opt_nobrl, "nobrl" },
143 { Opt_nobrl, "nolock" },
144 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400145 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400146 { Opt_setuids, "setuids" },
147 { Opt_nosetuids, "nosetuids" },
148 { Opt_dynperm, "dynperm" },
149 { Opt_nodynperm, "nodynperm" },
150 { Opt_nohard, "nohard" },
151 { Opt_nosoft, "nosoft" },
152 { Opt_nointr, "nointr" },
153 { Opt_intr, "intr" },
154 { Opt_nostrictsync, "nostrictsync" },
155 { Opt_strictsync, "strictsync" },
156 { Opt_serverino, "serverino" },
157 { Opt_noserverino, "noserverino" },
158 { Opt_rwpidforward, "rwpidforward" },
159 { Opt_cifsacl, "cifsacl" },
160 { Opt_nocifsacl, "nocifsacl" },
161 { Opt_acl, "acl" },
162 { Opt_noacl, "noacl" },
163 { Opt_locallease, "locallease" },
164 { Opt_sign, "sign" },
165 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400166 { Opt_noac, "noac" },
167 { Opt_fsc, "fsc" },
168 { Opt_mfsymlinks, "mfsymlinks" },
169 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400170 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400171 { Opt_nosharesock, "nosharesock" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400172
173 { Opt_backupuid, "backupuid=%s" },
174 { Opt_backupgid, "backupgid=%s" },
175 { Opt_uid, "uid=%s" },
176 { Opt_cruid, "cruid=%s" },
177 { Opt_gid, "gid=%s" },
178 { Opt_file_mode, "file_mode=%s" },
179 { Opt_dirmode, "dirmode=%s" },
180 { Opt_dirmode, "dir_mode=%s" },
181 { Opt_port, "port=%s" },
182 { Opt_rsize, "rsize=%s" },
183 { Opt_wsize, "wsize=%s" },
184 { Opt_actimeo, "actimeo=%s" },
185
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100186 { Opt_blank_user, "user=" },
187 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400188 { Opt_user, "user=%s" },
189 { Opt_user, "username=%s" },
190 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100191 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400192 { Opt_pass, "pass=%s" },
193 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100194 { Opt_blank_ip, "ip=" },
195 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400196 { Opt_ip, "ip=%s" },
197 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400198 { Opt_ignore, "unc=%s" },
199 { Opt_ignore, "target=%s" },
200 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400201 { Opt_domain, "dom=%s" },
202 { Opt_domain, "domain=%s" },
203 { Opt_domain, "workgroup=%s" },
204 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400205 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400206 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400207 { Opt_netbiosname, "netbiosname=%s" },
208 { Opt_servern, "servern=%s" },
209 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400210 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400211 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400212 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400213
214 { Opt_ignore, "cred" },
215 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400216 { Opt_ignore, "cred=%s" },
217 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400218 { Opt_ignore, "guest" },
219 { Opt_ignore, "rw" },
220 { Opt_ignore, "ro" },
221 { Opt_ignore, "suid" },
222 { Opt_ignore, "nosuid" },
223 { Opt_ignore, "exec" },
224 { Opt_ignore, "noexec" },
225 { Opt_ignore, "nodev" },
226 { Opt_ignore, "noauto" },
227 { Opt_ignore, "dev" },
228 { Opt_ignore, "mand" },
229 { Opt_ignore, "nomand" },
230 { Opt_ignore, "_netdev" },
231
232 { Opt_err, NULL }
233};
234
235enum {
236 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
237 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400238 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
239 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400240 Opt_sec_none,
241
242 Opt_sec_err
243};
244
245static const match_table_t cifs_secflavor_tokens = {
246 { Opt_sec_krb5, "krb5" },
247 { Opt_sec_krb5i, "krb5i" },
248 { Opt_sec_krb5p, "krb5p" },
249 { Opt_sec_ntlmsspi, "ntlmsspi" },
250 { Opt_sec_ntlmssp, "ntlmssp" },
251 { Opt_ntlm, "ntlm" },
252 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400253 { Opt_sec_ntlmv2, "nontlm" },
254 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400255 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400256 { Opt_sec_lanman, "lanman" },
257 { Opt_sec_none, "none" },
258
259 { Opt_sec_err, NULL }
260};
261
Jeff Layton15b6a472012-05-16 07:50:15 -0400262/* cache flavors */
263enum {
264 Opt_cache_loose,
265 Opt_cache_strict,
266 Opt_cache_none,
267 Opt_cache_err
268};
269
270static const match_table_t cifs_cacheflavor_tokens = {
271 { Opt_cache_loose, "loose" },
272 { Opt_cache_strict, "strict" },
273 { Opt_cache_none, "none" },
274 { Opt_cache_err, NULL }
275};
276
Jeff Layton23db65f2012-05-15 12:20:51 -0400277static const match_table_t cifs_smb_version_tokens = {
278 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600279 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000280 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500281 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500282 { Smb_302, SMB302_VERSION_STRING },
Jeff Layton23db65f2012-05-15 12:20:51 -0400283};
284
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300285static int ip_connect(struct TCP_Server_Info *server);
286static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400287static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400288static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400289static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
290 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Jeff Laytond5c56052008-12-01 18:42:33 -0500292/*
293 * cifs tcp session reconnection
294 *
295 * mark tcp session as reconnecting so temporarily locked
296 * mark all smb sessions as reconnecting for tcp session
297 * reconnect tcp session
298 * wake up waiters on reconnection? - (not needed currently)
299 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400300int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301cifs_reconnect(struct TCP_Server_Info *server)
302{
303 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500304 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000305 struct cifs_ses *ses;
306 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000307 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400308 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000311 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000312 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 next time through the loop */
314 spin_unlock(&GlobalMid_Lock);
315 return rc;
316 } else
317 server->tcpStatus = CifsNeedReconnect;
318 spin_unlock(&GlobalMid_Lock);
319 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400320#ifdef CONFIG_CIFS_SMB2
321 server->max_read = 0;
322#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Joe Perchesf96637b2013-05-04 22:12:25 -0500324 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
326 /* before reconnecting the tcp session, mark the smb session (uid)
327 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500328 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
329 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530330 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500331 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000332 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500333 ses->need_reconnect = true;
334 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500335 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000336 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500337 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530340 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500343 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500344 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000345 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500346 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
347 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800348 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500349 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
350 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 sock_release(server->ssocket);
352 server->ssocket = NULL;
353 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500354 server->sequence_number = 0;
355 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500356 kfree(server->session_key.response);
357 server->session_key.response = NULL;
358 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000359 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500360 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500362 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400363 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500364 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500366 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
367 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400368 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
369 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400370 list_move(&mid_entry->qhead, &retry_list);
371 }
372 spin_unlock(&GlobalMid_Lock);
373
Joe Perchesf96637b2013-05-04 22:12:25 -0500374 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400375 list_for_each_safe(tmp, tmp2, &retry_list) {
376 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500377 list_del_init(&mid_entry->qhead);
378 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400381 do {
Steve French6c3d8902006-07-31 22:46:20 +0000382 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300383
384 /* we should try only the port we connected to before */
Jeff Layton73e216a2013-09-05 08:38:10 -0400385 mutex_lock(&server->srv_mutex);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300386 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000387 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500388 cifs_dbg(FYI, "reconnect error %d\n", rc);
Steve French0cb766a2005-04-28 22:41:11 -0700389 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 } else {
391 atomic_inc(&tcpSesReconnectCount);
392 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000393 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000394 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000395 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 }
Jeff Layton73e216a2013-09-05 08:38:10 -0400397 mutex_unlock(&server->srv_mutex);
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400398 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 return rc;
401}
402
Jeff Laytonc74093b2011-01-11 07:24:23 -0500403static void
404cifs_echo_request(struct work_struct *work)
405{
406 int rc;
407 struct TCP_Server_Info *server = container_of(work,
408 struct TCP_Server_Info, echo.work);
409
Jeff Layton247ec9b2011-02-04 17:09:50 -0500410 /*
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400411 * We cannot send an echo if it is disabled or until the
412 * NEGOTIATE_PROTOCOL request is done, which is indicated by
413 * server->ops->need_neg() == true. Also, no need to ping if
414 * we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500415 */
Pavel Shilovsky286170a2012-05-25 10:43:58 +0400416 if (!server->ops->need_neg || server->ops->need_neg(server) ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400417 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Jeff Layton247ec9b2011-02-04 17:09:50 -0500418 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500419 goto requeue_echo;
420
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400421 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500422 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500423 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
424 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500425
426requeue_echo:
Jeff Laytonda472fc2012-03-23 14:40:53 -0400427 queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500428}
429
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400430static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400431allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400432{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400433 if (!server->bigbuf) {
434 server->bigbuf = (char *)cifs_buf_get();
435 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500436 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400437 msleep(3000);
438 /* retry will check if exiting */
439 return false;
440 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400441 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400442 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400443 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400444 }
445
Jeff Layton2a37ef92011-10-19 15:29:23 -0400446 if (!server->smallbuf) {
447 server->smallbuf = (char *)cifs_small_buf_get();
448 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500449 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400450 msleep(1000);
451 /* retry will check if exiting */
452 return false;
453 }
454 /* beginning of smb buffer is cleared in our buf_get */
455 } else {
456 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400457 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400458 }
459
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400460 return true;
461}
462
Jeff Laytonba749e62011-10-11 06:41:32 -0400463static bool
464server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400465{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300466 /*
467 * We need to wait 2 echo intervals to make sure we handle such
468 * situations right:
469 * 1s client sends a normal SMB request
470 * 2s client gets a response
471 * 30s echo workqueue job pops, and decides we got a response recently
472 * and don't need to send another
473 * ...
474 * 65s kernel_recvmsg times out, and we see that we haven't gotten
475 * a response in >60s.
476 */
477 if (server->tcpStatus == CifsGood &&
478 time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500479 cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n",
480 server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400481 cifs_reconnect(server);
482 wake_up(&server->response_q);
483 return true;
484 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400485
Jeff Laytonba749e62011-10-11 06:41:32 -0400486 return false;
487}
488
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400489/*
490 * kvec_array_init - clone a kvec array, and advance into it
491 * @new: pointer to memory for cloned array
492 * @iov: pointer to original array
493 * @nr_segs: number of members in original array
494 * @bytes: number of bytes to advance into the cloned array
495 *
496 * This function will copy the array provided in iov to a section of memory
497 * and advance the specified number of bytes into the new array. It returns
498 * the number of segments in the new array. "new" must be at least as big as
499 * the original iov array.
500 */
501static unsigned int
502kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
503 size_t bytes)
504{
505 size_t base = 0;
506
507 while (bytes || !iov->iov_len) {
508 int copy = min(bytes, iov->iov_len);
509
510 bytes -= copy;
511 base += copy;
512 if (iov->iov_len == base) {
513 iov++;
514 nr_segs--;
515 base = 0;
516 }
517 }
518 memcpy(new, iov, sizeof(*iov) * nr_segs);
519 new->iov_base += base;
520 new->iov_len -= base;
521 return nr_segs;
522}
523
Jeff Layton1041e3f2011-10-19 15:28:27 -0400524static struct kvec *
525get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
526{
527 struct kvec *new_iov;
528
529 if (server->iov && nr_segs <= server->nr_iov)
530 return server->iov;
531
532 /* not big enough -- allocate a new one and release the old */
533 new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
534 if (new_iov) {
535 kfree(server->iov);
536 server->iov = new_iov;
537 server->nr_iov = nr_segs;
538 }
539 return new_iov;
540}
541
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400542int
543cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
544 unsigned int nr_segs, unsigned int to_read)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400545{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400546 int length = 0;
547 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400548 unsigned int segs;
Jeff Laytone831e6c2011-10-11 06:41:32 -0400549 struct msghdr smb_msg;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400550 struct kvec *iov;
551
Jeff Layton1041e3f2011-10-19 15:28:27 -0400552 iov = get_server_iovec(server, nr_segs);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400553 if (!iov)
554 return -ENOMEM;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400555
Jeff Laytone831e6c2011-10-11 06:41:32 -0400556 smb_msg.msg_control = NULL;
557 smb_msg.msg_controllen = 0;
558
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400559 for (total_read = 0; to_read; total_read += length, to_read -= length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500560 try_to_freeze();
561
Jeff Laytonba749e62011-10-11 06:41:32 -0400562 if (server_unresponsive(server)) {
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400563 total_read = -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400564 break;
565 }
566
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400567 segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
568
569 length = kernel_recvmsg(server->ssocket, &smb_msg,
570 iov, segs, to_read, 0);
571
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400572 if (server->tcpStatus == CifsExiting) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400573 total_read = -ESHUTDOWN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400574 break;
575 } else if (server->tcpStatus == CifsNeedReconnect) {
576 cifs_reconnect(server);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400577 total_read = -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400578 break;
579 } else if (length == -ERESTARTSYS ||
580 length == -EAGAIN ||
581 length == -EINTR) {
582 /*
583 * Minimum sleep to prevent looping, allowing socket
584 * to clear and app threads to set tcpStatus
585 * CifsNeedReconnect if server hung.
586 */
587 usleep_range(1000, 2000);
588 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400589 continue;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400590 } else if (length <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500591 cifs_dbg(FYI, "Received no data or error: expecting %d\n"
592 "got %d", to_read, length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400593 cifs_reconnect(server);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400594 total_read = -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400595 break;
596 }
597 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400598 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400599}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400600
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400601int
602cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
603 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400604{
605 struct kvec iov;
606
607 iov.iov_base = buf;
608 iov.iov_len = to_read;
609
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400610 return cifs_readv_from_socket(server, &iov, 1, to_read);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400611}
612
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400613static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400614is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400615{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400616 /*
617 * The first byte big endian of the length field,
618 * is actually not part of the length but the type
619 * with the most common, zero, as regular data.
620 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400621 switch (type) {
622 case RFC1002_SESSION_MESSAGE:
623 /* Regular SMB response */
624 return true;
625 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500626 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400627 break;
628 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500629 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400630 break;
631 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400632 /*
633 * We get this from Windows 98 instead of an error on
634 * SMB negprot response.
635 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500636 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400637 /* give server a second to clean up */
638 msleep(1000);
639 /*
640 * Always try 445 first on reconnect since we get NACK
641 * on some if we ever connected to port 139 (the NACK
642 * is since we do not begin with RFC1001 session
643 * initialize frame).
644 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400645 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400646 cifs_reconnect(server);
647 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400648 break;
649 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500650 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400651 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400652 }
653
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400654 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400655}
656
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400657void
658dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400659{
660#ifdef CONFIG_CIFS_STATS2
661 mid->when_received = jiffies;
662#endif
663 spin_lock(&GlobalMid_Lock);
664 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400665 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400666 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400667 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400668 list_del_init(&mid->qhead);
669 spin_unlock(&GlobalMid_Lock);
670}
671
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400672static void
673handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400674 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400675{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400676 if (server->ops->check_trans2 &&
677 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400678 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400679 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400680 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400681 /* Was previous buf put in mpx struct for multi-rsp? */
682 if (!mid->multiRsp) {
683 /* smb buffer will be freed by user thread */
684 if (server->large_buf)
685 server->bigbuf = NULL;
686 else
687 server->smallbuf = NULL;
688 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400689 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400690}
691
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400692static void clean_demultiplex_info(struct TCP_Server_Info *server)
693{
694 int length;
695
696 /* take it off the list, if it's not already */
697 spin_lock(&cifs_tcp_ses_lock);
698 list_del_init(&server->tcp_ses_list);
699 spin_unlock(&cifs_tcp_ses_lock);
700
701 spin_lock(&GlobalMid_Lock);
702 server->tcpStatus = CifsExiting;
703 spin_unlock(&GlobalMid_Lock);
704 wake_up_all(&server->response_q);
705
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400706 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300707 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400708 if (server->credits <= 0)
709 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300710 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400711 /*
712 * Although there should not be any requests blocked on this queue it
713 * can not hurt to be paranoid and try to wake up requests that may
714 * haven been blocked when more than 50 at time were on the wire to the
715 * same server - they now will see the session is in exit state and get
716 * out of SendReceive.
717 */
718 wake_up_all(&server->request_q);
719 /* give those requests time to exit */
720 msleep(125);
721
722 if (server->ssocket) {
723 sock_release(server->ssocket);
724 server->ssocket = NULL;
725 }
726
727 if (!list_empty(&server->pending_mid_q)) {
728 struct list_head dispose_list;
729 struct mid_q_entry *mid_entry;
730 struct list_head *tmp, *tmp2;
731
732 INIT_LIST_HEAD(&dispose_list);
733 spin_lock(&GlobalMid_Lock);
734 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
735 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500736 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400737 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400738 list_move(&mid_entry->qhead, &dispose_list);
739 }
740 spin_unlock(&GlobalMid_Lock);
741
742 /* now walk dispose list and issue callbacks */
743 list_for_each_safe(tmp, tmp2, &dispose_list) {
744 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500745 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400746 list_del_init(&mid_entry->qhead);
747 mid_entry->callback(mid_entry);
748 }
749 /* 1/8th of sec is more than enough time for them to exit */
750 msleep(125);
751 }
752
753 if (!list_empty(&server->pending_mid_q)) {
754 /*
755 * mpx threads have not exited yet give them at least the smb
756 * send timeout time for long ops.
757 *
758 * Due to delays on oplock break requests, we need to wait at
759 * least 45 seconds before giving up on a request getting a
760 * response and going ahead and killing cifsd.
761 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500762 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400763 msleep(46000);
764 /*
765 * If threads still have not exited they are probably never
766 * coming home not much else we can do but free the memory.
767 */
768 }
769
770 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400771 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400772 kfree(server);
773
774 length = atomic_dec_return(&tcpSesAllocCount);
775 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -0700776 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400777}
778
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400779static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400780standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
781{
782 int length;
783 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400784 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400785
786 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400787 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500788 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400789 cifs_reconnect(server);
790 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +0400791 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400792 }
793
794 /* switch to large buffer if too big for a small one */
795 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
796 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400797 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400798 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400799 }
800
801 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400802 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
803 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400804 if (length < 0)
805 return length;
806 server->total_read += length;
807
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400808 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400809
810 /*
811 * We know that we received enough to get to the MID as we
812 * checked the pdu_length earlier. Now check to see
813 * if the rest of the header is OK. We borrow the length
814 * var for the rest of the loop to avoid a new stack var.
815 *
816 * 48 bytes is enough to display the header and a little bit
817 * into the payload for debugging purposes.
818 */
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400819 length = server->ops->check_message(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400820 if (length != 0)
821 cifs_dump_mem("Bad SMB: ", buf,
822 min_t(unsigned int, server->total_read, 48));
823
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700824 if (server->ops->is_status_pending &&
825 server->ops->is_status_pending(buf, server, length))
826 return -1;
827
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500828 if (!mid)
829 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400830
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400831 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500832 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400833}
834
835static int
Al Viro7c97c202011-06-21 08:51:28 -0400836cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837{
838 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400839 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400840 unsigned int pdu_length;
841 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500842 struct task_struct *task_to_wake = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500846 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400847
848 length = atomic_inc_return(&tcpSesAllocCount);
849 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -0700850 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700852 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000853 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700854 if (try_to_freeze())
855 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700856
Jeff Layton2a37ef92011-10-19 15:29:23 -0400857 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400858 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700859
Jeff Layton2a37ef92011-10-19 15:29:23 -0400860 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400861 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000862 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000863
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400864 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400865 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000866 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400867 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700868
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400869 /*
870 * The right amount was read from socket - 4 bytes,
871 * so we can now interpret the length field.
872 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400873 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700874
Joe Perchesf96637b2013-05-04 22:12:25 -0500875 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400876 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000877 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700878
Jeff Layton89482a52011-10-19 15:28:57 -0400879 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400880 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500881 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
882 pdu_length);
Jeff Layton89482a52011-10-19 15:28:57 -0400883 cifs_reconnect(server);
884 wake_up(&server->response_q);
885 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700886 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400887
Jeff Layton89482a52011-10-19 15:28:57 -0400888 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400889 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400890 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -0400891 if (length < 0)
892 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400893 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400894
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400895 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400896
Jeff Layton44d22d82011-10-19 15:29:49 -0400897 if (!mid_entry || !mid_entry->receive)
898 length = standard_receive3(server, mid_entry);
899 else
900 length = mid_entry->receive(server, mid_entry);
901
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400902 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700903 continue;
904
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400905 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400906 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700907
Steve Frenchfda35942011-01-20 18:06:34 +0000908 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500909 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -0400910 if (!mid_entry->multiRsp || mid_entry->multiEnd)
911 mid_entry->callback(mid_entry);
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400912 } else if (!server->ops->is_oplock_break ||
913 !server->ops->is_oplock_break(buf, server)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500914 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
915 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400916 cifs_dump_mem("Received Data is: ", buf,
917 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000918#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400919 if (server->ops->dump_detail)
920 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +0000921 cifs_dump_mids(server);
922#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000923
Steve Frenche4eb2952005-04-28 22:41:09 -0700924 }
925 } /* end while !EXITING */
926
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800927 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400928 cifs_buf_release(server->bigbuf);
929 if (server->smallbuf) /* no sense logging a debug message if NULL */
930 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500932 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400933 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -0500934
935 /* if server->tsk was NULL then wait for a signal before exiting */
936 if (!task_to_wake) {
937 set_current_state(TASK_INTERRUPTIBLE);
938 while (!signal_pending(current)) {
939 schedule();
940 set_current_state(TASK_INTERRUPTIBLE);
941 }
942 set_current_state(TASK_RUNNING);
943 }
944
Jeff Layton0468a2c2008-12-01 07:09:35 -0500945 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946}
947
Jeff Laytonc359cf32007-11-16 22:22:06 +0000948/* extract the host portion of the UNC string */
949static char *
950extract_hostname(const char *unc)
951{
952 const char *src;
953 char *dst, *delim;
954 unsigned int len;
955
956 /* skip double chars at beginning of string */
957 /* BB: check validity of these bytes? */
958 src = unc + 2;
959
960 /* delimiter between hostname and sharename is always '\\' now */
961 delim = strchr(src, '\\');
962 if (!delim)
963 return ERR_PTR(-EINVAL);
964
965 len = delim - src;
966 dst = kmalloc((len + 1), GFP_KERNEL);
967 if (dst == NULL)
968 return ERR_PTR(-ENOMEM);
969
970 memcpy(dst, src, len);
971 dst[len] = '\0';
972
973 return dst;
974}
975
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400976static int get_option_ul(substring_t args[], unsigned long *option)
977{
978 int rc;
979 char *string;
980
981 string = match_strdup(args);
982 if (string == NULL)
983 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +0100984 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400985 kfree(string);
986
987 return rc;
988}
989
Eric W. Biederman3da46562013-02-06 01:37:39 -0800990static int get_option_uid(substring_t args[], kuid_t *result)
991{
992 unsigned long value;
993 kuid_t uid;
994 int rc;
995
996 rc = get_option_ul(args, &value);
997 if (rc)
998 return rc;
999
1000 uid = make_kuid(current_user_ns(), value);
1001 if (!uid_valid(uid))
1002 return -EINVAL;
1003
1004 *result = uid;
1005 return 0;
1006}
1007
1008static int get_option_gid(substring_t args[], kgid_t *result)
1009{
1010 unsigned long value;
1011 kgid_t gid;
1012 int rc;
1013
1014 rc = get_option_ul(args, &value);
1015 if (rc)
1016 return rc;
1017
1018 gid = make_kgid(current_user_ns(), value);
1019 if (!gid_valid(gid))
1020 return -EINVAL;
1021
1022 *result = gid;
1023 return 0;
1024}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001025
1026static int cifs_parse_security_flavors(char *value,
1027 struct smb_vol *vol)
1028{
1029
1030 substring_t args[MAX_OPT_ARGS];
1031
Jeff Layton1e3cc572013-06-10 17:12:23 -05001032 /*
1033 * With mount options, the last one should win. Reset any existing
1034 * settings back to default.
1035 */
1036 vol->sectype = Unspecified;
1037 vol->sign = false;
1038
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001039 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001040 case Opt_sec_krb5p:
1041 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1042 return 1;
1043 case Opt_sec_krb5i:
1044 vol->sign = true;
1045 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001046 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001047 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001048 break;
1049 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001050 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001051 /* Fallthrough */
1052 case Opt_sec_ntlmssp:
1053 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001054 break;
1055 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001056 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001057 /* Fallthrough */
1058 case Opt_ntlm:
1059 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001060 break;
1061 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001062 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001063 /* Fallthrough */
1064 case Opt_sec_ntlmv2:
1065 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001066 break;
1067#ifdef CONFIG_CIFS_WEAK_PW_HASH
1068 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001069 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001070 break;
1071#endif
1072 case Opt_sec_none:
1073 vol->nullauth = 1;
1074 break;
1075 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001076 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001077 return 1;
1078 }
1079
1080 return 0;
1081}
1082
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001084cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1085{
1086 substring_t args[MAX_OPT_ARGS];
1087
1088 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1089 case Opt_cache_loose:
1090 vol->direct_io = false;
1091 vol->strict_io = false;
1092 break;
1093 case Opt_cache_strict:
1094 vol->direct_io = false;
1095 vol->strict_io = true;
1096 break;
1097 case Opt_cache_none:
1098 vol->direct_io = true;
1099 vol->strict_io = false;
1100 break;
1101 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001102 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001103 return 1;
1104 }
1105 return 0;
1106}
1107
1108static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001109cifs_parse_smb_version(char *value, struct smb_vol *vol)
1110{
1111 substring_t args[MAX_OPT_ARGS];
1112
1113 switch (match_token(value, cifs_smb_version_tokens, args)) {
1114 case Smb_1:
1115 vol->ops = &smb1_operations;
1116 vol->vals = &smb1_values;
1117 break;
Steve French1080ef72011-02-24 18:07:19 +00001118#ifdef CONFIG_CIFS_SMB2
Steve Frenchdd446b12012-11-28 23:21:06 -06001119 case Smb_20:
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001120 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001121 vol->vals = &smb20_values;
1122 break;
Steve French1080ef72011-02-24 18:07:19 +00001123 case Smb_21:
1124 vol->ops = &smb21_operations;
1125 vol->vals = &smb21_values;
1126 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001127 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001128 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001129 vol->vals = &smb30_values;
1130 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001131 case Smb_302:
1132 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1133 vol->vals = &smb302_values;
1134 break;
Steve French1080ef72011-02-24 18:07:19 +00001135#endif
Jeff Layton23db65f2012-05-15 12:20:51 -04001136 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001137 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001138 return 1;
1139 }
1140 return 0;
1141}
1142
Jeff Laytond387a5c2012-12-10 06:10:46 -05001143/*
1144 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1145 * fields with the result. Returns 0 on success and an error otherwise.
1146 */
1147static int
1148cifs_parse_devname(const char *devname, struct smb_vol *vol)
1149{
1150 char *pos;
1151 const char *delims = "/\\";
1152 size_t len;
1153
1154 /* make sure we have a valid UNC double delimiter prefix */
1155 len = strspn(devname, delims);
1156 if (len != 2)
1157 return -EINVAL;
1158
1159 /* find delimiter between host and sharename */
1160 pos = strpbrk(devname + 2, delims);
1161 if (!pos)
1162 return -EINVAL;
1163
1164 /* skip past delimiter */
1165 ++pos;
1166
1167 /* now go until next delimiter or end of string */
1168 len = strcspn(pos, delims);
1169
1170 /* move "pos" up to delimiter or NULL */
1171 pos += len;
1172 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1173 if (!vol->UNC)
1174 return -ENOMEM;
1175
1176 convert_delimiter(vol->UNC, '\\');
1177
1178 /* If pos is NULL, or is a bogus trailing delimiter then no prepath */
1179 if (!*pos++ || !*pos)
1180 return 0;
1181
1182 vol->prepath = kstrdup(pos, GFP_KERNEL);
1183 if (!vol->prepath)
1184 return -ENOMEM;
1185
1186 return 0;
1187}
1188
Jeff Layton23db65f2012-05-15 12:20:51 -04001189static int
Sean Finneyb9468452011-04-11 13:19:32 +00001190cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001191 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001193 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001194 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 unsigned int temp_len, i, j;
1196 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001197 short int override_uid = -1;
1198 short int override_gid = -1;
1199 bool uid_specified = false;
1200 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001201 bool sloppy = false;
1202 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001203 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001204 char *string = NULL;
1205 char *tmp_end, *value;
1206 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001207 bool got_ip = false;
1208 unsigned short port = 0;
1209 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001212 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001213 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Jeff Layton6ee95422012-11-26 11:09:57 -05001215 /* ensure we always start with zeroed-out smb_vol */
1216 memset(vol, 0, sizeof(*vol));
1217
Jeff Layton88463992010-11-22 15:31:03 -05001218 /*
1219 * does not have to be perfect mapping since field is
1220 * informational, only used for servers that do not support
1221 * port 445 and it can be overridden at mount time
1222 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001223 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1224 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001225 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1226
Jeff Layton1397f2e2011-01-07 11:30:28 -05001227 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001228 /* null target name indicates to use *SMBSERVR default called name
1229 if we end up sending RFC1001 session initialize */
1230 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001231 vol->cred_uid = current_uid();
1232 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001233 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001234
Steve French2baa2682014-09-27 02:19:01 -05001235 /*
1236 * default to SFM style remapping of seven reserved characters
1237 * unless user overrides it or we negotiate CIFS POSIX where
1238 * it is unnecessary. Can not simultaneously use more than one mapping
1239 * since then readdir could list files that open could not open
1240 */
1241 vol->remap = true;
1242
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001243 /* default to only allowing write access to owner of the mount */
1244 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
1246 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001247 /* default is always to request posix paths. */
1248 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001249 /* default to using server inode numbers where available */
1250 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001251
Jeff Layton1b359202012-09-19 15:20:27 -07001252 /* default is to use strict cifs caching semantics */
1253 vol->strict_io = true;
1254
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301255 vol->actimeo = CIFS_DEF_ACTIMEO;
1256
Jeff Layton23db65f2012-05-15 12:20:51 -04001257 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1258 vol->ops = &smb1_operations;
1259 vol->vals = &smb1_values;
1260
Sean Finneyb9468452011-04-11 13:19:32 +00001261 if (!mountdata)
1262 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Sean Finneyb9468452011-04-11 13:19:32 +00001264 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1265 if (!mountdata_copy)
1266 goto cifs_parse_mount_err;
1267
1268 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001269 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001270
Steve French50c2f752007-07-13 00:33:32 +00001271 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001272 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 separator[0] = options[4];
1274 options += 5;
1275 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001276 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 }
1278 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001279 vol->backupuid_specified = false; /* no backup intent for a user */
1280 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001281
Jeff Layton37d4f992013-05-24 07:40:05 -04001282 switch (cifs_parse_devname(devname, vol)) {
1283 case 0:
1284 break;
1285 case -ENOMEM:
1286 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1287 goto cifs_parse_mount_err;
1288 case -EINVAL:
1289 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1290 goto cifs_parse_mount_err;
1291 default:
1292 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1293 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001294 }
1295
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001297 substring_t args[MAX_OPT_ARGS];
1298 unsigned long option;
1299 int token;
1300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 if (!*data)
1302 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001304 token = match_token(data, cifs_mount_option_tokens, args);
1305
1306 switch (token) {
1307
1308 /* Ingnore the following */
1309 case Opt_ignore:
1310 break;
1311
1312 /* Boolean values */
1313 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001315 break;
1316 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001318 break;
1319 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001320 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001321 break;
1322 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001323 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001324 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001325 case Opt_forcegid:
1326 override_gid = 1;
1327 break;
1328 case Opt_noforcegid:
1329 override_gid = 0;
1330 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001331 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001332 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001333 break;
1334 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001335 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001336 break;
1337 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001339 break;
1340 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001342 break;
1343 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001345 break;
1346 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001348 break;
1349 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001350 vol->sfu_remap = true;
1351 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001352 break;
1353 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001354 vol->sfu_remap = false;
1355 break;
1356 case Opt_mapposix:
1357 vol->remap = true;
1358 vol->sfu_remap = false; /* disable SFU mapping */
1359 break;
1360 case Opt_nomapposix:
1361 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362 break;
1363 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001364 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001365 break;
1366 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001367 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 break;
1369 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001370 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371 break;
1372 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001373 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001374 break;
1375 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001376 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001377 break;
1378 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001379 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
1381 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001382 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001385 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001388 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001389 /*
1390 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001391 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001392 * local vfs will do advisory
1393 */
Steve French50c2f752007-07-13 00:33:32 +00001394 if (vol->file_mode ==
1395 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001396 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001397 break;
1398 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001399 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001400 break;
1401 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001403 break;
1404 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001406 break;
1407 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001408 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001409 break;
1410 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001411 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001412 break;
1413 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
1425 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001426 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 break;
1428 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001429 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001438 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001439 break;
1440 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001441 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
1443 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001444 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 break;
1452 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001453 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001454 break;
1455 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001456 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001457 break;
1458 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001459 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 * is a per tree connection (mount) not a per socket
1461 * or per-smb connection option in the protocol
1462 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1463 */
Steve French95b1cb92008-05-15 16:44:38 +00001464 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001465 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001466 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001467 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001468 break;
1469 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301470#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001471 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001472 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301473#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301474 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001475 break;
1476 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001477 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001478 break;
1479 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001480 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001481 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001482 case Opt_sloppy:
1483 sloppy = true;
1484 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001485 case Opt_nosharesock:
1486 vol->nosharesock = true;
1487 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001488
1489 /* Numeric Values */
1490 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001491 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001492 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1493 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001494 goto cifs_parse_mount_err;
1495 }
1496 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001497 break;
1498 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001499 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001500 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1501 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001502 goto cifs_parse_mount_err;
1503 }
1504 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001505 break;
1506 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001507 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001508 cifs_dbg(VFS, "%s: Invalid uid value\n",
1509 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001510 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001512 uid_specified = true;
1513 break;
1514 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001515 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001516 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1517 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001518 goto cifs_parse_mount_err;
1519 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001520 break;
1521 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001522 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001523 cifs_dbg(VFS, "%s: Invalid gid value\n",
1524 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001525 goto cifs_parse_mount_err;
1526 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001527 gid_specified = true;
1528 break;
1529 case Opt_file_mode:
1530 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001531 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1532 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001533 goto cifs_parse_mount_err;
1534 }
1535 vol->file_mode = option;
1536 break;
1537 case Opt_dirmode:
1538 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001539 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1540 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001541 goto cifs_parse_mount_err;
1542 }
1543 vol->dir_mode = option;
1544 break;
1545 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001546 if (get_option_ul(args, &option) ||
1547 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001548 cifs_dbg(VFS, "%s: Invalid port value\n",
1549 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001550 goto cifs_parse_mount_err;
1551 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001552 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001553 break;
1554 case Opt_rsize:
1555 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001556 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1557 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001558 goto cifs_parse_mount_err;
1559 }
1560 vol->rsize = option;
1561 break;
1562 case Opt_wsize:
1563 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001564 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1565 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001566 goto cifs_parse_mount_err;
1567 }
1568 vol->wsize = option;
1569 break;
1570 case Opt_actimeo:
1571 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001572 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1573 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001574 goto cifs_parse_mount_err;
1575 }
1576 vol->actimeo = HZ * option;
1577 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001578 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001579 goto cifs_parse_mount_err;
1580 }
1581 break;
1582
1583 /* String Arguments */
1584
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001585 case Opt_blank_user:
1586 /* null user, ie. anonymous authentication */
1587 vol->nullauth = 1;
1588 vol->username = NULL;
1589 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001590 case Opt_user:
1591 string = match_strdup(args);
1592 if (string == NULL)
1593 goto out_nomem;
1594
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04001595 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
1596 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001597 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001598 goto cifs_parse_mount_err;
1599 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001600
1601 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001602 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001603 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001604 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001605 break;
1606 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001607 /* passwords have to be handled differently
1608 * to allow the character used for deliminator
1609 * to be passed within them
1610 */
1611
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001612 /*
1613 * Check if this is a case where the password
1614 * starts with a delimiter
1615 */
1616 tmp_end = strchr(data, '=');
1617 tmp_end++;
1618 if (!(tmp_end < end && tmp_end[1] == delim)) {
1619 /* No it is not. Set the password to NULL */
Namjae Jeond6ccf492014-08-21 19:11:20 +09001620 kfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001621 vol->password = NULL;
1622 break;
1623 }
1624 /* Yes it is. Drop down to Opt_pass below.*/
1625 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001626 /* Obtain the value string */
1627 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001628 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001629
1630 /* Set tmp_end to end of the string */
1631 tmp_end = (char *) value + strlen(value);
1632
1633 /* Check if following character is the deliminator
1634 * If yes, we have encountered a double deliminator
1635 * reset the NULL character to the deliminator
1636 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301637 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001638 tmp_end[0] = delim;
1639
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301640 /* Keep iterating until we get to a single
1641 * deliminator OR the end
1642 */
1643 while ((tmp_end = strchr(tmp_end, delim))
1644 != NULL && (tmp_end[1] == delim)) {
1645 tmp_end = (char *) &tmp_end[2];
1646 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001647
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301648 /* Reset var options to point to next element */
1649 if (tmp_end) {
1650 tmp_end[0] = '\0';
1651 options = (char *) &tmp_end[1];
1652 } else
1653 /* Reached the end of the mount option
1654 * string */
1655 options = end;
1656 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001657
Namjae Jeond6ccf492014-08-21 19:11:20 +09001658 kfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001659 /* Now build new password string */
1660 temp_len = strlen(value);
1661 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1662 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001663 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001664 goto cifs_parse_mount_err;
1665 }
1666
1667 for (i = 0, j = 0; i < temp_len; i++, j++) {
1668 vol->password[j] = value[i];
1669 if ((value[i] == delim) &&
1670 value[i+1] == delim)
1671 /* skip the second deliminator */
1672 i++;
1673 }
1674 vol->password[j] = '\0';
1675 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001676 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001677 /* FIXME: should this be an error instead? */
1678 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001679 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001680 case Opt_ip:
1681 string = match_strdup(args);
1682 if (string == NULL)
1683 goto out_nomem;
1684
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001685 if (!cifs_convert_address(dstaddr, string,
1686 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001687 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001688 goto cifs_parse_mount_err;
1689 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001690 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001691 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001692 case Opt_domain:
1693 string = match_strdup(args);
1694 if (string == NULL)
1695 goto out_nomem;
1696
Chen Gang057d6332013-07-19 09:01:36 +08001697 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
1698 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001699 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001700 goto cifs_parse_mount_err;
1701 }
1702
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001703 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001704 vol->domainname = kstrdup(string, GFP_KERNEL);
1705 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001706 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001707 goto cifs_parse_mount_err;
1708 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001709 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001710 break;
1711 case Opt_srcaddr:
1712 string = match_strdup(args);
1713 if (string == NULL)
1714 goto out_nomem;
1715
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001716 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001717 (struct sockaddr *)&vol->srcaddr,
1718 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001719 pr_warn("CIFS: Could not parse srcaddr: %s\n",
1720 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001721 goto cifs_parse_mount_err;
1722 }
1723 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001724 case Opt_iocharset:
1725 string = match_strdup(args);
1726 if (string == NULL)
1727 goto out_nomem;
1728
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001729 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001730 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001731 goto cifs_parse_mount_err;
1732 }
1733
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001734 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04001735 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001736 vol->iocharset = kstrdup(string,
1737 GFP_KERNEL);
1738 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001739 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001740 goto cifs_parse_mount_err;
1741 }
1742 }
1743 /* if iocharset not set then load_nls_default
1744 * is used by caller
1745 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001746 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001747 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001748 case Opt_netbiosname:
1749 string = match_strdup(args);
1750 if (string == NULL)
1751 goto out_nomem;
1752
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001753 memset(vol->source_rfc1001_name, 0x20,
1754 RFC1001_NAME_LEN);
1755 /*
1756 * FIXME: are there cases in which a comma can
1757 * be valid in workstation netbios name (and
1758 * need special handling)?
1759 */
1760 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1761 /* don't ucase netbiosname for user */
1762 if (string[i] == 0)
1763 break;
1764 vol->source_rfc1001_name[i] = string[i];
1765 }
1766 /* The string has 16th byte zero still from
1767 * set at top of the function
1768 */
1769 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001770 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001771 break;
1772 case Opt_servern:
1773 /* servernetbiosname specified override *SMBSERVER */
1774 string = match_strdup(args);
1775 if (string == NULL)
1776 goto out_nomem;
1777
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001778 /* last byte, type, is 0x20 for servr type */
1779 memset(vol->target_rfc1001_name, 0x20,
1780 RFC1001_NAME_LEN_WITH_NULL);
1781
1782 /* BB are there cases in which a comma can be
1783 valid in this workstation netbios name
1784 (and need special handling)? */
1785
1786 /* user or mount helper must uppercase the
1787 netbios name */
1788 for (i = 0; i < 15; i++) {
1789 if (string[i] == 0)
1790 break;
1791 vol->target_rfc1001_name[i] = string[i];
1792 }
1793 /* The string has 16th byte zero still from
1794 set at top of the function */
1795 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001796 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001797 break;
1798 case Opt_ver:
1799 string = match_strdup(args);
1800 if (string == NULL)
1801 goto out_nomem;
1802
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07001803 if (strncasecmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001804 /* This is the default */
1805 break;
1806 }
1807 /* For all other value, error */
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001808 pr_warn("CIFS: Invalid version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001809 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001810 case Opt_vers:
1811 string = match_strdup(args);
1812 if (string == NULL)
1813 goto out_nomem;
1814
1815 if (cifs_parse_smb_version(string, vol) != 0)
1816 goto cifs_parse_mount_err;
1817 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001818 case Opt_sec:
1819 string = match_strdup(args);
1820 if (string == NULL)
1821 goto out_nomem;
1822
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001823 if (cifs_parse_security_flavors(string, vol) != 0)
1824 goto cifs_parse_mount_err;
1825 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001826 case Opt_cache:
1827 string = match_strdup(args);
1828 if (string == NULL)
1829 goto out_nomem;
1830
1831 if (cifs_parse_cache_flavor(string, vol) != 0)
1832 goto cifs_parse_mount_err;
1833 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001834 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001835 /*
1836 * An option we don't recognize. Save it off for later
1837 * if we haven't already found one
1838 */
1839 if (!invalid)
1840 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001841 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001843 /* Free up any allocated string */
1844 kfree(string);
1845 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001847
Jeff Laytond8162552012-03-23 14:40:56 -04001848 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001849 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04001850 goto cifs_parse_mount_err;
1851 }
1852
Jeff Layton8a8798a2012-01-17 16:09:15 -05001853#ifndef CONFIG_KEYS
1854 /* Muliuser mounts require CONFIG_KEYS support */
1855 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001856 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001857 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001858 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001859#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001860 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04001861 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001862 goto cifs_parse_mount_err;
1863 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001864
Jeff Layton62a1a432012-12-10 06:10:45 -05001865 /* make sure UNC has a share name */
1866 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001867 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05001868 goto cifs_parse_mount_err;
1869 }
1870
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001871 if (!got_ip) {
1872 /* No ip= option specified? Try to get it from UNC */
1873 if (!cifs_convert_address(dstaddr, &vol->UNC[2],
1874 strlen(&vol->UNC[2]))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001875 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001876 goto cifs_parse_mount_err;
1877 }
1878 }
1879
1880 /* set the port that we got earlier */
1881 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001883 if (uid_specified)
1884 vol->override_uid = override_uid;
1885 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001886 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001887
1888 if (gid_specified)
1889 vol->override_gid = override_gid;
1890 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001891 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001892
Sean Finneyb9468452011-04-11 13:19:32 +00001893 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001895
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001896out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001897 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001898cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001900 kfree(mountdata_copy);
1901 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902}
1903
Ben Greear3eb9a882010-09-01 17:06:02 -07001904/** Returns true if srcaddr isn't specified and rhs isn't
1905 * specified, or if srcaddr is specified and
1906 * matches the IP address of the rhs argument.
1907 */
Jeff Layton45151482010-07-06 20:43:02 -04001908static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001909srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1910{
1911 switch (srcaddr->sa_family) {
1912 case AF_UNSPEC:
1913 return (rhs->sa_family == AF_UNSPEC);
1914 case AF_INET: {
1915 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1916 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1917 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1918 }
1919 case AF_INET6: {
1920 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05001921 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07001922 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1923 }
1924 default:
1925 WARN_ON(1);
1926 return false; /* don't expect to be here */
1927 }
1928}
1929
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001930/*
1931 * If no port is specified in addr structure, we try to match with 445 port
1932 * and if it fails - with 139 ports. It should be called only if address
1933 * families of server and addr are equal.
1934 */
1935static bool
1936match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1937{
Steve French6da97912011-03-13 18:55:55 +00001938 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001939
1940 switch (addr->sa_family) {
1941 case AF_INET:
1942 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1943 port = ((struct sockaddr_in *) addr)->sin_port;
1944 break;
1945 case AF_INET6:
1946 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1947 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1948 break;
1949 default:
1950 WARN_ON(1);
1951 return false;
1952 }
1953
1954 if (!port) {
1955 port = htons(CIFS_PORT);
1956 if (port == *sport)
1957 return true;
1958
1959 port = htons(RFC1001_PORT);
1960 }
1961
1962 return port == *sport;
1963}
Ben Greear3eb9a882010-09-01 17:06:02 -07001964
1965static bool
1966match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
1967 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968{
Jeff Layton45151482010-07-06 20:43:02 -04001969 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001970 case AF_INET: {
1971 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1972 struct sockaddr_in *srv_addr4 =
1973 (struct sockaddr_in *)&server->dstaddr;
1974
1975 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04001976 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001977 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001978 }
1979 case AF_INET6: {
1980 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1981 struct sockaddr_in6 *srv_addr6 =
1982 (struct sockaddr_in6 *)&server->dstaddr;
1983
Jeff Layton45151482010-07-06 20:43:02 -04001984 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001985 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04001986 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001987 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04001988 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001989 break;
1990 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001991 default:
1992 WARN_ON(1);
1993 return false; /* don't expect to be here */
1994 }
Jeff Layton45151482010-07-06 20:43:02 -04001995
Ben Greear3eb9a882010-09-01 17:06:02 -07001996 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
1997 return false;
1998
Jeff Layton45151482010-07-06 20:43:02 -04001999 return true;
2000}
2001
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002002static bool
2003match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2004{
Jeff Layton3f618222013-06-12 19:52:14 -05002005 /*
2006 * The select_sectype function should either return the vol->sectype
2007 * that was specified, or "Unspecified" if that sectype was not
2008 * compatible with the given NEGOTIATE request.
2009 */
2010 if (select_sectype(server, vol->sectype) == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002011 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002012
Jeff Layton3f618222013-06-12 19:52:14 -05002013 /*
2014 * Now check if signing mode is acceptable. No need to check
2015 * global_secflags at this point since if MUST_SIGN is set then
2016 * the server->sign had better be too.
2017 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002018 if (vol->sign && !server->sign)
2019 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002020
2021 return true;
2022}
2023
Jeff Layton9fa114f2012-11-26 11:09:57 -05002024static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002025{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002026 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2027
Jeff Laytona0b3df52013-05-24 07:40:59 -04002028 if (vol->nosharesock)
2029 return 0;
2030
Jeff Layton23db65f2012-05-15 12:20:51 -04002031 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2032 return 0;
2033
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002034 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2035 return 0;
2036
2037 if (!match_address(server, addr,
2038 (struct sockaddr *)&vol->srcaddr))
2039 return 0;
2040
2041 if (!match_port(server, addr))
2042 return 0;
2043
2044 if (!match_security(server, vol))
2045 return 0;
2046
2047 return 1;
2048}
2049
Jeff Layton45151482010-07-06 20:43:02 -04002050static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002051cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002052{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002053 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302055 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002056 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002057 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002058 continue;
2059
Jeff Laytone7ddee92008-11-14 13:44:38 -05002060 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302061 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002062 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002063 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302065 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 return NULL;
2067}
2068
Jeff Layton14fbf502008-11-14 13:53:46 -05002069static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002070cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002072 struct task_struct *task;
2073
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302074 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002075 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302076 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002077 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002079
Rob Landleyf1d0c992011-01-22 15:44:05 -06002080 put_net(cifs_net_ns(server));
2081
Jeff Laytone7ddee92008-11-14 13:44:38 -05002082 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302083 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002084
Jeff Laytonc74093b2011-01-11 07:24:23 -05002085 cancel_delayed_work_sync(&server->echo);
2086
Jeff Laytone7ddee92008-11-14 13:44:38 -05002087 spin_lock(&GlobalMid_Lock);
2088 server->tcpStatus = CifsExiting;
2089 spin_unlock(&GlobalMid_Lock);
2090
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002091 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302092 cifs_fscache_release_client_cookie(server);
2093
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002094 kfree(server->session_key.response);
2095 server->session_key.response = NULL;
2096 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002097
2098 task = xchg(&server->tsk, NULL);
2099 if (task)
2100 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101}
2102
Jeff Layton63c038c2008-12-01 18:41:46 -05002103static struct TCP_Server_Info *
2104cifs_get_tcp_session(struct smb_vol *volume_info)
2105{
2106 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002107 int rc;
2108
Joe Perchesf96637b2013-05-04 22:12:25 -05002109 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002110
2111 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002112 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002113 if (tcp_ses)
2114 return tcp_ses;
2115
2116 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2117 if (!tcp_ses) {
2118 rc = -ENOMEM;
2119 goto out_err;
2120 }
2121
Jeff Layton23db65f2012-05-15 12:20:51 -04002122 tcp_ses->ops = volume_info->ops;
2123 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002124 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002125 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2126 if (IS_ERR(tcp_ses->hostname)) {
2127 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002128 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002129 }
2130
2131 tcp_ses->noblocksnd = volume_info->noblocksnd;
2132 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002133 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002134 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002135 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002136 init_waitqueue_head(&tcp_ses->response_q);
2137 init_waitqueue_head(&tcp_ses->request_q);
2138 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2139 mutex_init(&tcp_ses->srv_mutex);
2140 memcpy(tcp_ses->workstation_RFC1001_name,
2141 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2142 memcpy(tcp_ses->server_RFC1001_name,
2143 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002144 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002145 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002146 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002147 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002148 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2149 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002150 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002151 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2152 sizeof(tcp_ses->srcaddr));
2153 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2154 sizeof(tcp_ses->dstaddr));
Sachin Prabhu39552ea2014-05-13 00:48:12 +01002155#ifdef CONFIG_CIFS_SMB2
2156 get_random_bytes(tcp_ses->client_guid, SMB2_CLIENT_GUID_SIZE);
2157#endif
Jeff Layton63c038c2008-12-01 18:41:46 -05002158 /*
2159 * at this point we are the only ones with the pointer
2160 * to the struct since the kernel thread not created yet
2161 * no need to spinlock this init of tcpStatus or srv_count
2162 */
2163 tcp_ses->tcpStatus = CifsNew;
2164 ++tcp_ses->srv_count;
2165
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002166 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002167 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002168 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002169 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002170 }
2171
2172 /*
2173 * since we're in a cifs function already, we know that
2174 * this will succeed. No need for try_module_get().
2175 */
2176 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002177 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002178 tcp_ses, "cifsd");
2179 if (IS_ERR(tcp_ses->tsk)) {
2180 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002181 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002182 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002183 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002184 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002185 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002186
2187 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302188 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002189 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302190 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002191
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302192 cifs_fscache_get_client_cookie(tcp_ses);
2193
Jeff Laytonc74093b2011-01-11 07:24:23 -05002194 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002195 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002196
Jeff Layton63c038c2008-12-01 18:41:46 -05002197 return tcp_ses;
2198
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002199out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002200 cifs_crypto_shash_release(tcp_ses);
2201
Rob Landleyf1d0c992011-01-22 15:44:05 -06002202 put_net(cifs_net_ns(tcp_ses));
2203
Jeff Layton63c038c2008-12-01 18:41:46 -05002204out_err:
2205 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002206 if (!IS_ERR(tcp_ses->hostname))
2207 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002208 if (tcp_ses->ssocket)
2209 sock_release(tcp_ses->ssocket);
2210 kfree(tcp_ses);
2211 }
2212 return ERR_PTR(rc);
2213}
2214
Steve French96daf2b2011-05-27 04:34:02 +00002215static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002216{
Jeff Layton3f618222013-06-12 19:52:14 -05002217 if (vol->sectype != Unspecified &&
2218 vol->sectype != ses->sectype)
2219 return 0;
2220
2221 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002222 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002223 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002224 return 0;
2225 break;
2226 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002227 /* NULL username means anonymous session */
2228 if (ses->user_name == NULL) {
2229 if (!vol->nullauth)
2230 return 0;
2231 break;
2232 }
2233
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002234 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002235 if (strncmp(ses->user_name,
2236 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002237 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002238 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002239 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002240 ses->password != NULL &&
2241 strncmp(ses->password,
2242 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002243 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002244 return 0;
2245 }
2246 return 1;
2247}
2248
Steve French96daf2b2011-05-27 04:34:02 +00002249static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002250cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251{
Steve French96daf2b2011-05-27 04:34:02 +00002252 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302254 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002255 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002256 if (ses->status == CifsExiting)
2257 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002258 if (!match_session(ses, vol))
2259 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002260 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302261 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002262 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302264 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 return NULL;
2266}
2267
Jeff Layton14fbf502008-11-14 13:53:46 -05002268static void
Steve French96daf2b2011-05-27 04:34:02 +00002269cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002270{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002271 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002272 struct TCP_Server_Info *server = ses->server;
2273
Joe Perchesf96637b2013-05-04 22:12:25 -05002274 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002275
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302276 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002277 if (ses->status == CifsExiting) {
2278 spin_unlock(&cifs_tcp_ses_lock);
2279 return;
2280 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002281 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302282 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002283 return;
2284 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002285 if (ses->status == CifsGood)
2286 ses->status = CifsExiting;
2287 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002288
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002289 if (ses->status == CifsExiting && server->ops->logoff) {
2290 xid = get_xid();
2291 rc = server->ops->logoff(xid, ses);
2292 if (rc)
2293 cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2294 __func__, rc);
2295 _free_xid(xid);
2296 }
2297
2298 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002299 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302300 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002301
Jeff Layton14fbf502008-11-14 13:53:46 -05002302 sesInfoFree(ses);
2303 cifs_put_tcp_session(server);
2304}
2305
Jeff Layton8a8798a2012-01-17 16:09:15 -05002306#ifdef CONFIG_KEYS
2307
Chen Gang057d6332013-07-19 09:01:36 +08002308/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
2309#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05002310
2311/* Populate username and pw fields from keyring if possible */
2312static int
2313cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2314{
2315 int rc = 0;
2316 char *desc, *delim, *payload;
2317 ssize_t len;
2318 struct key *key;
2319 struct TCP_Server_Info *server = ses->server;
2320 struct sockaddr_in *sa;
2321 struct sockaddr_in6 *sa6;
2322 struct user_key_payload *upayload;
2323
2324 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2325 if (!desc)
2326 return -ENOMEM;
2327
2328 /* try to find an address key first */
2329 switch (server->dstaddr.ss_family) {
2330 case AF_INET:
2331 sa = (struct sockaddr_in *)&server->dstaddr;
2332 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2333 break;
2334 case AF_INET6:
2335 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2336 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2337 break;
2338 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002339 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2340 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002341 rc = -EINVAL;
2342 goto out_err;
2343 }
2344
Joe Perchesf96637b2013-05-04 22:12:25 -05002345 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002346 key = request_key(&key_type_logon, desc, "");
2347 if (IS_ERR(key)) {
2348 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002349 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002350 rc = PTR_ERR(key);
2351 goto out_err;
2352 }
2353
2354 /* didn't work, try to find a domain key */
2355 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002356 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002357 key = request_key(&key_type_logon, desc, "");
2358 if (IS_ERR(key)) {
2359 rc = PTR_ERR(key);
2360 goto out_err;
2361 }
2362 }
2363
2364 down_read(&key->sem);
2365 upayload = key->payload.data;
2366 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002367 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002368 goto out_key_put;
2369 }
2370
2371 /* find first : in payload */
2372 payload = (char *)upayload->data;
2373 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002374 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002375 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002376 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2377 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002378 rc = -EINVAL;
2379 goto out_key_put;
2380 }
2381
2382 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002383 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002384 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2385 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002386 rc = -EINVAL;
2387 goto out_key_put;
2388 }
2389
2390 vol->username = kstrndup(payload, len, GFP_KERNEL);
2391 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002392 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2393 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002394 rc = -ENOMEM;
2395 goto out_key_put;
2396 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002397 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002398
2399 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002400 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002401 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002402 rc = -EINVAL;
2403 kfree(vol->username);
2404 vol->username = NULL;
2405 goto out_key_put;
2406 }
2407
2408 ++delim;
2409 vol->password = kstrndup(delim, len, GFP_KERNEL);
2410 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002411 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2412 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002413 rc = -ENOMEM;
2414 kfree(vol->username);
2415 vol->username = NULL;
2416 goto out_key_put;
2417 }
2418
2419out_key_put:
2420 up_read(&key->sem);
2421 key_put(key);
2422out_err:
2423 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002424 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002425 return rc;
2426}
2427#else /* ! CONFIG_KEYS */
2428static inline int
2429cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2430 struct cifs_ses *ses __attribute__((unused)))
2431{
2432 return -ENOSYS;
2433}
2434#endif /* CONFIG_KEYS */
2435
Steve French96daf2b2011-05-27 04:34:02 +00002436static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002437cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2438{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002439 int rc = -ENOMEM;
2440 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002441 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002442 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2443 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002444
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002445 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002446
Jeff Layton4ff67b72010-07-06 20:43:02 -04002447 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002448 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002449 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2450 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002451
Jeff Layton36988c72010-04-24 07:57:43 -04002452 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002453 rc = cifs_negotiate_protocol(xid, ses);
2454 if (rc) {
2455 mutex_unlock(&ses->session_mutex);
2456 /* problem -- put our ses reference */
2457 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002458 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002459 return ERR_PTR(rc);
2460 }
Jeff Layton36988c72010-04-24 07:57:43 -04002461 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002462 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002463 rc = cifs_setup_session(xid, ses,
2464 volume_info->local_nls);
2465 if (rc) {
2466 mutex_unlock(&ses->session_mutex);
2467 /* problem -- put our reference */
2468 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002469 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002470 return ERR_PTR(rc);
2471 }
2472 }
2473 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002474
2475 /* existing SMB ses has a server reference already */
2476 cifs_put_tcp_session(server);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002477 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002478 return ses;
2479 }
2480
Joe Perchesf96637b2013-05-04 22:12:25 -05002481 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002482 ses = sesInfoAlloc();
2483 if (ses == NULL)
2484 goto get_ses_fail;
2485
2486 /* new SMB session uses our server ref */
2487 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002488 if (server->dstaddr.ss_family == AF_INET6)
2489 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002490 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002491 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002492
Steve French8727c8a2011-02-25 01:11:56 -06002493 if (volume_info->username) {
2494 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2495 if (!ses->user_name)
2496 goto get_ses_fail;
2497 }
Jeff Layton36988c72010-04-24 07:57:43 -04002498
2499 /* volume_info->password freed at unmount */
2500 if (volume_info->password) {
2501 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2502 if (!ses->password)
2503 goto get_ses_fail;
2504 }
2505 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002506 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2507 if (!ses->domainName)
2508 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002509 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002510 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002511 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002512
Jeff Layton28e11bd2013-05-26 07:01:00 -04002513 ses->sectype = volume_info->sectype;
2514 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04002515
2516 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002517 rc = cifs_negotiate_protocol(xid, ses);
2518 if (!rc)
2519 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002520 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002521 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002522 goto get_ses_fail;
2523
2524 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302525 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002526 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302527 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002528
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002529 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002530 return ses;
2531
2532get_ses_fail:
2533 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002534 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002535 return ERR_PTR(rc);
2536}
2537
Steve French96daf2b2011-05-27 04:34:02 +00002538static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002539{
2540 if (tcon->tidStatus == CifsExiting)
2541 return 0;
2542 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2543 return 0;
2544 return 1;
2545}
2546
Steve French96daf2b2011-05-27 04:34:02 +00002547static struct cifs_tcon *
2548cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549{
2550 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002551 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302553 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002554 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002555 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002556 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002557 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002558 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302559 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 return tcon;
2561 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302562 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 return NULL;
2564}
2565
Jeff Laytonf1987b42008-11-15 11:12:47 -05002566static void
Steve French96daf2b2011-05-27 04:34:02 +00002567cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002568{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002569 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002570 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002571
Joe Perchesf96637b2013-05-04 22:12:25 -05002572 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302573 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002574 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302575 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002576 return;
2577 }
2578
2579 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302580 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002581
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002582 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002583 if (ses->server->ops->tree_disconnect)
2584 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002585 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002586
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302587 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002588 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002589 cifs_put_smb_ses(ses);
2590}
2591
Steve French96daf2b2011-05-27 04:34:02 +00002592static struct cifs_tcon *
2593cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002594{
2595 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002596 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002597
2598 tcon = cifs_find_tcon(ses, volume_info->UNC);
2599 if (tcon) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002600 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002601 /* existing tcon already has a reference */
2602 cifs_put_smb_ses(ses);
2603 if (tcon->seal != volume_info->seal)
Joe Perchesf96637b2013-05-04 22:12:25 -05002604 cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002605 return tcon;
2606 }
2607
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002608 if (!ses->server->ops->tree_connect) {
2609 rc = -ENOSYS;
2610 goto out_fail;
2611 }
2612
Jeff Laytond00c28d2010-04-24 07:57:44 -04002613 tcon = tconInfoAlloc();
2614 if (tcon == NULL) {
2615 rc = -ENOMEM;
2616 goto out_fail;
2617 }
2618
2619 tcon->ses = ses;
2620 if (volume_info->password) {
2621 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2622 if (!tcon->password) {
2623 rc = -ENOMEM;
2624 goto out_fail;
2625 }
2626 }
2627
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002628 /*
2629 * BB Do we need to wrap session_mutex around this TCon call and Unix
2630 * SetFS as we do on SessSetup and reconnect?
2631 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002632 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002633 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2634 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002635 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002636 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002637 if (rc)
2638 goto out_fail;
2639
2640 if (volume_info->nodfs) {
2641 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002642 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002643 }
2644 tcon->seal = volume_info->seal;
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002645 /*
2646 * We can have only one retry value for a connection to a share so for
2647 * resources mounted more than once to the same server share the last
2648 * value passed in for the retry flag is used.
2649 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04002650 tcon->retry = volume_info->retry;
2651 tcon->nocase = volume_info->nocase;
2652 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07002653 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002654
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302655 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002656 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302657 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002658
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302659 cifs_fscache_get_super_cookie(tcon);
2660
Jeff Laytond00c28d2010-04-24 07:57:44 -04002661 return tcon;
2662
2663out_fail:
2664 tconInfoFree(tcon);
2665 return ERR_PTR(rc);
2666}
2667
Jeff Layton9d002df2010-10-06 19:51:11 -04002668void
2669cifs_put_tlink(struct tcon_link *tlink)
2670{
2671 if (!tlink || IS_ERR(tlink))
2672 return;
2673
2674 if (!atomic_dec_and_test(&tlink->tl_count) ||
2675 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2676 tlink->tl_time = jiffies;
2677 return;
2678 }
2679
2680 if (!IS_ERR(tlink_tcon(tlink)))
2681 cifs_put_tcon(tlink_tcon(tlink));
2682 kfree(tlink);
2683 return;
2684}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002685
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002686static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002687cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2688{
2689 return cifs_sb->master_tlink;
2690}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002691
2692static int
2693compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2694{
2695 struct cifs_sb_info *old = CIFS_SB(sb);
2696 struct cifs_sb_info *new = mnt_data->cifs_sb;
2697
2698 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2699 return 0;
2700
2701 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2702 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2703 return 0;
2704
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002705 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002706 * We want to share sb only if we don't specify an r/wsize or
2707 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002708 */
2709 if (new->wsize && new->wsize < old->wsize)
2710 return 0;
2711
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002712 if (new->rsize && new->rsize < old->rsize)
2713 return 0;
2714
Eric W. Biederman1f682332013-02-06 01:20:20 -08002715 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002716 return 0;
2717
2718 if (old->mnt_file_mode != new->mnt_file_mode ||
2719 old->mnt_dir_mode != new->mnt_dir_mode)
2720 return 0;
2721
2722 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2723 return 0;
2724
2725 if (old->actimeo != new->actimeo)
2726 return 0;
2727
2728 return 1;
2729}
2730
2731int
2732cifs_match_super(struct super_block *sb, void *data)
2733{
2734 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2735 struct smb_vol *volume_info;
2736 struct cifs_sb_info *cifs_sb;
2737 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002738 struct cifs_ses *ses;
2739 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002740 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002741 int rc = 0;
2742
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002743 spin_lock(&cifs_tcp_ses_lock);
2744 cifs_sb = CIFS_SB(sb);
2745 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2746 if (IS_ERR(tlink)) {
2747 spin_unlock(&cifs_tcp_ses_lock);
2748 return rc;
2749 }
2750 tcon = tlink_tcon(tlink);
2751 ses = tcon->ses;
2752 tcp_srv = ses->server;
2753
2754 volume_info = mnt_data->vol;
2755
Jeff Layton9fa114f2012-11-26 11:09:57 -05002756 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002757 !match_session(ses, volume_info) ||
2758 !match_tcon(tcon, volume_info->UNC)) {
2759 rc = 0;
2760 goto out;
2761 }
2762
2763 rc = compare_mount_options(sb, mnt_data);
2764out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002765 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002766 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002767 return rc;
2768}
2769
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002771get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002772 const struct nls_table *nls_codepage, unsigned int *num_referrals,
2773 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774{
2775 char *temp_unc;
2776 int rc = 0;
2777
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002778 if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002779 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002781 *num_referrals = 0;
2782 *referrals = NULL;
2783
2784 if (ses->ipc_tid == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 temp_unc = kmalloc(2 /* for slashes */ +
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002786 strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
2787 + 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 if (temp_unc == NULL)
2789 return -ENOMEM;
2790 temp_unc[0] = '\\';
2791 temp_unc[1] = '\\';
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002792 strcpy(temp_unc + 2, ses->serverName);
2793 strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
2794 rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
2795 nls_codepage);
Joe Perchesf96637b2013-05-04 22:12:25 -05002796 cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 kfree(temp_unc);
2798 }
2799 if (rc == 0)
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002800 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
2801 referrals, num_referrals,
2802 nls_codepage, remap);
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002803 /*
2804 * BB - map targetUNCs to dfs_info3 structures, here or in
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002805 * ses->server->ops->get_dfs_refer.
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002806 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
2808 return rc;
2809}
2810
Jeff Layton09e50d52008-07-23 10:11:19 -04002811#ifdef CONFIG_DEBUG_LOCK_ALLOC
2812static struct lock_class_key cifs_key[2];
2813static struct lock_class_key cifs_slock_key[2];
2814
2815static inline void
2816cifs_reclassify_socket4(struct socket *sock)
2817{
2818 struct sock *sk = sock->sk;
2819 BUG_ON(sock_owned_by_user(sk));
2820 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2821 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2822}
2823
2824static inline void
2825cifs_reclassify_socket6(struct socket *sock)
2826{
2827 struct sock *sk = sock->sk;
2828 BUG_ON(sock_owned_by_user(sk));
2829 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2830 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2831}
2832#else
2833static inline void
2834cifs_reclassify_socket4(struct socket *sock)
2835{
2836}
2837
2838static inline void
2839cifs_reclassify_socket6(struct socket *sock)
2840{
2841}
2842#endif
2843
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002845static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846{
Steve French50c2f752007-07-13 00:33:32 +00002847 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848
Steve French50c2f752007-07-13 00:33:32 +00002849 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 /* mask a nibble at a time and encode */
2851 target[j] = 'A' + (0x0F & (source[i] >> 4));
2852 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002853 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 }
2855
2856}
2857
Ben Greear3eb9a882010-09-01 17:06:02 -07002858static int
2859bind_socket(struct TCP_Server_Info *server)
2860{
2861 int rc = 0;
2862 if (server->srcaddr.ss_family != AF_UNSPEC) {
2863 /* Bind to the specified local IP address */
2864 struct socket *socket = server->ssocket;
2865 rc = socket->ops->bind(socket,
2866 (struct sockaddr *) &server->srcaddr,
2867 sizeof(server->srcaddr));
2868 if (rc < 0) {
2869 struct sockaddr_in *saddr4;
2870 struct sockaddr_in6 *saddr6;
2871 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2872 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2873 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05002874 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
2875 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002876 else
Joe Perchesf96637b2013-05-04 22:12:25 -05002877 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
2878 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002879 }
2880 }
2881 return rc;
2882}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
2884static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002885ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886{
2887 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002888 /*
2889 * some servers require RFC1001 sessinit before sending
2890 * negprot - BB check reconnection in case where second
2891 * sessinit is sent but no second negprot
2892 */
2893 struct rfc1002_session_packet *ses_init_buf;
2894 struct smb_hdr *smb_buf;
2895 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2896 GFP_KERNEL);
2897 if (ses_init_buf) {
2898 ses_init_buf->trailer.session_req.called_len = 32;
2899
2900 if (server->server_RFC1001_name &&
2901 server->server_RFC1001_name[0] != 0)
2902 rfc1002mangle(ses_init_buf->trailer.
2903 session_req.called_name,
2904 server->server_RFC1001_name,
2905 RFC1001_NAME_LEN_WITH_NULL);
2906 else
2907 rfc1002mangle(ses_init_buf->trailer.
2908 session_req.called_name,
2909 DEFAULT_CIFS_CALLED_NAME,
2910 RFC1001_NAME_LEN_WITH_NULL);
2911
2912 ses_init_buf->trailer.session_req.calling_len = 32;
2913
2914 /*
2915 * calling name ends in null (byte 16) from old smb
2916 * convention.
2917 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05002918 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002919 rfc1002mangle(ses_init_buf->trailer.
2920 session_req.calling_name,
2921 server->workstation_RFC1001_name,
2922 RFC1001_NAME_LEN_WITH_NULL);
2923 else
2924 rfc1002mangle(ses_init_buf->trailer.
2925 session_req.calling_name,
2926 "LINUX_CIFS_CLNT",
2927 RFC1001_NAME_LEN_WITH_NULL);
2928
2929 ses_init_buf->trailer.session_req.scope1 = 0;
2930 ses_init_buf->trailer.session_req.scope2 = 0;
2931 smb_buf = (struct smb_hdr *)ses_init_buf;
2932
2933 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00002934 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002935 rc = smb_send(server, smb_buf, 0x44);
2936 kfree(ses_init_buf);
2937 /*
2938 * RFC1001 layer in at least one server
2939 * requires very short break before negprot
2940 * presumably because not expecting negprot
2941 * to follow so fast. This is a simple
2942 * solution that works without
2943 * complicating the code and causes no
2944 * significant slowing down on mount
2945 * for everyone else
2946 */
2947 usleep_range(1000, 2000);
2948 }
2949 /*
2950 * else the negprot may still work without this
2951 * even though malloc failed
2952 */
2953
2954 return rc;
2955}
2956
2957static int
2958generic_ip_connect(struct TCP_Server_Info *server)
2959{
2960 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00002961 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002962 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002963 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002964 struct sockaddr *saddr;
2965
2966 saddr = (struct sockaddr *) &server->dstaddr;
2967
2968 if (server->dstaddr.ss_family == AF_INET6) {
2969 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
2970 slen = sizeof(struct sockaddr_in6);
2971 sfamily = AF_INET6;
2972 } else {
2973 sport = ((struct sockaddr_in *) saddr)->sin_port;
2974 slen = sizeof(struct sockaddr_in);
2975 sfamily = AF_INET;
2976 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002978 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06002979 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
2980 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002982 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002983 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002986
2987 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05002988 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002989 server->ssocket = socket;
2990 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002991 if (sfamily == AF_INET6)
2992 cifs_reclassify_socket6(socket);
2993 else
2994 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 }
2996
Ben Greear3eb9a882010-09-01 17:06:02 -07002997 rc = bind_socket(server);
2998 if (rc < 0)
2999 return rc;
3000
Jeff Laytond5c56052008-12-01 18:42:33 -05003001 /*
3002 * Eventually check for other socket options to change from
3003 * the default. sock_setsockopt not used because it expects
3004 * user space buffer
3005 */
3006 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003007 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003008
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003009 /* make the bufsizes depend on wsize/rsize and max requests */
3010 if (server->noautotune) {
3011 if (socket->sk->sk_sndbuf < (200 * 1024))
3012 socket->sk->sk_sndbuf = 200 * 1024;
3013 if (socket->sk->sk_rcvbuf < (140 * 1024))
3014 socket->sk->sk_rcvbuf = 140 * 1024;
3015 }
3016
Steve French6a5fa2362010-01-01 01:28:43 +00003017 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003018 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003019 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3020 (char *)&val, sizeof(val));
3021 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003022 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3023 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003024 }
3025
Joe Perchesf96637b2013-05-04 22:12:25 -05003026 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003027 socket->sk->sk_sndbuf,
3028 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3029
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003030 rc = socket->ops->connect(socket, saddr, slen, 0);
3031 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003032 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003033 sock_release(socket);
3034 server->ssocket = NULL;
3035 return rc;
3036 }
3037
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003038 if (sport == htons(RFC1001_PORT))
3039 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003040
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 return rc;
3042}
3043
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003044static int
3045ip_connect(struct TCP_Server_Info *server)
3046{
Steve French6da97912011-03-13 18:55:55 +00003047 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003048 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3049 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3050
3051 if (server->dstaddr.ss_family == AF_INET6)
3052 sport = &addr6->sin6_port;
3053 else
3054 sport = &addr->sin_port;
3055
3056 if (*sport == 0) {
3057 int rc;
3058
3059 /* try with 445 port at first */
3060 *sport = htons(CIFS_PORT);
3061
3062 rc = generic_ip_connect(server);
3063 if (rc >= 0)
3064 return rc;
3065
3066 /* if it failed, try with 139 port */
3067 *sport = htons(RFC1001_PORT);
3068 }
3069
3070 return generic_ip_connect(server);
3071}
3072
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003073void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003074 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003075{
3076 /* if we are reconnecting then should we check to see if
3077 * any requested capabilities changed locally e.g. via
3078 * remount but we can not do much about it here
3079 * if they have (even if we could detect it by the following)
3080 * Perhaps we could add a backpointer to array of sb from tcon
3081 * or if we change to make all sb to same share the same
3082 * sb as NFS - then we only have one backpointer to sb.
3083 * What if we wanted to mount the server share twice once with
3084 * and once without posixacls or posix paths? */
3085 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003086
Steve Frenchc18c8422007-07-18 23:21:09 +00003087 if (vol_info && vol_info->no_linux_ext) {
3088 tcon->fsUnixInfo.Capability = 0;
3089 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003090 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003091 return;
3092 } else if (vol_info)
3093 tcon->unix_ext = 1; /* Unix Extensions supported */
3094
3095 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003096 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003097 return;
3098 }
Steve French50c2f752007-07-13 00:33:32 +00003099
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003100 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003101 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003102 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003103 /* check for reconnect case in which we do not
3104 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003105 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003106 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003107 originally at mount time */
3108 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3109 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003110 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3111 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003112 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003113 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003114 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003115 cifs_dbg(VFS, "possible reconnect error\n");
3116 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003117 }
Steve French8af18972007-02-14 04:42:51 +00003118 }
Steve French50c2f752007-07-13 00:33:32 +00003119
Steve French6848b732011-05-26 18:38:54 +00003120 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003121 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003122
Steve French8af18972007-02-14 04:42:51 +00003123 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003124 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003125 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003126 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003127 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003128 if (cifs_sb)
3129 cifs_sb->mnt_cifs_flags |=
3130 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003131 }
3132
Steve French75865f8c2007-06-24 18:30:48 +00003133 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003134 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003135 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003136 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003137 if (cifs_sb)
3138 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003139 CIFS_MOUNT_POSIX_PATHS;
3140 }
Steve French50c2f752007-07-13 00:33:32 +00003141
Joe Perchesf96637b2013-05-04 22:12:25 -05003142 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003143#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003144 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003145 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003146 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003147 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003148 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003149 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003150 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003151 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003152 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003153 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003154 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003155 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003156 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003157 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003158 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003159 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003160 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003161 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003162#endif /* CIFS_DEBUG2 */
3163 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003164 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003165 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003166 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003167 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 +00003168
Steve French8af18972007-02-14 04:42:51 +00003169 }
3170 }
3171}
3172
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003173void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3174 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003175{
Jeff Layton2de970f2010-10-06 19:51:12 -04003176 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3177
Al Viro2ced6f62011-06-17 09:20:04 -04003178 spin_lock_init(&cifs_sb->tlink_tree_lock);
3179 cifs_sb->tlink_tree = RB_ROOT;
3180
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003181 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003182 * Temporarily set r/wsize for matching superblock. If we end up using
3183 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003184 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003185 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003186 cifs_sb->wsize = pvolume_info->wsize;
3187
Steve French3b795212008-11-13 19:45:32 +00003188 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3189 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3190 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3191 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003192 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3193 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003194
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303195 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003196 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303197
Steve French3b795212008-11-13 19:45:32 +00003198 if (pvolume_info->noperm)
3199 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3200 if (pvolume_info->setuids)
3201 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3202 if (pvolume_info->server_ino)
3203 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3204 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05003205 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3206 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00003207 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3208 if (pvolume_info->no_xattr)
3209 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3210 if (pvolume_info->sfu_emul)
3211 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3212 if (pvolume_info->nobrl)
3213 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003214 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003215 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003216 if (pvolume_info->mand_lock)
3217 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003218 if (pvolume_info->rwpidforward)
3219 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003220 if (pvolume_info->cifs_acl)
3221 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003222 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003223 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003224 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3225 }
3226 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003227 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003228 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3229 }
Steve French3b795212008-11-13 19:45:32 +00003230 if (pvolume_info->override_uid)
3231 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3232 if (pvolume_info->override_gid)
3233 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3234 if (pvolume_info->dynperm)
3235 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303236 if (pvolume_info->fsc)
3237 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003238 if (pvolume_info->multiuser)
3239 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3240 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003241 if (pvolume_info->strict_io)
3242 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003243 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003244 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003245 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3246 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003247 if (pvolume_info->mfsymlinks) {
3248 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05003249 /*
3250 * Our SFU ("Services for Unix" emulation does not allow
3251 * creating symlinks but does allow reading existing SFU
3252 * symlinks (it does allow both creating and reading SFU
3253 * style mknod and FIFOs though). When "mfsymlinks" and
3254 * "sfu" are both enabled at the same time, it allows
3255 * reading both types of symlinks, but will only create
3256 * them with mfsymlinks format. This allows better
3257 * Apple compatibility (probably better for Samba too)
3258 * while still recognizing old Windows style symlinks.
3259 */
3260 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003261 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05003262 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003263 }
Steve French3b795212008-11-13 19:45:32 +00003264
3265 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003266 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003267}
3268
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003269static void
3270cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003271{
Sean Finneyb9468452011-04-11 13:19:32 +00003272 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003273 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003274 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003275 kfree(volume_info->domainname);
3276 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003277 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003278}
3279
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003280void
3281cifs_cleanup_volume_info(struct smb_vol *volume_info)
3282{
3283 if (!volume_info)
3284 return;
3285 cleanup_volume_info_contents(volume_info);
3286 kfree(volume_info);
3287}
3288
3289
Steve French2d6d5892009-04-09 00:36:44 +00003290#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003291/*
3292 * cifs_build_path_to_root returns full path to root when we do not have an
3293 * exiting connection (tcon)
3294 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003295static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003296build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003297 const struct cifs_sb_info *cifs_sb)
3298{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003299 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003300 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003301 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003302
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003303 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003304 if (full_path == NULL)
3305 return ERR_PTR(-ENOMEM);
3306
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003307 strncpy(full_path, vol->UNC, unc_len);
3308 pos = full_path + unc_len;
3309
3310 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04003311 *pos = CIFS_DIR_SEP(cifs_sb);
3312 strncpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003313 pos += pplen;
3314 }
3315
3316 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003317 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003318 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003319 return full_path;
3320}
Sean Finneydd613942011-04-11 13:19:30 +00003321
3322/*
3323 * Perform a dfs referral query for a share and (optionally) prefix
3324 *
Sean Finney046462a2011-04-11 13:19:33 +00003325 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3326 * to a string containing updated options for the submount. Otherwise it
3327 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003328 *
3329 * Returns the rc from get_dfs_path to the caller, which can be used to
3330 * determine whether there were referrals.
3331 */
3332static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003333expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003334 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003335 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003336{
3337 int rc;
3338 unsigned int num_referrals = 0;
3339 struct dfs_info3_param *referrals = NULL;
3340 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3341
3342 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3343 if (IS_ERR(full_path))
3344 return PTR_ERR(full_path);
3345
3346 /* For DFS paths, skip the first '\' of the UNC */
3347 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3348
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003349 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Steve French2baa2682014-09-27 02:19:01 -05003350 &num_referrals, &referrals, cifs_remap(cifs_sb));
Sean Finneydd613942011-04-11 13:19:30 +00003351
3352 if (!rc && num_referrals > 0) {
3353 char *fake_devname = NULL;
3354
3355 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3356 full_path + 1, referrals,
3357 &fake_devname);
3358
3359 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003360
Sean Finneydd613942011-04-11 13:19:30 +00003361 if (IS_ERR(mdata)) {
3362 rc = PTR_ERR(mdata);
3363 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003364 } else {
3365 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003366 rc = cifs_setup_volume_info(volume_info, mdata,
3367 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003368 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003369 kfree(fake_devname);
3370 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003371 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003372 }
3373 kfree(full_path);
3374 return rc;
3375}
Steve French2d6d5892009-04-09 00:36:44 +00003376#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003377
Jeff Layton04db79b2011-07-06 08:10:38 -04003378static int
3379cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3380 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003382 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003383
Jeff Layton04db79b2011-07-06 08:10:38 -04003384 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3385 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386
Jeff Layton7586b762008-12-01 18:41:49 -05003387 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003388 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003389 kfree(volume_info->username);
3390 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003391 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003393 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003395 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003396 /* In userspace mount helper we can get user name from alternate
3397 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003398 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 }
3400
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003402 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003403 /* load_nls_default cannot return null */
3404 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003406 volume_info->local_nls = load_nls(volume_info->iocharset);
3407 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003408 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003409 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003410 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 }
3412 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003413
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003414 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003415}
3416
3417struct smb_vol *
3418cifs_get_volume_info(char *mount_data, const char *devname)
3419{
3420 int rc;
3421 struct smb_vol *volume_info;
3422
Jeff Layton6ee95422012-11-26 11:09:57 -05003423 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003424 if (!volume_info)
3425 return ERR_PTR(-ENOMEM);
3426
3427 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3428 if (rc) {
3429 cifs_cleanup_volume_info(volume_info);
3430 volume_info = ERR_PTR(rc);
3431 }
3432
3433 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003434}
3435
3436int
Al Viro2c6292a2011-06-17 09:05:48 -04003437cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003438{
Jeff Layton1daaae82012-03-21 06:30:40 -04003439 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003440 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003441 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003442 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003443 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003444 char *full_path;
3445 struct tcon_link *tlink;
3446#ifdef CONFIG_CIFS_DFS_UPCALL
3447 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003448#endif
Al Virodd854462011-06-17 08:24:42 -04003449
Christoph Hellwigb4caecd2015-01-14 10:42:32 +01003450 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs");
Al Virodd854462011-06-17 08:24:42 -04003451 if (rc)
3452 return rc;
3453
Jeff Layton20547492011-07-09 12:21:07 -04003454#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003455try_mount_again:
3456 /* cleanup activities if we're chasing a referral */
3457 if (referral_walks_count) {
3458 if (tcon)
3459 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003460 else if (ses)
3461 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003462
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003463 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003464 }
3465#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003466 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003467 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003468 ses = NULL;
3469 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003470 full_path = NULL;
3471 tlink = NULL;
3472
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003473 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474
Jeff Layton63c038c2008-12-01 18:41:46 -05003475 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003476 server = cifs_get_tcp_session(volume_info);
3477 if (IS_ERR(server)) {
3478 rc = PTR_ERR(server);
Al Virodd854462011-06-17 08:24:42 -04003479 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003480 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 }
3482
Jeff Layton36988c72010-04-24 07:57:43 -04003483 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003484 ses = cifs_get_smb_ses(server, volume_info);
3485 if (IS_ERR(ses)) {
3486 rc = PTR_ERR(ses);
3487 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003488 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 }
Steve French50c2f752007-07-13 00:33:32 +00003490
Jeff Laytond00c28d2010-04-24 07:57:44 -04003491 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003492 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003493 if (IS_ERR(tcon)) {
3494 rc = PTR_ERR(tcon);
3495 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003496 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003497 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003498
Steve French6848b732011-05-26 18:38:54 +00003499 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003500 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003501 /* reset of caps checks mount to see if unix extensions
3502 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003503 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003504 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3505 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3506 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3507 rc = -EACCES;
3508 goto mount_fail_check;
3509 }
3510 } else
3511 tcon->unix_ext = 0; /* server does not support them */
3512
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003513 /* do not care if a following call succeed - informational */
3514 if (!tcon->ipc && server->ops->qfs_tcon)
3515 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003516
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003517 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3518 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003519
Jeff Layton66bfaad2011-10-19 15:30:35 -04003520 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003521 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003522
Igor Mammedove4cce942009-02-10 14:10:26 +03003523remote_path_check:
3524#ifdef CONFIG_CIFS_DFS_UPCALL
3525 /*
3526 * Perform an unconditional check for whether there are DFS
3527 * referrals for this path without prefix, to provide support
3528 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003529 * with PATH_NOT_COVERED to requests that include the prefix.
3530 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003531 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003532 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003533 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3534 false);
Steve Frencheeac8042006-01-13 21:34:58 -08003535 if (!refrc) {
Steve French4523cc32007-04-30 20:13:06 +00003536 referral_walks_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 goto try_mount_again;
3538 }
3539 }
3540#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003541
Steve Frenchf87d39d2011-05-27 03:50:55 +00003542 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003544 if (!server->ops->is_path_accessible) {
3545 rc = -ENOSYS;
3546 goto mount_fail_check;
3547 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003548 /*
3549 * cifs_build_path_to_root works only when we have a valid tcon
3550 */
3551 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 if (full_path == NULL) {
3553 rc = -ENOMEM;
3554 goto mount_fail_check;
3555 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003556 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3557 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 if (rc != 0 && rc != -EREMOTE) {
3559 kfree(full_path);
3560 goto mount_fail_check;
3561 }
3562 kfree(full_path);
3563 }
3564
3565 /* get referral if needed */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003566 if (rc == -EREMOTE) {
3567#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003568 if (referral_walks_count > MAX_NESTED_LINKS) {
3569 /*
3570 * BB: when we implement proper loop detection,
3571 * we will remove this check. But now we need it
3572 * to prevent an indefinite loop if 'DFS tree' is
3573 * misconfigured (i.e. has loops).
3574 */
3575 rc = -ELOOP;
3576 goto mount_fail_check;
3577 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003578
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003579 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003580
Sean Finneydd613942011-04-11 13:19:30 +00003581 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003582 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003583 goto try_mount_again;
3584 }
Sean Finneydd613942011-04-11 13:19:30 +00003585 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003586#else /* No DFS support, return error on mount */
3587 rc = -EOPNOTSUPP;
3588#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003589 }
3590
Jeff Layton9d002df2010-10-06 19:51:11 -04003591 if (rc)
3592 goto mount_fail_check;
3593
3594 /* now, hang the tcon off of the superblock */
3595 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3596 if (tlink == NULL) {
3597 rc = -ENOMEM;
3598 goto mount_fail_check;
3599 }
3600
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003601 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003602 tlink->tl_tcon = tcon;
3603 tlink->tl_time = jiffies;
3604 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3605 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3606
Jeff Layton413e6612010-10-28 13:33:38 -04003607 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003608 spin_lock(&cifs_sb->tlink_tree_lock);
3609 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3610 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003611
Jeff Laytonda472fc2012-03-23 14:40:53 -04003612 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003613 TLINK_IDLE_EXPIRE);
3614
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003615mount_fail_check:
3616 /* on error free sesinfo and tcon struct if needed */
3617 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003618 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003619 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003620 if (tcon)
3621 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003622 else if (ses)
3623 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003624 else
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003625 cifs_put_tcp_session(server);
Al Virodd854462011-06-17 08:24:42 -04003626 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003627 }
3628
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003630 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 return rc;
3632}
3633
Jeff Layton8d1bca32011-06-11 21:17:10 -04003634/*
3635 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3636 * pointer may be NULL.
3637 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003639CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00003640 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 const struct nls_table *nls_codepage)
3642{
3643 struct smb_hdr *smb_buffer;
3644 struct smb_hdr *smb_buffer_response;
3645 TCONX_REQ *pSMB;
3646 TCONX_RSP *pSMBr;
3647 unsigned char *bcc_ptr;
3648 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003649 int length;
3650 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
3652 if (ses == NULL)
3653 return -EIO;
3654
3655 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003656 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003658
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 smb_buffer_response = smb_buffer;
3660
3661 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3662 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003663
Pavel Shilovsky88257362012-05-23 14:01:59 +04003664 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 smb_buffer->Uid = ses->Suid;
3666 pSMB = (TCONX_REQ *) smb_buffer;
3667 pSMBr = (TCONX_RSP *) smb_buffer_response;
3668
3669 pSMB->AndXCommand = 0xFF;
3670 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003672 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003673 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003674 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003675 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003676 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003677 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003678 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003679 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3680 specified as required (when that support is added to
3681 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003682 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003683 by Samba (not sure whether other servers allow
3684 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003685#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003686 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05003687 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003688 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003689 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003690 SECMODE_PW_ENCRYPT ? true : false,
3691 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003692 else
3693#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003694 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003695 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05003696 if (rc) {
3697 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
3698 __func__, rc);
3699 cifs_buf_release(smb_buffer);
3700 return rc;
3701 }
Steve Frencheeac8042006-01-13 21:34:58 -08003702
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003703 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003704 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003705 /* must align unicode strings */
3706 *bcc_ptr = 0; /* null byte password */
3707 bcc_ptr++;
3708 }
Steve Frencheeac8042006-01-13 21:34:58 -08003709 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
Jeff Layton38d77c52013-05-26 07:01:00 -04003711 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3713
3714 if (ses->capabilities & CAP_STATUS32) {
3715 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3716 }
3717 if (ses->capabilities & CAP_DFS) {
3718 smb_buffer->Flags2 |= SMBFLG2_DFS;
3719 }
3720 if (ses->capabilities & CAP_UNICODE) {
3721 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3722 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003723 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003724 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003725 (/* server len*/ + 256 /* share len */), nls_codepage);
3726 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 bcc_ptr += 2; /* skip trailing null */
3728 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729 strcpy(bcc_ptr, tree);
3730 bcc_ptr += strlen(tree) + 1;
3731 }
3732 strcpy(bcc_ptr, "?????");
3733 bcc_ptr += strlen("?????");
3734 bcc_ptr += 1;
3735 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003736 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3737 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 pSMB->ByteCount = cpu_to_le16(count);
3739
Steve French133672e2007-11-13 22:41:37 +00003740 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003741 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743 /* above now done in SendReceive */
3744 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003745 bool is_unicode;
3746
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003748 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 tcon->tid = smb_buffer_response->Tid;
3750 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003751 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003752 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003753 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
3754 is_unicode = true;
3755 else
3756 is_unicode = false;
3757
Jeff Laytoncc20c032009-04-30 07:16:21 -04003758
Steve French50c2f752007-07-13 00:33:32 +00003759 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00003760 if (length == 3) {
3761 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3762 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003763 cifs_dbg(FYI, "IPC connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003764 tcon->ipc = 1;
3765 }
3766 } else if (length == 2) {
3767 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3768 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05003769 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003770 }
3771 }
Steve French50c2f752007-07-13 00:33:32 +00003772 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04003773 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05003774 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04003775
3776 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04003777 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06003778 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00003779 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04003780 nls_codepage);
3781
Joe Perchesf96637b2013-05-04 22:12:25 -05003782 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003783
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003784 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00003785 (smb_buffer_response->WordCount == 7))
3786 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00003787 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3788 else
3789 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05003790 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003792 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 ses->ipc_tid = smb_buffer_response->Tid;
3794 }
3795
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00003796 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 return rc;
3798}
3799
Al Viro2e32cf52013-10-03 12:53:37 -04003800static void delayed_free(struct rcu_head *p)
3801{
3802 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
3803 unload_nls(sbi->local_nls);
3804 kfree(sbi);
3805}
3806
Al Viro2a9b9952011-06-17 09:27:16 -04003807void
3808cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809{
Jeff Laytonb647c352010-10-28 11:16:44 -04003810 struct rb_root *root = &cifs_sb->tlink_tree;
3811 struct rb_node *node;
3812 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
Jeff Layton2de970f2010-10-06 19:51:12 -04003814 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
3815
Jeff Laytonb647c352010-10-28 11:16:44 -04003816 spin_lock(&cifs_sb->tlink_tree_lock);
3817 while ((node = rb_first(root))) {
3818 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3819 cifs_get_tlink(tlink);
3820 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3821 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00003822
Jeff Laytonb647c352010-10-28 11:16:44 -04003823 spin_unlock(&cifs_sb->tlink_tree_lock);
3824 cifs_put_tlink(tlink);
3825 spin_lock(&cifs_sb->tlink_tree_lock);
3826 }
3827 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003828
Al Virodd854462011-06-17 08:24:42 -04003829 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04003830 kfree(cifs_sb->mountdata);
Al Viro2e32cf52013-10-03 12:53:37 -04003831 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00003832}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003834int
3835cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836{
3837 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04003838 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003840 if (!server->ops->need_neg || !server->ops->negotiate)
3841 return -ENOSYS;
3842
Jeff Layton198b5682010-04-24 07:57:48 -04003843 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003844 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04003845 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
Pavel Shilovsky45275782012-05-17 17:53:29 +04003847 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003848
3849 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04003850 if (rc == 0) {
3851 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04003852 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04003853 server->tcpStatus = CifsGood;
3854 else
3855 rc = -EHOSTDOWN;
3856 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 }
Steve French26b994f2008-08-06 05:11:33 +00003858
Jeff Layton198b5682010-04-24 07:57:48 -04003859 return rc;
3860}
Steve French26b994f2008-08-06 05:11:33 +00003861
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003862int
3863cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
3864 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04003865{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003866 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04003867 struct TCP_Server_Info *server = ses->server;
3868
Jeff Layton198b5682010-04-24 07:57:48 -04003869 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00003870 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003871 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00003872
Joe Perchesf96637b2013-05-04 22:12:25 -05003873 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00003874 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04003875
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003876 if (server->ops->sess_setup)
3877 rc = server->ops->sess_setup(xid, ses, nls_info);
3878
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05003879 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003880 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003881
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 return rc;
3883}
3884
Jeff Layton8a8798a2012-01-17 16:09:15 -05003885static int
3886cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
3887{
Jeff Layton3f618222013-06-12 19:52:14 -05003888 vol->sectype = ses->sectype;
3889
3890 /* krb5 is special, since we don't need username or pw */
3891 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003892 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003893
3894 return cifs_set_cifscreds(vol, ses);
3895}
3896
Steve French96daf2b2011-05-27 04:34:02 +00003897static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003898cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04003899{
Jeff Layton8a8798a2012-01-17 16:09:15 -05003900 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00003901 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
3902 struct cifs_ses *ses;
3903 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04003904 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04003905
3906 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03003907 if (vol_info == NULL)
3908 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04003909
Jeff Layton9d002df2010-10-06 19:51:11 -04003910 vol_info->local_nls = cifs_sb->local_nls;
3911 vol_info->linux_uid = fsuid;
3912 vol_info->cred_uid = fsuid;
3913 vol_info->UNC = master_tcon->treeName;
3914 vol_info->retry = master_tcon->retry;
3915 vol_info->nocase = master_tcon->nocase;
3916 vol_info->local_lease = master_tcon->local_lease;
3917 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04003918 vol_info->sectype = master_tcon->ses->sectype;
3919 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04003920
Jeff Layton8a8798a2012-01-17 16:09:15 -05003921 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
3922 if (rc) {
3923 tcon = ERR_PTR(rc);
3924 goto out;
3925 }
Jeff Layton9d002df2010-10-06 19:51:11 -04003926
3927 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303928 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003929 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303930 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003931
3932 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
3933 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00003934 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04003935 cifs_put_tcp_session(master_tcon->ses->server);
3936 goto out;
3937 }
3938
3939 tcon = cifs_get_tcon(ses, vol_info);
3940 if (IS_ERR(tcon)) {
3941 cifs_put_smb_ses(ses);
3942 goto out;
3943 }
3944
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003945 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04003946 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
3947out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05003948 kfree(vol_info->username);
3949 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04003950 kfree(vol_info);
3951
3952 return tcon;
3953}
3954
Steve French96daf2b2011-05-27 04:34:02 +00003955struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04003956cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
3957{
3958 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
3959}
3960
Jeff Laytonb647c352010-10-28 11:16:44 -04003961/* find and return a tlink with given uid */
3962static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003963tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04003964{
3965 struct rb_node *node = root->rb_node;
3966 struct tcon_link *tlink;
3967
3968 while (node) {
3969 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3970
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003971 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003972 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003973 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003974 node = node->rb_right;
3975 else
3976 return tlink;
3977 }
3978 return NULL;
3979}
3980
3981/* insert a tcon_link into the tree */
3982static void
3983tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
3984{
3985 struct rb_node **new = &(root->rb_node), *parent = NULL;
3986 struct tcon_link *tlink;
3987
3988 while (*new) {
3989 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
3990 parent = *new;
3991
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003992 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003993 new = &((*new)->rb_left);
3994 else
3995 new = &((*new)->rb_right);
3996 }
3997
3998 rb_link_node(&new_tlink->tl_rbnode, parent, new);
3999 rb_insert_color(&new_tlink->tl_rbnode, root);
4000}
4001
Jeff Layton9d002df2010-10-06 19:51:11 -04004002/*
4003 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4004 * current task.
4005 *
4006 * If the superblock doesn't refer to a multiuser mount, then just return
4007 * the master tcon for the mount.
4008 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304009 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004010 * exists, then check to see if it's pending construction. If it is then wait
4011 * for construction to complete. Once it's no longer pending, check to see if
4012 * it failed and either return an error or retry construction, depending on
4013 * the timeout.
4014 *
4015 * If one doesn't exist then insert a new tcon_link struct into the tree and
4016 * try to construct a new one.
4017 */
4018struct tcon_link *
4019cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4020{
4021 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004022 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004023 struct tcon_link *tlink, *newtlink;
4024
4025 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4026 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4027
4028 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004029 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004030 if (tlink)
4031 cifs_get_tlink(tlink);
4032 spin_unlock(&cifs_sb->tlink_tree_lock);
4033
4034 if (tlink == NULL) {
4035 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4036 if (newtlink == NULL)
4037 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004038 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004039 newtlink->tl_tcon = ERR_PTR(-EACCES);
4040 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4041 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4042 cifs_get_tlink(newtlink);
4043
Jeff Layton9d002df2010-10-06 19:51:11 -04004044 spin_lock(&cifs_sb->tlink_tree_lock);
4045 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004046 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004047 if (tlink) {
4048 cifs_get_tlink(tlink);
4049 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004050 kfree(newtlink);
4051 goto wait_for_construction;
4052 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004053 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004054 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4055 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004056 } else {
4057wait_for_construction:
4058 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04004059 TASK_INTERRUPTIBLE);
4060 if (ret) {
4061 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10004062 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04004063 }
4064
4065 /* if it's good, return it */
4066 if (!IS_ERR(tlink->tl_tcon))
4067 return tlink;
4068
4069 /* return error if we tried this already recently */
4070 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4071 cifs_put_tlink(tlink);
4072 return ERR_PTR(-EACCES);
4073 }
4074
4075 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4076 goto wait_for_construction;
4077 }
4078
4079 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4080 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4081 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4082
4083 if (IS_ERR(tlink->tl_tcon)) {
4084 cifs_put_tlink(tlink);
4085 return ERR_PTR(-EACCES);
4086 }
4087
4088 return tlink;
4089}
Jeff Layton2de970f2010-10-06 19:51:12 -04004090
4091/*
4092 * periodic workqueue job that scans tcon_tree for a superblock and closes
4093 * out tcons.
4094 */
4095static void
4096cifs_prune_tlinks(struct work_struct *work)
4097{
4098 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4099 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004100 struct rb_root *root = &cifs_sb->tlink_tree;
4101 struct rb_node *node = rb_first(root);
4102 struct rb_node *tmp;
4103 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004104
Jeff Laytonb647c352010-10-28 11:16:44 -04004105 /*
4106 * Because we drop the spinlock in the loop in order to put the tlink
4107 * it's not guarded against removal of links from the tree. The only
4108 * places that remove entries from the tree are this function and
4109 * umounts. Because this function is non-reentrant and is canceled
4110 * before umount can proceed, this is safe.
4111 */
4112 spin_lock(&cifs_sb->tlink_tree_lock);
4113 node = rb_first(root);
4114 while (node != NULL) {
4115 tmp = node;
4116 node = rb_next(tmp);
4117 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4118
4119 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4120 atomic_read(&tlink->tl_count) != 0 ||
4121 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4122 continue;
4123
4124 cifs_get_tlink(tlink);
4125 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4126 rb_erase(tmp, root);
4127
Jeff Layton2de970f2010-10-06 19:51:12 -04004128 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004129 cifs_put_tlink(tlink);
4130 spin_lock(&cifs_sb->tlink_tree_lock);
4131 }
4132 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004133
Jeff Laytonda472fc2012-03-23 14:40:53 -04004134 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004135 TLINK_IDLE_EXPIRE);
4136}