blob: 5b97e56ddbca8fd8b4a4552c95acd97d5ca6c318 [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,
73 Opt_mapchars, Opt_nomapchars, Opt_sfu,
74 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
75 Opt_noposixpaths, Opt_nounix,
76 Opt_nocase,
77 Opt_brl, Opt_nobrl,
78 Opt_forcemandatorylock, Opt_setuids,
79 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
80 Opt_nohard, Opt_nosoft,
81 Opt_nointr, Opt_intr,
82 Opt_nostrictsync, Opt_strictsync,
83 Opt_serverino, Opt_noserverino,
84 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
85 Opt_acl, Opt_noacl, Opt_locallease,
Jeff Layton1b359202012-09-19 15:20:27 -070086 Opt_sign, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040087 Opt_fsc, Opt_mfsymlinks,
Jeff Laytond8162552012-03-23 14:40:56 -040088 Opt_multiuser, Opt_sloppy,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040089
90 /* Mount options which take numeric value */
91 Opt_backupuid, Opt_backupgid, Opt_uid,
92 Opt_cruid, Opt_gid, Opt_file_mode,
93 Opt_dirmode, Opt_port,
94 Opt_rsize, Opt_wsize, Opt_actimeo,
95
96 /* Mount options which take string value */
97 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -040098 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040099 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400100 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400101
102 /* Mount options to be ignored */
103 Opt_ignore,
104
105 /* Options which could be blank */
106 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100107 Opt_blank_user,
108 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400109
110 Opt_err
111};
112
113static const match_table_t cifs_mount_option_tokens = {
114
115 { Opt_user_xattr, "user_xattr" },
116 { Opt_nouser_xattr, "nouser_xattr" },
117 { Opt_forceuid, "forceuid" },
118 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400119 { Opt_forcegid, "forcegid" },
120 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400121 { Opt_noblocksend, "noblocksend" },
122 { Opt_noautotune, "noautotune" },
123 { Opt_hard, "hard" },
124 { Opt_soft, "soft" },
125 { Opt_perm, "perm" },
126 { Opt_noperm, "noperm" },
127 { Opt_mapchars, "mapchars" },
128 { Opt_nomapchars, "nomapchars" },
129 { Opt_sfu, "sfu" },
130 { Opt_nosfu, "nosfu" },
131 { Opt_nodfs, "nodfs" },
132 { Opt_posixpaths, "posixpaths" },
133 { Opt_noposixpaths, "noposixpaths" },
134 { Opt_nounix, "nounix" },
135 { Opt_nounix, "nolinux" },
136 { Opt_nocase, "nocase" },
137 { Opt_nocase, "ignorecase" },
138 { Opt_brl, "brl" },
139 { Opt_nobrl, "nobrl" },
140 { Opt_nobrl, "nolock" },
141 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400142 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400143 { Opt_setuids, "setuids" },
144 { Opt_nosetuids, "nosetuids" },
145 { Opt_dynperm, "dynperm" },
146 { Opt_nodynperm, "nodynperm" },
147 { Opt_nohard, "nohard" },
148 { Opt_nosoft, "nosoft" },
149 { Opt_nointr, "nointr" },
150 { Opt_intr, "intr" },
151 { Opt_nostrictsync, "nostrictsync" },
152 { Opt_strictsync, "strictsync" },
153 { Opt_serverino, "serverino" },
154 { Opt_noserverino, "noserverino" },
155 { Opt_rwpidforward, "rwpidforward" },
156 { Opt_cifsacl, "cifsacl" },
157 { Opt_nocifsacl, "nocifsacl" },
158 { Opt_acl, "acl" },
159 { Opt_noacl, "noacl" },
160 { Opt_locallease, "locallease" },
161 { Opt_sign, "sign" },
162 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400163 { Opt_noac, "noac" },
164 { Opt_fsc, "fsc" },
165 { Opt_mfsymlinks, "mfsymlinks" },
166 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400167 { Opt_sloppy, "sloppy" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400168
169 { Opt_backupuid, "backupuid=%s" },
170 { Opt_backupgid, "backupgid=%s" },
171 { Opt_uid, "uid=%s" },
172 { Opt_cruid, "cruid=%s" },
173 { Opt_gid, "gid=%s" },
174 { Opt_file_mode, "file_mode=%s" },
175 { Opt_dirmode, "dirmode=%s" },
176 { Opt_dirmode, "dir_mode=%s" },
177 { Opt_port, "port=%s" },
178 { Opt_rsize, "rsize=%s" },
179 { Opt_wsize, "wsize=%s" },
180 { Opt_actimeo, "actimeo=%s" },
181
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100182 { Opt_blank_user, "user=" },
183 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400184 { Opt_user, "user=%s" },
185 { Opt_user, "username=%s" },
186 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100187 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400188 { Opt_pass, "pass=%s" },
189 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100190 { Opt_blank_ip, "ip=" },
191 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400192 { Opt_ip, "ip=%s" },
193 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400194 { Opt_ignore, "unc=%s" },
195 { Opt_ignore, "target=%s" },
196 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400197 { Opt_domain, "dom=%s" },
198 { Opt_domain, "domain=%s" },
199 { Opt_domain, "workgroup=%s" },
200 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400201 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400202 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400203 { Opt_netbiosname, "netbiosname=%s" },
204 { Opt_servern, "servern=%s" },
205 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400206 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400207 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400208 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400209
210 { Opt_ignore, "cred" },
211 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400212 { Opt_ignore, "cred=%s" },
213 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400214 { Opt_ignore, "guest" },
215 { Opt_ignore, "rw" },
216 { Opt_ignore, "ro" },
217 { Opt_ignore, "suid" },
218 { Opt_ignore, "nosuid" },
219 { Opt_ignore, "exec" },
220 { Opt_ignore, "noexec" },
221 { Opt_ignore, "nodev" },
222 { Opt_ignore, "noauto" },
223 { Opt_ignore, "dev" },
224 { Opt_ignore, "mand" },
225 { Opt_ignore, "nomand" },
226 { Opt_ignore, "_netdev" },
227
228 { Opt_err, NULL }
229};
230
231enum {
232 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
233 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400234 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
235 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400236 Opt_sec_none,
237
238 Opt_sec_err
239};
240
241static const match_table_t cifs_secflavor_tokens = {
242 { Opt_sec_krb5, "krb5" },
243 { Opt_sec_krb5i, "krb5i" },
244 { Opt_sec_krb5p, "krb5p" },
245 { Opt_sec_ntlmsspi, "ntlmsspi" },
246 { Opt_sec_ntlmssp, "ntlmssp" },
247 { Opt_ntlm, "ntlm" },
248 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400249 { Opt_sec_ntlmv2, "nontlm" },
250 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400251 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400252 { Opt_sec_lanman, "lanman" },
253 { Opt_sec_none, "none" },
254
255 { Opt_sec_err, NULL }
256};
257
Jeff Layton15b6a472012-05-16 07:50:15 -0400258/* cache flavors */
259enum {
260 Opt_cache_loose,
261 Opt_cache_strict,
262 Opt_cache_none,
263 Opt_cache_err
264};
265
266static const match_table_t cifs_cacheflavor_tokens = {
267 { Opt_cache_loose, "loose" },
268 { Opt_cache_strict, "strict" },
269 { Opt_cache_none, "none" },
270 { Opt_cache_err, NULL }
271};
272
Jeff Layton23db65f2012-05-15 12:20:51 -0400273static const match_table_t cifs_smb_version_tokens = {
274 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600275 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000276 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500277 { Smb_30, SMB30_VERSION_STRING },
Jeff Layton23db65f2012-05-15 12:20:51 -0400278};
279
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300280static int ip_connect(struct TCP_Server_Info *server);
281static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400282static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400283static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400284static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
285 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Jeff Laytond5c56052008-12-01 18:42:33 -0500287/*
288 * cifs tcp session reconnection
289 *
290 * mark tcp session as reconnecting so temporarily locked
291 * mark all smb sessions as reconnecting for tcp session
292 * reconnect tcp session
293 * wake up waiters on reconnection? - (not needed currently)
294 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400295int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296cifs_reconnect(struct TCP_Server_Info *server)
297{
298 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500299 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000300 struct cifs_ses *ses;
301 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000302 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400303 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000304
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000306 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000307 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 next time through the loop */
309 spin_unlock(&GlobalMid_Lock);
310 return rc;
311 } else
312 server->tcpStatus = CifsNeedReconnect;
313 spin_unlock(&GlobalMid_Lock);
314 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400315#ifdef CONFIG_CIFS_SMB2
316 server->max_read = 0;
317#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Joe Perchesf96637b2013-05-04 22:12:25 -0500319 cifs_dbg(FYI, "Reconnecting tcp session\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
321 /* before reconnecting the tcp session, mark the smb session (uid)
322 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500323 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
324 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530325 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500326 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000327 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500328 ses->need_reconnect = true;
329 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500330 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000331 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500332 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530335 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500338 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500339 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000340 if (server->ssocket) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500341 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
342 server->ssocket->state, server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800343 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesf96637b2013-05-04 22:12:25 -0500344 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
345 server->ssocket->state, server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 sock_release(server->ssocket);
347 server->ssocket = NULL;
348 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500349 server->sequence_number = 0;
350 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500351 kfree(server->session_key.response);
352 server->session_key.response = NULL;
353 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000354 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500355 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500357 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400358 INIT_LIST_HEAD(&retry_list);
Joe Perchesf96637b2013-05-04 22:12:25 -0500359 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500361 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
362 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400363 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
364 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400365 list_move(&mid_entry->qhead, &retry_list);
366 }
367 spin_unlock(&GlobalMid_Lock);
368
Joe Perchesf96637b2013-05-04 22:12:25 -0500369 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
Jeff Layton3c1105d2011-05-22 07:09:13 -0400370 list_for_each_safe(tmp, tmp2, &retry_list) {
371 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500372 list_del_init(&mid_entry->qhead);
373 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400376 do {
Steve French6c3d8902006-07-31 22:46:20 +0000377 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300378
379 /* we should try only the port we connected to before */
380 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000381 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500382 cifs_dbg(FYI, "reconnect error %d\n", rc);
Steve French0cb766a2005-04-28 22:41:11 -0700383 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 } else {
385 atomic_inc(&tcpSesReconnectCount);
386 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000387 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000388 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000389 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400391 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500392
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 return rc;
394}
395
Jeff Laytonc74093b2011-01-11 07:24:23 -0500396static void
397cifs_echo_request(struct work_struct *work)
398{
399 int rc;
400 struct TCP_Server_Info *server = container_of(work,
401 struct TCP_Server_Info, echo.work);
402
Jeff Layton247ec9b2011-02-04 17:09:50 -0500403 /*
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400404 * We cannot send an echo if it is disabled or until the
405 * NEGOTIATE_PROTOCOL request is done, which is indicated by
406 * server->ops->need_neg() == true. Also, no need to ping if
407 * we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500408 */
Pavel Shilovsky286170a2012-05-25 10:43:58 +0400409 if (!server->ops->need_neg || server->ops->need_neg(server) ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400410 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Jeff Layton247ec9b2011-02-04 17:09:50 -0500411 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500412 goto requeue_echo;
413
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400414 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500415 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500416 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
417 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500418
419requeue_echo:
Jeff Laytonda472fc2012-03-23 14:40:53 -0400420 queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500421}
422
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400423static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400424allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400425{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400426 if (!server->bigbuf) {
427 server->bigbuf = (char *)cifs_buf_get();
428 if (!server->bigbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500429 cifs_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400430 msleep(3000);
431 /* retry will check if exiting */
432 return false;
433 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400434 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400435 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400436 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400437 }
438
Jeff Layton2a37ef92011-10-19 15:29:23 -0400439 if (!server->smallbuf) {
440 server->smallbuf = (char *)cifs_small_buf_get();
441 if (!server->smallbuf) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500442 cifs_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400443 msleep(1000);
444 /* retry will check if exiting */
445 return false;
446 }
447 /* beginning of smb buffer is cleared in our buf_get */
448 } else {
449 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400450 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400451 }
452
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400453 return true;
454}
455
Jeff Laytonba749e62011-10-11 06:41:32 -0400456static bool
457server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400458{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300459 /*
460 * We need to wait 2 echo intervals to make sure we handle such
461 * situations right:
462 * 1s client sends a normal SMB request
463 * 2s client gets a response
464 * 30s echo workqueue job pops, and decides we got a response recently
465 * and don't need to send another
466 * ...
467 * 65s kernel_recvmsg times out, and we see that we haven't gotten
468 * a response in >60s.
469 */
470 if (server->tcpStatus == CifsGood &&
471 time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500472 cifs_dbg(VFS, "Server %s has not responded in %d seconds. Reconnecting...\n",
473 server->hostname, (2 * SMB_ECHO_INTERVAL) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400474 cifs_reconnect(server);
475 wake_up(&server->response_q);
476 return true;
477 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400478
Jeff Laytonba749e62011-10-11 06:41:32 -0400479 return false;
480}
481
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400482/*
483 * kvec_array_init - clone a kvec array, and advance into it
484 * @new: pointer to memory for cloned array
485 * @iov: pointer to original array
486 * @nr_segs: number of members in original array
487 * @bytes: number of bytes to advance into the cloned array
488 *
489 * This function will copy the array provided in iov to a section of memory
490 * and advance the specified number of bytes into the new array. It returns
491 * the number of segments in the new array. "new" must be at least as big as
492 * the original iov array.
493 */
494static unsigned int
495kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
496 size_t bytes)
497{
498 size_t base = 0;
499
500 while (bytes || !iov->iov_len) {
501 int copy = min(bytes, iov->iov_len);
502
503 bytes -= copy;
504 base += copy;
505 if (iov->iov_len == base) {
506 iov++;
507 nr_segs--;
508 base = 0;
509 }
510 }
511 memcpy(new, iov, sizeof(*iov) * nr_segs);
512 new->iov_base += base;
513 new->iov_len -= base;
514 return nr_segs;
515}
516
Jeff Layton1041e3f2011-10-19 15:28:27 -0400517static struct kvec *
518get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
519{
520 struct kvec *new_iov;
521
522 if (server->iov && nr_segs <= server->nr_iov)
523 return server->iov;
524
525 /* not big enough -- allocate a new one and release the old */
526 new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
527 if (new_iov) {
528 kfree(server->iov);
529 server->iov = new_iov;
530 server->nr_iov = nr_segs;
531 }
532 return new_iov;
533}
534
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400535int
536cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
537 unsigned int nr_segs, unsigned int to_read)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400538{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400539 int length = 0;
540 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400541 unsigned int segs;
Jeff Laytone831e6c2011-10-11 06:41:32 -0400542 struct msghdr smb_msg;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400543 struct kvec *iov;
544
Jeff Layton1041e3f2011-10-19 15:28:27 -0400545 iov = get_server_iovec(server, nr_segs);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400546 if (!iov)
547 return -ENOMEM;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400548
Jeff Laytone831e6c2011-10-11 06:41:32 -0400549 smb_msg.msg_control = NULL;
550 smb_msg.msg_controllen = 0;
551
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400552 for (total_read = 0; to_read; total_read += length, to_read -= length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500553 try_to_freeze();
554
Jeff Laytonba749e62011-10-11 06:41:32 -0400555 if (server_unresponsive(server)) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400556 total_read = -EAGAIN;
Jeff Laytonba749e62011-10-11 06:41:32 -0400557 break;
558 }
559
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400560 segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
561
562 length = kernel_recvmsg(server->ssocket, &smb_msg,
563 iov, segs, to_read, 0);
564
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400565 if (server->tcpStatus == CifsExiting) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400566 total_read = -ESHUTDOWN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400567 break;
568 } else if (server->tcpStatus == CifsNeedReconnect) {
569 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400570 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400571 break;
572 } else if (length == -ERESTARTSYS ||
573 length == -EAGAIN ||
574 length == -EINTR) {
575 /*
576 * Minimum sleep to prevent looping, allowing socket
577 * to clear and app threads to set tcpStatus
578 * CifsNeedReconnect if server hung.
579 */
580 usleep_range(1000, 2000);
581 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400582 continue;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400583 } else if (length <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500584 cifs_dbg(FYI, "Received no data or error: expecting %d\n"
585 "got %d", to_read, length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400586 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400587 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400588 break;
589 }
590 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400591 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400592}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400593
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400594int
595cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
596 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400597{
598 struct kvec iov;
599
600 iov.iov_base = buf;
601 iov.iov_len = to_read;
602
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400603 return cifs_readv_from_socket(server, &iov, 1, to_read);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400604}
605
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400606static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400607is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400608{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400609 /*
610 * The first byte big endian of the length field,
611 * is actually not part of the length but the type
612 * with the most common, zero, as regular data.
613 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400614 switch (type) {
615 case RFC1002_SESSION_MESSAGE:
616 /* Regular SMB response */
617 return true;
618 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500619 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400620 break;
621 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500622 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400623 break;
624 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400625 /*
626 * We get this from Windows 98 instead of an error on
627 * SMB negprot response.
628 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500629 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400630 /* give server a second to clean up */
631 msleep(1000);
632 /*
633 * Always try 445 first on reconnect since we get NACK
634 * on some if we ever connected to port 139 (the NACK
635 * is since we do not begin with RFC1001 session
636 * initialize frame).
637 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400638 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400639 cifs_reconnect(server);
640 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400641 break;
642 default:
Joe Perchesf96637b2013-05-04 22:12:25 -0500643 cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400644 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400645 }
646
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400647 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400648}
649
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400650void
651dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400652{
653#ifdef CONFIG_CIFS_STATS2
654 mid->when_received = jiffies;
655#endif
656 spin_lock(&GlobalMid_Lock);
657 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400658 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400659 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400660 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400661 list_del_init(&mid->qhead);
662 spin_unlock(&GlobalMid_Lock);
663}
664
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400665static void
666handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400667 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400668{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400669 if (server->ops->check_trans2 &&
670 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400671 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400672 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400673 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400674 /* Was previous buf put in mpx struct for multi-rsp? */
675 if (!mid->multiRsp) {
676 /* smb buffer will be freed by user thread */
677 if (server->large_buf)
678 server->bigbuf = NULL;
679 else
680 server->smallbuf = NULL;
681 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400682 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400683}
684
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400685static void clean_demultiplex_info(struct TCP_Server_Info *server)
686{
687 int length;
688
689 /* take it off the list, if it's not already */
690 spin_lock(&cifs_tcp_ses_lock);
691 list_del_init(&server->tcp_ses_list);
692 spin_unlock(&cifs_tcp_ses_lock);
693
694 spin_lock(&GlobalMid_Lock);
695 server->tcpStatus = CifsExiting;
696 spin_unlock(&GlobalMid_Lock);
697 wake_up_all(&server->response_q);
698
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400699 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300700 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400701 if (server->credits <= 0)
702 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300703 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400704 /*
705 * Although there should not be any requests blocked on this queue it
706 * can not hurt to be paranoid and try to wake up requests that may
707 * haven been blocked when more than 50 at time were on the wire to the
708 * same server - they now will see the session is in exit state and get
709 * out of SendReceive.
710 */
711 wake_up_all(&server->request_q);
712 /* give those requests time to exit */
713 msleep(125);
714
715 if (server->ssocket) {
716 sock_release(server->ssocket);
717 server->ssocket = NULL;
718 }
719
720 if (!list_empty(&server->pending_mid_q)) {
721 struct list_head dispose_list;
722 struct mid_q_entry *mid_entry;
723 struct list_head *tmp, *tmp2;
724
725 INIT_LIST_HEAD(&dispose_list);
726 spin_lock(&GlobalMid_Lock);
727 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
728 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500729 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400730 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400731 list_move(&mid_entry->qhead, &dispose_list);
732 }
733 spin_unlock(&GlobalMid_Lock);
734
735 /* now walk dispose list and issue callbacks */
736 list_for_each_safe(tmp, tmp2, &dispose_list) {
737 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500738 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400739 list_del_init(&mid_entry->qhead);
740 mid_entry->callback(mid_entry);
741 }
742 /* 1/8th of sec is more than enough time for them to exit */
743 msleep(125);
744 }
745
746 if (!list_empty(&server->pending_mid_q)) {
747 /*
748 * mpx threads have not exited yet give them at least the smb
749 * send timeout time for long ops.
750 *
751 * Due to delays on oplock break requests, we need to wait at
752 * least 45 seconds before giving up on a request getting a
753 * response and going ahead and killing cifsd.
754 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500755 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400756 msleep(46000);
757 /*
758 * If threads still have not exited they are probably never
759 * coming home not much else we can do but free the memory.
760 */
761 }
762
763 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400764 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400765 kfree(server);
766
767 length = atomic_dec_return(&tcpSesAllocCount);
768 if (length > 0)
769 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
770 GFP_KERNEL);
771}
772
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400773static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400774standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
775{
776 int length;
777 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400778 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400779
780 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400781 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500782 cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400783 cifs_reconnect(server);
784 wake_up(&server->response_q);
785 return -EAGAIN;
786 }
787
788 /* switch to large buffer if too big for a small one */
789 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
790 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400791 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400792 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400793 }
794
795 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400796 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
797 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400798 if (length < 0)
799 return length;
800 server->total_read += length;
801
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400802 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400803
804 /*
805 * We know that we received enough to get to the MID as we
806 * checked the pdu_length earlier. Now check to see
807 * if the rest of the header is OK. We borrow the length
808 * var for the rest of the loop to avoid a new stack var.
809 *
810 * 48 bytes is enough to display the header and a little bit
811 * into the payload for debugging purposes.
812 */
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400813 length = server->ops->check_message(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400814 if (length != 0)
815 cifs_dump_mem("Bad SMB: ", buf,
816 min_t(unsigned int, server->total_read, 48));
817
Pavel Shilovsky2e44b282012-09-18 16:20:33 -0700818 if (server->ops->is_status_pending &&
819 server->ops->is_status_pending(buf, server, length))
820 return -1;
821
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500822 if (!mid)
823 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400824
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400825 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500826 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400827}
828
829static int
Al Viro7c97c202011-06-21 08:51:28 -0400830cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
832 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400833 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400834 unsigned int pdu_length;
835 char *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 struct task_struct *task_to_wake = NULL;
837 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -0500840 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400841
842 length = atomic_inc_return(&tcpSesAllocCount);
843 if (length > 1)
Steve French26f57362007-08-30 22:09:15 +0000844 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
845 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700847 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000848 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700849 if (try_to_freeze())
850 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700851
Jeff Layton2a37ef92011-10-19 15:29:23 -0400852 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400853 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700854
Jeff Layton2a37ef92011-10-19 15:29:23 -0400855 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400856 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000857 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000858
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400859 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400860 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +0000861 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400862 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700863
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400864 /*
865 * The right amount was read from socket - 4 bytes,
866 * so we can now interpret the length field.
867 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400868 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -0700869
Joe Perchesf96637b2013-05-04 22:12:25 -0500870 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400871 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000872 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700873
Jeff Layton89482a52011-10-19 15:28:57 -0400874 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400875 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500876 cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
877 pdu_length);
Jeff Layton89482a52011-10-19 15:28:57 -0400878 cifs_reconnect(server);
879 wake_up(&server->response_q);
880 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700881 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400882
Jeff Layton89482a52011-10-19 15:28:57 -0400883 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400884 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400885 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -0400886 if (length < 0)
887 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400888 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -0400889
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400890 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400891
Jeff Layton44d22d82011-10-19 15:29:49 -0400892 if (!mid_entry || !mid_entry->receive)
893 length = standard_receive3(server, mid_entry);
894 else
895 length = mid_entry->receive(server, mid_entry);
896
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400897 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700898 continue;
899
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400900 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -0400901 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700902
Steve Frenchfda35942011-01-20 18:06:34 +0000903 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500904 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -0400905 if (!mid_entry->multiRsp || mid_entry->multiEnd)
906 mid_entry->callback(mid_entry);
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400907 } else if (!server->ops->is_oplock_break ||
908 !server->ops->is_oplock_break(buf, server)) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500909 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
910 atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400911 cifs_dump_mem("Received Data is: ", buf,
912 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +0000913#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky7f0adb52012-05-28 15:50:10 +0400914 if (server->ops->dump_detail)
915 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +0000916 cifs_dump_mids(server);
917#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000918
Steve Frenche4eb2952005-04-28 22:41:09 -0700919 }
920 } /* end while !EXITING */
921
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800922 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -0400923 cifs_buf_release(server->bigbuf);
924 if (server->smallbuf) /* no sense logging a debug message if NULL */
925 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -0400927 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400928 clean_demultiplex_info(server);
Steve French50c2f752007-07-13 00:33:32 +0000929
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -0400930 /* if server->tsk was NULL then wait for a signal before exiting */
931 if (!task_to_wake) {
932 set_current_state(TASK_INTERRUPTIBLE);
933 while (!signal_pending(current)) {
934 schedule();
935 set_current_state(TASK_INTERRUPTIBLE);
936 }
937 set_current_state(TASK_RUNNING);
938 }
939
Jeff Layton0468a2c2008-12-01 07:09:35 -0500940 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941}
942
Jeff Laytonc359cf32007-11-16 22:22:06 +0000943/* extract the host portion of the UNC string */
944static char *
945extract_hostname(const char *unc)
946{
947 const char *src;
948 char *dst, *delim;
949 unsigned int len;
950
951 /* skip double chars at beginning of string */
952 /* BB: check validity of these bytes? */
953 src = unc + 2;
954
955 /* delimiter between hostname and sharename is always '\\' now */
956 delim = strchr(src, '\\');
957 if (!delim)
958 return ERR_PTR(-EINVAL);
959
960 len = delim - src;
961 dst = kmalloc((len + 1), GFP_KERNEL);
962 if (dst == NULL)
963 return ERR_PTR(-ENOMEM);
964
965 memcpy(dst, src, len);
966 dst[len] = '\0';
967
968 return dst;
969}
970
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400971static int get_option_ul(substring_t args[], unsigned long *option)
972{
973 int rc;
974 char *string;
975
976 string = match_strdup(args);
977 if (string == NULL)
978 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +0100979 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400980 kfree(string);
981
982 return rc;
983}
984
Eric W. Biederman3da46562013-02-06 01:37:39 -0800985static int get_option_uid(substring_t args[], kuid_t *result)
986{
987 unsigned long value;
988 kuid_t uid;
989 int rc;
990
991 rc = get_option_ul(args, &value);
992 if (rc)
993 return rc;
994
995 uid = make_kuid(current_user_ns(), value);
996 if (!uid_valid(uid))
997 return -EINVAL;
998
999 *result = uid;
1000 return 0;
1001}
1002
1003static int get_option_gid(substring_t args[], kgid_t *result)
1004{
1005 unsigned long value;
1006 kgid_t gid;
1007 int rc;
1008
1009 rc = get_option_ul(args, &value);
1010 if (rc)
1011 return rc;
1012
1013 gid = make_kgid(current_user_ns(), value);
1014 if (!gid_valid(gid))
1015 return -EINVAL;
1016
1017 *result = gid;
1018 return 0;
1019}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001020
1021static int cifs_parse_security_flavors(char *value,
1022 struct smb_vol *vol)
1023{
1024
1025 substring_t args[MAX_OPT_ARGS];
1026
1027 switch (match_token(value, cifs_secflavor_tokens, args)) {
1028 case Opt_sec_krb5:
Martijn de Gouw0b7bc842012-10-24 11:45:46 +02001029 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001030 break;
1031 case Opt_sec_krb5i:
1032 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
1033 break;
1034 case Opt_sec_krb5p:
1035 /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
Joe Perchesf96637b2013-05-04 22:12:25 -05001036 cifs_dbg(VFS, "Krb5 cifs privacy not supported\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001037 break;
1038 case Opt_sec_ntlmssp:
1039 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1040 break;
1041 case Opt_sec_ntlmsspi:
1042 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
1043 break;
1044 case Opt_ntlm:
1045 /* ntlm is default so can be turned off too */
1046 vol->secFlg |= CIFSSEC_MAY_NTLM;
1047 break;
1048 case Opt_sec_ntlmi:
1049 vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
1050 break;
Jeff Layton76596242012-07-23 20:34:17 -04001051 case Opt_sec_ntlmv2:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001052 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1053 break;
1054 case Opt_sec_ntlmv2i:
1055 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
1056 break;
1057#ifdef CONFIG_CIFS_WEAK_PW_HASH
1058 case Opt_sec_lanman:
1059 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1060 break;
1061#endif
1062 case Opt_sec_none:
1063 vol->nullauth = 1;
Jeff Layton539673f2013-05-24 07:40:04 -04001064 vol->secFlg |= CIFSSEC_MAY_NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001065 break;
1066 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001067 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001068 return 1;
1069 }
1070
1071 return 0;
1072}
1073
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001075cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1076{
1077 substring_t args[MAX_OPT_ARGS];
1078
1079 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1080 case Opt_cache_loose:
1081 vol->direct_io = false;
1082 vol->strict_io = false;
1083 break;
1084 case Opt_cache_strict:
1085 vol->direct_io = false;
1086 vol->strict_io = true;
1087 break;
1088 case Opt_cache_none:
1089 vol->direct_io = true;
1090 vol->strict_io = false;
1091 break;
1092 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001093 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001094 return 1;
1095 }
1096 return 0;
1097}
1098
1099static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001100cifs_parse_smb_version(char *value, struct smb_vol *vol)
1101{
1102 substring_t args[MAX_OPT_ARGS];
1103
1104 switch (match_token(value, cifs_smb_version_tokens, args)) {
1105 case Smb_1:
1106 vol->ops = &smb1_operations;
1107 vol->vals = &smb1_values;
1108 break;
Steve French1080ef72011-02-24 18:07:19 +00001109#ifdef CONFIG_CIFS_SMB2
Steve Frenchdd446b12012-11-28 23:21:06 -06001110 case Smb_20:
1111 vol->ops = &smb21_operations; /* currently identical with 2.1 */
1112 vol->vals = &smb20_values;
1113 break;
Steve French1080ef72011-02-24 18:07:19 +00001114 case Smb_21:
1115 vol->ops = &smb21_operations;
1116 vol->vals = &smb21_values;
1117 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001118 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001119 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001120 vol->vals = &smb30_values;
1121 break;
Steve French1080ef72011-02-24 18:07:19 +00001122#endif
Jeff Layton23db65f2012-05-15 12:20:51 -04001123 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001124 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001125 return 1;
1126 }
1127 return 0;
1128}
1129
Jeff Laytond387a5c2012-12-10 06:10:46 -05001130/*
1131 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1132 * fields with the result. Returns 0 on success and an error otherwise.
1133 */
1134static int
1135cifs_parse_devname(const char *devname, struct smb_vol *vol)
1136{
1137 char *pos;
1138 const char *delims = "/\\";
1139 size_t len;
1140
1141 /* make sure we have a valid UNC double delimiter prefix */
1142 len = strspn(devname, delims);
1143 if (len != 2)
1144 return -EINVAL;
1145
1146 /* find delimiter between host and sharename */
1147 pos = strpbrk(devname + 2, delims);
1148 if (!pos)
1149 return -EINVAL;
1150
1151 /* skip past delimiter */
1152 ++pos;
1153
1154 /* now go until next delimiter or end of string */
1155 len = strcspn(pos, delims);
1156
1157 /* move "pos" up to delimiter or NULL */
1158 pos += len;
1159 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1160 if (!vol->UNC)
1161 return -ENOMEM;
1162
1163 convert_delimiter(vol->UNC, '\\');
1164
1165 /* If pos is NULL, or is a bogus trailing delimiter then no prepath */
1166 if (!*pos++ || !*pos)
1167 return 0;
1168
1169 vol->prepath = kstrdup(pos, GFP_KERNEL);
1170 if (!vol->prepath)
1171 return -ENOMEM;
1172
1173 return 0;
1174}
1175
Jeff Layton23db65f2012-05-15 12:20:51 -04001176static int
Sean Finneyb9468452011-04-11 13:19:32 +00001177cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001178 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001180 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001181 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 unsigned int temp_len, i, j;
1183 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001184 short int override_uid = -1;
1185 short int override_gid = -1;
1186 bool uid_specified = false;
1187 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001188 bool sloppy = false;
1189 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001190 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001191 char *string = NULL;
1192 char *tmp_end, *value;
1193 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001194 bool got_ip = false;
1195 unsigned short port = 0;
1196 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001199 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001200 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
Jeff Layton6ee95422012-11-26 11:09:57 -05001202 /* ensure we always start with zeroed-out smb_vol */
1203 memset(vol, 0, sizeof(*vol));
1204
Jeff Layton88463992010-11-22 15:31:03 -05001205 /*
1206 * does not have to be perfect mapping since field is
1207 * informational, only used for servers that do not support
1208 * port 445 and it can be overridden at mount time
1209 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001210 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1211 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001212 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1213
Jeff Layton1397f2e2011-01-07 11:30:28 -05001214 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001215 /* null target name indicates to use *SMBSERVR default called name
1216 if we end up sending RFC1001 session initialize */
1217 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001218 vol->cred_uid = current_uid();
1219 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001220 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001221
1222 /* default to only allowing write access to owner of the mount */
1223 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001226 /* default is always to request posix paths. */
1227 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001228 /* default to using server inode numbers where available */
1229 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001230
Jeff Layton1b359202012-09-19 15:20:27 -07001231 /* default is to use strict cifs caching semantics */
1232 vol->strict_io = true;
1233
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301234 vol->actimeo = CIFS_DEF_ACTIMEO;
1235
Jeff Layton23db65f2012-05-15 12:20:51 -04001236 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1237 vol->ops = &smb1_operations;
1238 vol->vals = &smb1_values;
1239
Sean Finneyb9468452011-04-11 13:19:32 +00001240 if (!mountdata)
1241 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Sean Finneyb9468452011-04-11 13:19:32 +00001243 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1244 if (!mountdata_copy)
1245 goto cifs_parse_mount_err;
1246
1247 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001248 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001249
Steve French50c2f752007-07-13 00:33:32 +00001250 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001251 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 separator[0] = options[4];
1253 options += 5;
1254 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001255 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 }
1257 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001258 vol->backupuid_specified = false; /* no backup intent for a user */
1259 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001260
Jeff Layton37d4f992013-05-24 07:40:05 -04001261 switch (cifs_parse_devname(devname, vol)) {
1262 case 0:
1263 break;
1264 case -ENOMEM:
1265 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1266 goto cifs_parse_mount_err;
1267 case -EINVAL:
1268 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1269 goto cifs_parse_mount_err;
1270 default:
1271 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1272 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001273 }
1274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001276 substring_t args[MAX_OPT_ARGS];
1277 unsigned long option;
1278 int token;
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 if (!*data)
1281 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001283 token = match_token(data, cifs_mount_option_tokens, args);
1284
1285 switch (token) {
1286
1287 /* Ingnore the following */
1288 case Opt_ignore:
1289 break;
1290
1291 /* Boolean values */
1292 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001294 break;
1295 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001297 break;
1298 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001299 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001300 break;
1301 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001302 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001303 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001304 case Opt_forcegid:
1305 override_gid = 1;
1306 break;
1307 case Opt_noforcegid:
1308 override_gid = 0;
1309 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001310 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001311 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001312 break;
1313 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001314 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001315 break;
1316 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001318 break;
1319 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001321 break;
1322 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001324 break;
1325 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001327 break;
1328 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001329 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001330 break;
1331 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001332 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001333 break;
1334 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001335 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001336 break;
1337 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001338 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001339 break;
1340 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001341 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001342 break;
1343 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001344 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001345 break;
1346 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001347 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001348 break;
1349 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001350 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001351 break;
1352 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001353 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001354 break;
1355 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001356 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001357 break;
1358 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001359 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001360 /*
1361 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001363 * local vfs will do advisory
1364 */
Steve French50c2f752007-07-13 00:33:32 +00001365 if (vol->file_mode ==
1366 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001367 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 break;
1369 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001370 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371 break;
1372 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001374 break;
1375 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001377 break;
1378 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001379 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
1381 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001382 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
1390 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 break;
1393 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001395 break;
1396 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001397 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001398 break;
1399 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001400 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001401 break;
1402 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001404 break;
1405 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001407 break;
1408 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001409 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001410 break;
1411 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001412 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001413 break;
1414 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001415 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001416 break;
1417 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001419 break;
1420 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001422 break;
1423 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001424 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001425 break;
1426 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001427 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001428 break;
1429 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001430 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001431 * is a per tree connection (mount) not a per socket
1432 * or per-smb connection option in the protocol
1433 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1434 */
Steve French95b1cb92008-05-15 16:44:38 +00001435 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001437 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001438 printk(KERN_WARNING "CIFS: Mount option noac not "
1439 "supported. Instead set "
1440 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001441 break;
1442 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301443#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001444 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001445 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301446#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301447 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001450 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 break;
1452 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001453 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001454 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001455 case Opt_sloppy:
1456 sloppy = true;
1457 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001458
1459 /* Numeric Values */
1460 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001461 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001462 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1463 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001464 goto cifs_parse_mount_err;
1465 }
1466 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001467 break;
1468 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001469 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001470 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1471 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001472 goto cifs_parse_mount_err;
1473 }
1474 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001475 break;
1476 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001477 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001478 cifs_dbg(VFS, "%s: Invalid uid value\n",
1479 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001480 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001482 uid_specified = true;
1483 break;
1484 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001485 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001486 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1487 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001488 goto cifs_parse_mount_err;
1489 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001490 break;
1491 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001492 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001493 cifs_dbg(VFS, "%s: Invalid gid value\n",
1494 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001495 goto cifs_parse_mount_err;
1496 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001497 gid_specified = true;
1498 break;
1499 case Opt_file_mode:
1500 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001501 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1502 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001503 goto cifs_parse_mount_err;
1504 }
1505 vol->file_mode = option;
1506 break;
1507 case Opt_dirmode:
1508 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001509 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1510 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001511 goto cifs_parse_mount_err;
1512 }
1513 vol->dir_mode = option;
1514 break;
1515 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001516 if (get_option_ul(args, &option) ||
1517 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001518 cifs_dbg(VFS, "%s: Invalid port value\n",
1519 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001520 goto cifs_parse_mount_err;
1521 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001522 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001523 break;
1524 case Opt_rsize:
1525 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001526 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1527 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001528 goto cifs_parse_mount_err;
1529 }
1530 vol->rsize = option;
1531 break;
1532 case Opt_wsize:
1533 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001534 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1535 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001536 goto cifs_parse_mount_err;
1537 }
1538 vol->wsize = option;
1539 break;
1540 case Opt_actimeo:
1541 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001542 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1543 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001544 goto cifs_parse_mount_err;
1545 }
1546 vol->actimeo = HZ * option;
1547 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001548 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001549 goto cifs_parse_mount_err;
1550 }
1551 break;
1552
1553 /* String Arguments */
1554
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001555 case Opt_blank_user:
1556 /* null user, ie. anonymous authentication */
1557 vol->nullauth = 1;
1558 vol->username = NULL;
1559 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001560 case Opt_user:
1561 string = match_strdup(args);
1562 if (string == NULL)
1563 goto out_nomem;
1564
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001565 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001566 MAX_USERNAME_SIZE) {
1567 printk(KERN_WARNING "CIFS: username too long\n");
1568 goto cifs_parse_mount_err;
1569 }
1570 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001571 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001572 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001573 break;
1574 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001575 /* passwords have to be handled differently
1576 * to allow the character used for deliminator
1577 * to be passed within them
1578 */
1579
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001580 /*
1581 * Check if this is a case where the password
1582 * starts with a delimiter
1583 */
1584 tmp_end = strchr(data, '=');
1585 tmp_end++;
1586 if (!(tmp_end < end && tmp_end[1] == delim)) {
1587 /* No it is not. Set the password to NULL */
1588 vol->password = NULL;
1589 break;
1590 }
1591 /* Yes it is. Drop down to Opt_pass below.*/
1592 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001593 /* Obtain the value string */
1594 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001595 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001596
1597 /* Set tmp_end to end of the string */
1598 tmp_end = (char *) value + strlen(value);
1599
1600 /* Check if following character is the deliminator
1601 * If yes, we have encountered a double deliminator
1602 * reset the NULL character to the deliminator
1603 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301604 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001605 tmp_end[0] = delim;
1606
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301607 /* Keep iterating until we get to a single
1608 * deliminator OR the end
1609 */
1610 while ((tmp_end = strchr(tmp_end, delim))
1611 != NULL && (tmp_end[1] == delim)) {
1612 tmp_end = (char *) &tmp_end[2];
1613 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001614
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301615 /* Reset var options to point to next element */
1616 if (tmp_end) {
1617 tmp_end[0] = '\0';
1618 options = (char *) &tmp_end[1];
1619 } else
1620 /* Reached the end of the mount option
1621 * string */
1622 options = end;
1623 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001624
1625 /* Now build new password string */
1626 temp_len = strlen(value);
1627 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1628 if (vol->password == NULL) {
1629 printk(KERN_WARNING "CIFS: no memory "
1630 "for password\n");
1631 goto cifs_parse_mount_err;
1632 }
1633
1634 for (i = 0, j = 0; i < temp_len; i++, j++) {
1635 vol->password[j] = value[i];
1636 if ((value[i] == delim) &&
1637 value[i+1] == delim)
1638 /* skip the second deliminator */
1639 i++;
1640 }
1641 vol->password[j] = '\0';
1642 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001643 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001644 /* FIXME: should this be an error instead? */
1645 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001646 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001647 case Opt_ip:
1648 string = match_strdup(args);
1649 if (string == NULL)
1650 goto out_nomem;
1651
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001652 if (!cifs_convert_address(dstaddr, string,
1653 strlen(string))) {
1654 printk(KERN_ERR "CIFS: bad ip= option (%s).\n",
1655 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001656 goto cifs_parse_mount_err;
1657 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001658 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001659 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001660 case Opt_domain:
1661 string = match_strdup(args);
1662 if (string == NULL)
1663 goto out_nomem;
1664
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001665 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001666 printk(KERN_WARNING "CIFS: domain name too"
1667 " long\n");
1668 goto cifs_parse_mount_err;
1669 }
1670
1671 vol->domainname = kstrdup(string, GFP_KERNEL);
1672 if (!vol->domainname) {
1673 printk(KERN_WARNING "CIFS: no memory "
1674 "for domainname\n");
1675 goto cifs_parse_mount_err;
1676 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001677 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001678 break;
1679 case Opt_srcaddr:
1680 string = match_strdup(args);
1681 if (string == NULL)
1682 goto out_nomem;
1683
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001684 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001685 (struct sockaddr *)&vol->srcaddr,
1686 string, strlen(string))) {
1687 printk(KERN_WARNING "CIFS: Could not parse"
1688 " srcaddr: %s\n", string);
1689 goto cifs_parse_mount_err;
1690 }
1691 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001692 case Opt_iocharset:
1693 string = match_strdup(args);
1694 if (string == NULL)
1695 goto out_nomem;
1696
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001697 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001698 printk(KERN_WARNING "CIFS: iocharset name "
1699 "too long.\n");
1700 goto cifs_parse_mount_err;
1701 }
1702
1703 if (strnicmp(string, "default", 7) != 0) {
1704 vol->iocharset = kstrdup(string,
1705 GFP_KERNEL);
1706 if (!vol->iocharset) {
1707 printk(KERN_WARNING "CIFS: no memory"
1708 "for charset\n");
1709 goto cifs_parse_mount_err;
1710 }
1711 }
1712 /* if iocharset not set then load_nls_default
1713 * is used by caller
1714 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001715 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001716 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001717 case Opt_netbiosname:
1718 string = match_strdup(args);
1719 if (string == NULL)
1720 goto out_nomem;
1721
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001722 memset(vol->source_rfc1001_name, 0x20,
1723 RFC1001_NAME_LEN);
1724 /*
1725 * FIXME: are there cases in which a comma can
1726 * be valid in workstation netbios name (and
1727 * need special handling)?
1728 */
1729 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1730 /* don't ucase netbiosname for user */
1731 if (string[i] == 0)
1732 break;
1733 vol->source_rfc1001_name[i] = string[i];
1734 }
1735 /* The string has 16th byte zero still from
1736 * set at top of the function
1737 */
1738 if (i == RFC1001_NAME_LEN && string[i] != 0)
1739 printk(KERN_WARNING "CIFS: netbiosname"
1740 " longer than 15 truncated.\n");
1741
1742 break;
1743 case Opt_servern:
1744 /* servernetbiosname specified override *SMBSERVER */
1745 string = match_strdup(args);
1746 if (string == NULL)
1747 goto out_nomem;
1748
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001749 /* last byte, type, is 0x20 for servr type */
1750 memset(vol->target_rfc1001_name, 0x20,
1751 RFC1001_NAME_LEN_WITH_NULL);
1752
1753 /* BB are there cases in which a comma can be
1754 valid in this workstation netbios name
1755 (and need special handling)? */
1756
1757 /* user or mount helper must uppercase the
1758 netbios name */
1759 for (i = 0; i < 15; i++) {
1760 if (string[i] == 0)
1761 break;
1762 vol->target_rfc1001_name[i] = string[i];
1763 }
1764 /* The string has 16th byte zero still from
1765 set at top of the function */
1766 if (i == RFC1001_NAME_LEN && string[i] != 0)
1767 printk(KERN_WARNING "CIFS: server net"
1768 "biosname longer than 15 truncated.\n");
1769 break;
1770 case Opt_ver:
1771 string = match_strdup(args);
1772 if (string == NULL)
1773 goto out_nomem;
1774
Jeff Layton5249af32012-05-15 12:04:03 -04001775 if (strnicmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 /* This is the default */
1777 break;
1778 }
1779 /* For all other value, error */
1780 printk(KERN_WARNING "CIFS: Invalid version"
1781 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001782 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001783 case Opt_vers:
1784 string = match_strdup(args);
1785 if (string == NULL)
1786 goto out_nomem;
1787
1788 if (cifs_parse_smb_version(string, vol) != 0)
1789 goto cifs_parse_mount_err;
1790 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001791 case Opt_sec:
1792 string = match_strdup(args);
1793 if (string == NULL)
1794 goto out_nomem;
1795
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001796 if (cifs_parse_security_flavors(string, vol) != 0)
1797 goto cifs_parse_mount_err;
1798 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001799 case Opt_cache:
1800 string = match_strdup(args);
1801 if (string == NULL)
1802 goto out_nomem;
1803
1804 if (cifs_parse_cache_flavor(string, vol) != 0)
1805 goto cifs_parse_mount_err;
1806 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001807 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001808 /*
1809 * An option we don't recognize. Save it off for later
1810 * if we haven't already found one
1811 */
1812 if (!invalid)
1813 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001814 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 /* Free up any allocated string */
1817 kfree(string);
1818 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001820
Jeff Laytond8162552012-03-23 14:40:56 -04001821 if (!sloppy && invalid) {
1822 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1823 goto cifs_parse_mount_err;
1824 }
1825
Jeff Layton8a8798a2012-01-17 16:09:15 -05001826#ifndef CONFIG_KEYS
1827 /* Muliuser mounts require CONFIG_KEYS support */
1828 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001829 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001830 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001831 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001832#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001833 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04001834 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001835 goto cifs_parse_mount_err;
1836 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001837
Jeff Layton62a1a432012-12-10 06:10:45 -05001838 /* make sure UNC has a share name */
1839 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001840 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05001841 goto cifs_parse_mount_err;
1842 }
1843
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001844 if (!got_ip) {
1845 /* No ip= option specified? Try to get it from UNC */
1846 if (!cifs_convert_address(dstaddr, &vol->UNC[2],
1847 strlen(&vol->UNC[2]))) {
1848 printk(KERN_ERR "Unable to determine destination "
1849 "address.\n");
1850 goto cifs_parse_mount_err;
1851 }
1852 }
1853
1854 /* set the port that we got earlier */
1855 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001857 if (uid_specified)
1858 vol->override_uid = override_uid;
1859 else if (override_uid == 1)
1860 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1861 "specified with no uid= option.\n");
1862
1863 if (gid_specified)
1864 vol->override_gid = override_gid;
1865 else if (override_gid == 1)
1866 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1867 "specified with no gid= option.\n");
1868
Sean Finneyb9468452011-04-11 13:19:32 +00001869 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001871
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001872out_nomem:
1873 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001874cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001875 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001876 kfree(mountdata_copy);
1877 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878}
1879
Ben Greear3eb9a882010-09-01 17:06:02 -07001880/** Returns true if srcaddr isn't specified and rhs isn't
1881 * specified, or if srcaddr is specified and
1882 * matches the IP address of the rhs argument.
1883 */
Jeff Layton45151482010-07-06 20:43:02 -04001884static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001885srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1886{
1887 switch (srcaddr->sa_family) {
1888 case AF_UNSPEC:
1889 return (rhs->sa_family == AF_UNSPEC);
1890 case AF_INET: {
1891 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1892 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1893 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1894 }
1895 case AF_INET6: {
1896 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05001897 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07001898 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1899 }
1900 default:
1901 WARN_ON(1);
1902 return false; /* don't expect to be here */
1903 }
1904}
1905
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001906/*
1907 * If no port is specified in addr structure, we try to match with 445 port
1908 * and if it fails - with 139 ports. It should be called only if address
1909 * families of server and addr are equal.
1910 */
1911static bool
1912match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1913{
Steve French6da97912011-03-13 18:55:55 +00001914 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001915
1916 switch (addr->sa_family) {
1917 case AF_INET:
1918 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1919 port = ((struct sockaddr_in *) addr)->sin_port;
1920 break;
1921 case AF_INET6:
1922 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1923 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1924 break;
1925 default:
1926 WARN_ON(1);
1927 return false;
1928 }
1929
1930 if (!port) {
1931 port = htons(CIFS_PORT);
1932 if (port == *sport)
1933 return true;
1934
1935 port = htons(RFC1001_PORT);
1936 }
1937
1938 return port == *sport;
1939}
Ben Greear3eb9a882010-09-01 17:06:02 -07001940
1941static bool
1942match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
1943 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944{
Jeff Layton45151482010-07-06 20:43:02 -04001945 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001946 case AF_INET: {
1947 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1948 struct sockaddr_in *srv_addr4 =
1949 (struct sockaddr_in *)&server->dstaddr;
1950
1951 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04001952 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001953 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001954 }
1955 case AF_INET6: {
1956 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1957 struct sockaddr_in6 *srv_addr6 =
1958 (struct sockaddr_in6 *)&server->dstaddr;
1959
Jeff Layton45151482010-07-06 20:43:02 -04001960 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001961 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04001962 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001963 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04001964 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001965 break;
1966 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001967 default:
1968 WARN_ON(1);
1969 return false; /* don't expect to be here */
1970 }
Jeff Layton45151482010-07-06 20:43:02 -04001971
Ben Greear3eb9a882010-09-01 17:06:02 -07001972 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
1973 return false;
1974
Jeff Layton45151482010-07-06 20:43:02 -04001975 return true;
1976}
1977
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001978static bool
1979match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
1980{
1981 unsigned int secFlags;
1982
1983 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
1984 secFlags = vol->secFlg;
1985 else
1986 secFlags = global_secflags | vol->secFlg;
1987
1988 switch (server->secType) {
1989 case LANMAN:
1990 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
1991 return false;
1992 break;
1993 case NTLMv2:
1994 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
1995 return false;
1996 break;
1997 case NTLM:
1998 if (!(secFlags & CIFSSEC_MAY_NTLM))
1999 return false;
2000 break;
2001 case Kerberos:
2002 if (!(secFlags & CIFSSEC_MAY_KRB5))
2003 return false;
2004 break;
2005 case RawNTLMSSP:
2006 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2007 return false;
2008 break;
2009 default:
2010 /* shouldn't happen */
2011 return false;
2012 }
2013
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002014 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002015 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002016 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002017 return false;
2018 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002019 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002020 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2021 return false;
2022
2023 return true;
2024}
2025
Jeff Layton9fa114f2012-11-26 11:09:57 -05002026static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002027{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002028 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2029
Jeff Layton23db65f2012-05-15 12:20:51 -04002030 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2031 return 0;
2032
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002033 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2034 return 0;
2035
2036 if (!match_address(server, addr,
2037 (struct sockaddr *)&vol->srcaddr))
2038 return 0;
2039
2040 if (!match_port(server, addr))
2041 return 0;
2042
2043 if (!match_security(server, vol))
2044 return 0;
2045
2046 return 1;
2047}
2048
Jeff Layton45151482010-07-06 20:43:02 -04002049static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002050cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002051{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002052 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302054 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002055 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002056 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002057 continue;
2058
Jeff Laytone7ddee92008-11-14 13:44:38 -05002059 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302060 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002061 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002062 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302064 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 return NULL;
2066}
2067
Jeff Layton14fbf502008-11-14 13:53:46 -05002068static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002069cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002071 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302073 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002074 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302075 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002076 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002078
Rob Landleyf1d0c992011-01-22 15:44:05 -06002079 put_net(cifs_net_ns(server));
2080
Jeff Laytone7ddee92008-11-14 13:44:38 -05002081 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302082 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002083
Jeff Laytonc74093b2011-01-11 07:24:23 -05002084 cancel_delayed_work_sync(&server->echo);
2085
Jeff Laytone7ddee92008-11-14 13:44:38 -05002086 spin_lock(&GlobalMid_Lock);
2087 server->tcpStatus = CifsExiting;
2088 spin_unlock(&GlobalMid_Lock);
2089
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002090 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302091 cifs_fscache_release_client_cookie(server);
2092
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002093 kfree(server->session_key.response);
2094 server->session_key.response = NULL;
2095 server->session_key.len = 0;
2096
Jeff Laytone7ddee92008-11-14 13:44:38 -05002097 task = xchg(&server->tsk, NULL);
2098 if (task)
2099 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100}
2101
Jeff Layton63c038c2008-12-01 18:41:46 -05002102static struct TCP_Server_Info *
2103cifs_get_tcp_session(struct smb_vol *volume_info)
2104{
2105 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002106 int rc;
2107
Joe Perchesf96637b2013-05-04 22:12:25 -05002108 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002109
2110 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002111 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002112 if (tcp_ses)
2113 return tcp_ses;
2114
2115 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2116 if (!tcp_ses) {
2117 rc = -ENOMEM;
2118 goto out_err;
2119 }
2120
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002121 rc = cifs_crypto_shash_allocate(tcp_ses);
2122 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002123 cifs_dbg(VFS, "could not setup hash structures rc %d\n", rc);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002124 goto out_err;
2125 }
2126
Jeff Layton23db65f2012-05-15 12:20:51 -04002127 tcp_ses->ops = volume_info->ops;
2128 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002129 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002130 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2131 if (IS_ERR(tcp_ses->hostname)) {
2132 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002133 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002134 }
2135
2136 tcp_ses->noblocksnd = volume_info->noblocksnd;
2137 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002138 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002139 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002140 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002141 init_waitqueue_head(&tcp_ses->response_q);
2142 init_waitqueue_head(&tcp_ses->request_q);
2143 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2144 mutex_init(&tcp_ses->srv_mutex);
2145 memcpy(tcp_ses->workstation_RFC1001_name,
2146 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2147 memcpy(tcp_ses->server_RFC1001_name,
2148 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002149 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002150 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002151 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002152 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002153 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2154 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002155 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002156 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2157 sizeof(tcp_ses->srcaddr));
2158 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2159 sizeof(tcp_ses->dstaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002160 /*
2161 * at this point we are the only ones with the pointer
2162 * to the struct since the kernel thread not created yet
2163 * no need to spinlock this init of tcpStatus or srv_count
2164 */
2165 tcp_ses->tcpStatus = CifsNew;
2166 ++tcp_ses->srv_count;
2167
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002168 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002169 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002170 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002171 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002172 }
2173
2174 /*
2175 * since we're in a cifs function already, we know that
2176 * this will succeed. No need for try_module_get().
2177 */
2178 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002179 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002180 tcp_ses, "cifsd");
2181 if (IS_ERR(tcp_ses->tsk)) {
2182 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002183 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002184 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002185 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002186 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002187 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002188
2189 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302190 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002191 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302192 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002193
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302194 cifs_fscache_get_client_cookie(tcp_ses);
2195
Jeff Laytonc74093b2011-01-11 07:24:23 -05002196 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002197 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002198
Jeff Layton63c038c2008-12-01 18:41:46 -05002199 return tcp_ses;
2200
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002201out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002202 cifs_crypto_shash_release(tcp_ses);
2203
Rob Landleyf1d0c992011-01-22 15:44:05 -06002204 put_net(cifs_net_ns(tcp_ses));
2205
Jeff Layton63c038c2008-12-01 18:41:46 -05002206out_err:
2207 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002208 if (!IS_ERR(tcp_ses->hostname))
2209 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002210 if (tcp_ses->ssocket)
2211 sock_release(tcp_ses->ssocket);
2212 kfree(tcp_ses);
2213 }
2214 return ERR_PTR(rc);
2215}
2216
Steve French96daf2b2011-05-27 04:34:02 +00002217static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002218{
2219 switch (ses->server->secType) {
2220 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002221 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002222 return 0;
2223 break;
2224 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002225 /* NULL username means anonymous session */
2226 if (ses->user_name == NULL) {
2227 if (!vol->nullauth)
2228 return 0;
2229 break;
2230 }
2231
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002232 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002233 if (strncmp(ses->user_name,
2234 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002235 MAX_USERNAME_SIZE))
2236 return 0;
2237 if (strlen(vol->username) != 0 &&
2238 ses->password != NULL &&
2239 strncmp(ses->password,
2240 vol->password ? vol->password : "",
2241 MAX_PASSWORD_SIZE))
2242 return 0;
2243 }
2244 return 1;
2245}
2246
Steve French96daf2b2011-05-27 04:34:02 +00002247static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002248cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249{
Steve French96daf2b2011-05-27 04:34:02 +00002250 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302252 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002253 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002254 if (!match_session(ses, vol))
2255 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002256 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302257 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002258 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302260 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 return NULL;
2262}
2263
Jeff Layton14fbf502008-11-14 13:53:46 -05002264static void
Steve French96daf2b2011-05-27 04:34:02 +00002265cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002266{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04002267 unsigned int xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002268 struct TCP_Server_Info *server = ses->server;
2269
Joe Perchesf96637b2013-05-04 22:12:25 -05002270 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302271 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002272 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302273 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002274 return;
2275 }
2276
2277 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302278 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002279
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04002280 if (ses->status == CifsGood && server->ops->logoff) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002281 xid = get_xid();
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04002282 server->ops->logoff(xid, ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002283 _free_xid(xid);
Jeff Layton14fbf502008-11-14 13:53:46 -05002284 }
2285 sesInfoFree(ses);
2286 cifs_put_tcp_session(server);
2287}
2288
Jeff Layton8a8798a2012-01-17 16:09:15 -05002289#ifdef CONFIG_KEYS
2290
2291/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2292#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2293
2294/* Populate username and pw fields from keyring if possible */
2295static int
2296cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2297{
2298 int rc = 0;
2299 char *desc, *delim, *payload;
2300 ssize_t len;
2301 struct key *key;
2302 struct TCP_Server_Info *server = ses->server;
2303 struct sockaddr_in *sa;
2304 struct sockaddr_in6 *sa6;
2305 struct user_key_payload *upayload;
2306
2307 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2308 if (!desc)
2309 return -ENOMEM;
2310
2311 /* try to find an address key first */
2312 switch (server->dstaddr.ss_family) {
2313 case AF_INET:
2314 sa = (struct sockaddr_in *)&server->dstaddr;
2315 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2316 break;
2317 case AF_INET6:
2318 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2319 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2320 break;
2321 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002322 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2323 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002324 rc = -EINVAL;
2325 goto out_err;
2326 }
2327
Joe Perchesf96637b2013-05-04 22:12:25 -05002328 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002329 key = request_key(&key_type_logon, desc, "");
2330 if (IS_ERR(key)) {
2331 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002332 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002333 rc = PTR_ERR(key);
2334 goto out_err;
2335 }
2336
2337 /* didn't work, try to find a domain key */
2338 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002339 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002340 key = request_key(&key_type_logon, desc, "");
2341 if (IS_ERR(key)) {
2342 rc = PTR_ERR(key);
2343 goto out_err;
2344 }
2345 }
2346
2347 down_read(&key->sem);
2348 upayload = key->payload.data;
2349 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002350 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002351 goto out_key_put;
2352 }
2353
2354 /* find first : in payload */
2355 payload = (char *)upayload->data;
2356 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002357 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002358 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002359 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2360 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002361 rc = -EINVAL;
2362 goto out_key_put;
2363 }
2364
2365 len = delim - payload;
2366 if (len > MAX_USERNAME_SIZE || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002367 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2368 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002369 rc = -EINVAL;
2370 goto out_key_put;
2371 }
2372
2373 vol->username = kstrndup(payload, len, GFP_KERNEL);
2374 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002375 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2376 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002377 rc = -ENOMEM;
2378 goto out_key_put;
2379 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002380 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002381
2382 len = key->datalen - (len + 1);
2383 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002384 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002385 rc = -EINVAL;
2386 kfree(vol->username);
2387 vol->username = NULL;
2388 goto out_key_put;
2389 }
2390
2391 ++delim;
2392 vol->password = kstrndup(delim, len, GFP_KERNEL);
2393 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002394 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2395 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002396 rc = -ENOMEM;
2397 kfree(vol->username);
2398 vol->username = NULL;
2399 goto out_key_put;
2400 }
2401
2402out_key_put:
2403 up_read(&key->sem);
2404 key_put(key);
2405out_err:
2406 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002407 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002408 return rc;
2409}
2410#else /* ! CONFIG_KEYS */
2411static inline int
2412cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2413 struct cifs_ses *ses __attribute__((unused)))
2414{
2415 return -ENOSYS;
2416}
2417#endif /* CONFIG_KEYS */
2418
Steve French96daf2b2011-05-27 04:34:02 +00002419static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002420cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2421{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002422 int rc = -ENOMEM;
2423 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002424 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002425 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2426 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002427
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002428 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002429
Jeff Layton4ff67b72010-07-06 20:43:02 -04002430 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002431 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002432 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2433 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002434
Jeff Layton36988c72010-04-24 07:57:43 -04002435 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002436 rc = cifs_negotiate_protocol(xid, ses);
2437 if (rc) {
2438 mutex_unlock(&ses->session_mutex);
2439 /* problem -- put our ses reference */
2440 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002441 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002442 return ERR_PTR(rc);
2443 }
Jeff Layton36988c72010-04-24 07:57:43 -04002444 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002445 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002446 rc = cifs_setup_session(xid, ses,
2447 volume_info->local_nls);
2448 if (rc) {
2449 mutex_unlock(&ses->session_mutex);
2450 /* problem -- put our reference */
2451 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002452 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002453 return ERR_PTR(rc);
2454 }
2455 }
2456 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002457
2458 /* existing SMB ses has a server reference already */
2459 cifs_put_tcp_session(server);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002460 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002461 return ses;
2462 }
2463
Joe Perchesf96637b2013-05-04 22:12:25 -05002464 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002465 ses = sesInfoAlloc();
2466 if (ses == NULL)
2467 goto get_ses_fail;
2468
2469 /* new SMB session uses our server ref */
2470 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002471 if (server->dstaddr.ss_family == AF_INET6)
2472 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002473 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002474 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002475
Steve French8727c8a2011-02-25 01:11:56 -06002476 if (volume_info->username) {
2477 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2478 if (!ses->user_name)
2479 goto get_ses_fail;
2480 }
Jeff Layton36988c72010-04-24 07:57:43 -04002481
2482 /* volume_info->password freed at unmount */
2483 if (volume_info->password) {
2484 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2485 if (!ses->password)
2486 goto get_ses_fail;
2487 }
2488 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002489 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2490 if (!ses->domainName)
2491 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002492 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002493 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002494 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002495
Jeff Layton36988c72010-04-24 07:57:43 -04002496 ses->overrideSecFlg = volume_info->secFlg;
2497
2498 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002499 rc = cifs_negotiate_protocol(xid, ses);
2500 if (!rc)
2501 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002502 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002503 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002504 goto get_ses_fail;
2505
2506 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302507 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002508 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302509 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002510
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002511 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002512 return ses;
2513
2514get_ses_fail:
2515 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002516 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002517 return ERR_PTR(rc);
2518}
2519
Steve French96daf2b2011-05-27 04:34:02 +00002520static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002521{
2522 if (tcon->tidStatus == CifsExiting)
2523 return 0;
2524 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2525 return 0;
2526 return 1;
2527}
2528
Steve French96daf2b2011-05-27 04:34:02 +00002529static struct cifs_tcon *
2530cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531{
2532 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002533 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302535 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002536 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002537 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002538 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002539 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002540 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302541 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 return tcon;
2543 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302544 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 return NULL;
2546}
2547
Jeff Laytonf1987b42008-11-15 11:12:47 -05002548static void
Steve French96daf2b2011-05-27 04:34:02 +00002549cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002550{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002551 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002552 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002553
Joe Perchesf96637b2013-05-04 22:12:25 -05002554 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302555 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002556 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302557 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002558 return;
2559 }
2560
2561 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302562 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002563
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002564 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002565 if (ses->server->ops->tree_disconnect)
2566 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002567 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002568
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302569 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002570 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002571 cifs_put_smb_ses(ses);
2572}
2573
Steve French96daf2b2011-05-27 04:34:02 +00002574static struct cifs_tcon *
2575cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002576{
2577 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002578 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002579
2580 tcon = cifs_find_tcon(ses, volume_info->UNC);
2581 if (tcon) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002582 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002583 /* existing tcon already has a reference */
2584 cifs_put_smb_ses(ses);
2585 if (tcon->seal != volume_info->seal)
Joe Perchesf96637b2013-05-04 22:12:25 -05002586 cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002587 return tcon;
2588 }
2589
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002590 if (!ses->server->ops->tree_connect) {
2591 rc = -ENOSYS;
2592 goto out_fail;
2593 }
2594
Jeff Laytond00c28d2010-04-24 07:57:44 -04002595 tcon = tconInfoAlloc();
2596 if (tcon == NULL) {
2597 rc = -ENOMEM;
2598 goto out_fail;
2599 }
2600
2601 tcon->ses = ses;
2602 if (volume_info->password) {
2603 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2604 if (!tcon->password) {
2605 rc = -ENOMEM;
2606 goto out_fail;
2607 }
2608 }
2609
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002610 /*
2611 * BB Do we need to wrap session_mutex around this TCon call and Unix
2612 * SetFS as we do on SessSetup and reconnect?
2613 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002614 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002615 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2616 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002617 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002618 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002619 if (rc)
2620 goto out_fail;
2621
2622 if (volume_info->nodfs) {
2623 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002624 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002625 }
2626 tcon->seal = volume_info->seal;
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002627 /*
2628 * We can have only one retry value for a connection to a share so for
2629 * resources mounted more than once to the same server share the last
2630 * value passed in for the retry flag is used.
2631 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04002632 tcon->retry = volume_info->retry;
2633 tcon->nocase = volume_info->nocase;
2634 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07002635 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002636
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302637 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002638 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302639 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002640
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302641 cifs_fscache_get_super_cookie(tcon);
2642
Jeff Laytond00c28d2010-04-24 07:57:44 -04002643 return tcon;
2644
2645out_fail:
2646 tconInfoFree(tcon);
2647 return ERR_PTR(rc);
2648}
2649
Jeff Layton9d002df2010-10-06 19:51:11 -04002650void
2651cifs_put_tlink(struct tcon_link *tlink)
2652{
2653 if (!tlink || IS_ERR(tlink))
2654 return;
2655
2656 if (!atomic_dec_and_test(&tlink->tl_count) ||
2657 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2658 tlink->tl_time = jiffies;
2659 return;
2660 }
2661
2662 if (!IS_ERR(tlink_tcon(tlink)))
2663 cifs_put_tcon(tlink_tcon(tlink));
2664 kfree(tlink);
2665 return;
2666}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002667
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002668static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002669cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2670{
2671 return cifs_sb->master_tlink;
2672}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002673
2674static int
2675compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2676{
2677 struct cifs_sb_info *old = CIFS_SB(sb);
2678 struct cifs_sb_info *new = mnt_data->cifs_sb;
2679
2680 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2681 return 0;
2682
2683 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2684 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2685 return 0;
2686
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002687 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002688 * We want to share sb only if we don't specify an r/wsize or
2689 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002690 */
2691 if (new->wsize && new->wsize < old->wsize)
2692 return 0;
2693
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002694 if (new->rsize && new->rsize < old->rsize)
2695 return 0;
2696
Eric W. Biederman1f682332013-02-06 01:20:20 -08002697 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002698 return 0;
2699
2700 if (old->mnt_file_mode != new->mnt_file_mode ||
2701 old->mnt_dir_mode != new->mnt_dir_mode)
2702 return 0;
2703
2704 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2705 return 0;
2706
2707 if (old->actimeo != new->actimeo)
2708 return 0;
2709
2710 return 1;
2711}
2712
2713int
2714cifs_match_super(struct super_block *sb, void *data)
2715{
2716 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2717 struct smb_vol *volume_info;
2718 struct cifs_sb_info *cifs_sb;
2719 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002720 struct cifs_ses *ses;
2721 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002722 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002723 int rc = 0;
2724
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002725 spin_lock(&cifs_tcp_ses_lock);
2726 cifs_sb = CIFS_SB(sb);
2727 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2728 if (IS_ERR(tlink)) {
2729 spin_unlock(&cifs_tcp_ses_lock);
2730 return rc;
2731 }
2732 tcon = tlink_tcon(tlink);
2733 ses = tcon->ses;
2734 tcp_srv = ses->server;
2735
2736 volume_info = mnt_data->vol;
2737
Jeff Layton9fa114f2012-11-26 11:09:57 -05002738 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002739 !match_session(ses, volume_info) ||
2740 !match_tcon(tcon, volume_info->UNC)) {
2741 rc = 0;
2742 goto out;
2743 }
2744
2745 rc = compare_mount_options(sb, mnt_data);
2746out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002747 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002748 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002749 return rc;
2750}
2751
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002753get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002754 const struct nls_table *nls_codepage, unsigned int *num_referrals,
2755 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756{
2757 char *temp_unc;
2758 int rc = 0;
2759
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002760 if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002761 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002763 *num_referrals = 0;
2764 *referrals = NULL;
2765
2766 if (ses->ipc_tid == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 temp_unc = kmalloc(2 /* for slashes */ +
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002768 strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
2769 + 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 if (temp_unc == NULL)
2771 return -ENOMEM;
2772 temp_unc[0] = '\\';
2773 temp_unc[1] = '\\';
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002774 strcpy(temp_unc + 2, ses->serverName);
2775 strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
2776 rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
2777 nls_codepage);
Joe Perchesf96637b2013-05-04 22:12:25 -05002778 cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 kfree(temp_unc);
2780 }
2781 if (rc == 0)
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002782 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
2783 referrals, num_referrals,
2784 nls_codepage, remap);
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002785 /*
2786 * BB - map targetUNCs to dfs_info3 structures, here or in
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002787 * ses->server->ops->get_dfs_refer.
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002788 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789
2790 return rc;
2791}
2792
Jeff Layton09e50d52008-07-23 10:11:19 -04002793#ifdef CONFIG_DEBUG_LOCK_ALLOC
2794static struct lock_class_key cifs_key[2];
2795static struct lock_class_key cifs_slock_key[2];
2796
2797static inline void
2798cifs_reclassify_socket4(struct socket *sock)
2799{
2800 struct sock *sk = sock->sk;
2801 BUG_ON(sock_owned_by_user(sk));
2802 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2803 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2804}
2805
2806static inline void
2807cifs_reclassify_socket6(struct socket *sock)
2808{
2809 struct sock *sk = sock->sk;
2810 BUG_ON(sock_owned_by_user(sk));
2811 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2812 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2813}
2814#else
2815static inline void
2816cifs_reclassify_socket4(struct socket *sock)
2817{
2818}
2819
2820static inline void
2821cifs_reclassify_socket6(struct socket *sock)
2822{
2823}
2824#endif
2825
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002827static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828{
Steve French50c2f752007-07-13 00:33:32 +00002829 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
Steve French50c2f752007-07-13 00:33:32 +00002831 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 /* mask a nibble at a time and encode */
2833 target[j] = 'A' + (0x0F & (source[i] >> 4));
2834 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002835 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 }
2837
2838}
2839
Ben Greear3eb9a882010-09-01 17:06:02 -07002840static int
2841bind_socket(struct TCP_Server_Info *server)
2842{
2843 int rc = 0;
2844 if (server->srcaddr.ss_family != AF_UNSPEC) {
2845 /* Bind to the specified local IP address */
2846 struct socket *socket = server->ssocket;
2847 rc = socket->ops->bind(socket,
2848 (struct sockaddr *) &server->srcaddr,
2849 sizeof(server->srcaddr));
2850 if (rc < 0) {
2851 struct sockaddr_in *saddr4;
2852 struct sockaddr_in6 *saddr6;
2853 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2854 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2855 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05002856 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
2857 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002858 else
Joe Perchesf96637b2013-05-04 22:12:25 -05002859 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
2860 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002861 }
2862 }
2863 return rc;
2864}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865
2866static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002867ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868{
2869 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002870 /*
2871 * some servers require RFC1001 sessinit before sending
2872 * negprot - BB check reconnection in case where second
2873 * sessinit is sent but no second negprot
2874 */
2875 struct rfc1002_session_packet *ses_init_buf;
2876 struct smb_hdr *smb_buf;
2877 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2878 GFP_KERNEL);
2879 if (ses_init_buf) {
2880 ses_init_buf->trailer.session_req.called_len = 32;
2881
2882 if (server->server_RFC1001_name &&
2883 server->server_RFC1001_name[0] != 0)
2884 rfc1002mangle(ses_init_buf->trailer.
2885 session_req.called_name,
2886 server->server_RFC1001_name,
2887 RFC1001_NAME_LEN_WITH_NULL);
2888 else
2889 rfc1002mangle(ses_init_buf->trailer.
2890 session_req.called_name,
2891 DEFAULT_CIFS_CALLED_NAME,
2892 RFC1001_NAME_LEN_WITH_NULL);
2893
2894 ses_init_buf->trailer.session_req.calling_len = 32;
2895
2896 /*
2897 * calling name ends in null (byte 16) from old smb
2898 * convention.
2899 */
2900 if (server->workstation_RFC1001_name &&
2901 server->workstation_RFC1001_name[0] != 0)
2902 rfc1002mangle(ses_init_buf->trailer.
2903 session_req.calling_name,
2904 server->workstation_RFC1001_name,
2905 RFC1001_NAME_LEN_WITH_NULL);
2906 else
2907 rfc1002mangle(ses_init_buf->trailer.
2908 session_req.calling_name,
2909 "LINUX_CIFS_CLNT",
2910 RFC1001_NAME_LEN_WITH_NULL);
2911
2912 ses_init_buf->trailer.session_req.scope1 = 0;
2913 ses_init_buf->trailer.session_req.scope2 = 0;
2914 smb_buf = (struct smb_hdr *)ses_init_buf;
2915
2916 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00002917 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002918 rc = smb_send(server, smb_buf, 0x44);
2919 kfree(ses_init_buf);
2920 /*
2921 * RFC1001 layer in at least one server
2922 * requires very short break before negprot
2923 * presumably because not expecting negprot
2924 * to follow so fast. This is a simple
2925 * solution that works without
2926 * complicating the code and causes no
2927 * significant slowing down on mount
2928 * for everyone else
2929 */
2930 usleep_range(1000, 2000);
2931 }
2932 /*
2933 * else the negprot may still work without this
2934 * even though malloc failed
2935 */
2936
2937 return rc;
2938}
2939
2940static int
2941generic_ip_connect(struct TCP_Server_Info *server)
2942{
2943 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00002944 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002945 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002946 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002947 struct sockaddr *saddr;
2948
2949 saddr = (struct sockaddr *) &server->dstaddr;
2950
2951 if (server->dstaddr.ss_family == AF_INET6) {
2952 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
2953 slen = sizeof(struct sockaddr_in6);
2954 sfamily = AF_INET6;
2955 } else {
2956 sport = ((struct sockaddr_in *) saddr)->sin_port;
2957 slen = sizeof(struct sockaddr_in);
2958 sfamily = AF_INET;
2959 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002961 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06002962 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
2963 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002965 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002966 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002969
2970 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05002971 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002972 server->ssocket = socket;
2973 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002974 if (sfamily == AF_INET6)
2975 cifs_reclassify_socket6(socket);
2976 else
2977 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 }
2979
Ben Greear3eb9a882010-09-01 17:06:02 -07002980 rc = bind_socket(server);
2981 if (rc < 0)
2982 return rc;
2983
Jeff Laytond5c56052008-12-01 18:42:33 -05002984 /*
2985 * Eventually check for other socket options to change from
2986 * the default. sock_setsockopt not used because it expects
2987 * user space buffer
2988 */
2989 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00002990 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00002991
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002992 /* make the bufsizes depend on wsize/rsize and max requests */
2993 if (server->noautotune) {
2994 if (socket->sk->sk_sndbuf < (200 * 1024))
2995 socket->sk->sk_sndbuf = 200 * 1024;
2996 if (socket->sk->sk_rcvbuf < (140 * 1024))
2997 socket->sk->sk_rcvbuf = 140 * 1024;
2998 }
2999
Steve French6a5fa2362010-01-01 01:28:43 +00003000 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003001 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003002 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3003 (char *)&val, sizeof(val));
3004 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003005 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3006 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003007 }
3008
Joe Perchesf96637b2013-05-04 22:12:25 -05003009 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003010 socket->sk->sk_sndbuf,
3011 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3012
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003013 rc = socket->ops->connect(socket, saddr, slen, 0);
3014 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003015 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003016 sock_release(socket);
3017 server->ssocket = NULL;
3018 return rc;
3019 }
3020
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003021 if (sport == htons(RFC1001_PORT))
3022 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003023
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 return rc;
3025}
3026
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003027static int
3028ip_connect(struct TCP_Server_Info *server)
3029{
Steve French6da97912011-03-13 18:55:55 +00003030 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003031 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3032 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3033
3034 if (server->dstaddr.ss_family == AF_INET6)
3035 sport = &addr6->sin6_port;
3036 else
3037 sport = &addr->sin_port;
3038
3039 if (*sport == 0) {
3040 int rc;
3041
3042 /* try with 445 port at first */
3043 *sport = htons(CIFS_PORT);
3044
3045 rc = generic_ip_connect(server);
3046 if (rc >= 0)
3047 return rc;
3048
3049 /* if it failed, try with 139 port */
3050 *sport = htons(RFC1001_PORT);
3051 }
3052
3053 return generic_ip_connect(server);
3054}
3055
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003056void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003057 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003058{
3059 /* if we are reconnecting then should we check to see if
3060 * any requested capabilities changed locally e.g. via
3061 * remount but we can not do much about it here
3062 * if they have (even if we could detect it by the following)
3063 * Perhaps we could add a backpointer to array of sb from tcon
3064 * or if we change to make all sb to same share the same
3065 * sb as NFS - then we only have one backpointer to sb.
3066 * What if we wanted to mount the server share twice once with
3067 * and once without posixacls or posix paths? */
3068 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003069
Steve Frenchc18c8422007-07-18 23:21:09 +00003070 if (vol_info && vol_info->no_linux_ext) {
3071 tcon->fsUnixInfo.Capability = 0;
3072 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003073 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003074 return;
3075 } else if (vol_info)
3076 tcon->unix_ext = 1; /* Unix Extensions supported */
3077
3078 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003079 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003080 return;
3081 }
Steve French50c2f752007-07-13 00:33:32 +00003082
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003083 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003084 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003085 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003086 /* check for reconnect case in which we do not
3087 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003088 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003089 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003090 originally at mount time */
3091 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3092 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003093 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3094 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003095 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003096 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003097 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003098 cifs_dbg(VFS, "possible reconnect error\n");
3099 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003100 }
Steve French8af18972007-02-14 04:42:51 +00003101 }
Steve French50c2f752007-07-13 00:33:32 +00003102
Steve French6848b732011-05-26 18:38:54 +00003103 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003104 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003105
Steve French8af18972007-02-14 04:42:51 +00003106 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003107 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003108 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003109 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003110 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003111 if (cifs_sb)
3112 cifs_sb->mnt_cifs_flags |=
3113 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003114 }
3115
Steve French75865f8c2007-06-24 18:30:48 +00003116 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003117 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003118 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003119 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003120 if (cifs_sb)
3121 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003122 CIFS_MOUNT_POSIX_PATHS;
3123 }
Steve French50c2f752007-07-13 00:33:32 +00003124
Joe Perchesf96637b2013-05-04 22:12:25 -05003125 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003126#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003127 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003128 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003129 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003130 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003131 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003132 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003133 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003134 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003135 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003136 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003137 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003138 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003139 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003140 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003141 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003142 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003143 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003144 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003145#endif /* CIFS_DEBUG2 */
3146 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003147 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003148 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003149 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003150 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 +00003151
Steve French8af18972007-02-14 04:42:51 +00003152 }
3153 }
3154}
3155
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003156void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3157 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003158{
Jeff Layton2de970f2010-10-06 19:51:12 -04003159 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3160
Al Viro2ced6f62011-06-17 09:20:04 -04003161 spin_lock_init(&cifs_sb->tlink_tree_lock);
3162 cifs_sb->tlink_tree = RB_ROOT;
3163
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003164 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003165 * Temporarily set r/wsize for matching superblock. If we end up using
3166 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003167 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003168 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003169 cifs_sb->wsize = pvolume_info->wsize;
3170
Steve French3b795212008-11-13 19:45:32 +00003171 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3172 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3173 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3174 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003175 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3176 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003177
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303178 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003179 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303180
Steve French3b795212008-11-13 19:45:32 +00003181 if (pvolume_info->noperm)
3182 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3183 if (pvolume_info->setuids)
3184 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3185 if (pvolume_info->server_ino)
3186 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3187 if (pvolume_info->remap)
3188 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3189 if (pvolume_info->no_xattr)
3190 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3191 if (pvolume_info->sfu_emul)
3192 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3193 if (pvolume_info->nobrl)
3194 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003195 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003196 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003197 if (pvolume_info->mand_lock)
3198 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003199 if (pvolume_info->rwpidforward)
3200 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003201 if (pvolume_info->cifs_acl)
3202 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003203 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003204 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003205 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3206 }
3207 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003208 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003209 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3210 }
Steve French3b795212008-11-13 19:45:32 +00003211 if (pvolume_info->override_uid)
3212 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3213 if (pvolume_info->override_gid)
3214 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3215 if (pvolume_info->dynperm)
3216 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303217 if (pvolume_info->fsc)
3218 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003219 if (pvolume_info->multiuser)
3220 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3221 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003222 if (pvolume_info->strict_io)
3223 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003224 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003225 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003226 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3227 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003228 if (pvolume_info->mfsymlinks) {
3229 if (pvolume_info->sfu_emul) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003230 cifs_dbg(VFS, "mount option mfsymlinks ignored if sfu mount option is used\n");
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003231 } else {
3232 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3233 }
3234 }
Steve French3b795212008-11-13 19:45:32 +00003235
3236 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003237 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003238}
3239
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003240static void
3241cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003242{
Sean Finneyb9468452011-04-11 13:19:32 +00003243 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003244 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003245 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003246 kfree(volume_info->domainname);
3247 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003248 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003249}
3250
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003251void
3252cifs_cleanup_volume_info(struct smb_vol *volume_info)
3253{
3254 if (!volume_info)
3255 return;
3256 cleanup_volume_info_contents(volume_info);
3257 kfree(volume_info);
3258}
3259
3260
Steve French2d6d5892009-04-09 00:36:44 +00003261#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003262/*
3263 * cifs_build_path_to_root returns full path to root when we do not have an
3264 * exiting connection (tcon)
3265 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003266static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003267build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003268 const struct cifs_sb_info *cifs_sb)
3269{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003270 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003271 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003272 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003273
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003274 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003275 if (full_path == NULL)
3276 return ERR_PTR(-ENOMEM);
3277
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003278 strncpy(full_path, vol->UNC, unc_len);
3279 pos = full_path + unc_len;
3280
3281 if (pplen) {
Jeff Layton839db3d2012-12-10 06:10:45 -05003282 *pos++ = CIFS_DIR_SEP(cifs_sb);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003283 strncpy(pos, vol->prepath, pplen);
3284 pos += pplen;
3285 }
3286
3287 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003288 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003289 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003290 return full_path;
3291}
Sean Finneydd613942011-04-11 13:19:30 +00003292
3293/*
3294 * Perform a dfs referral query for a share and (optionally) prefix
3295 *
Sean Finney046462a2011-04-11 13:19:33 +00003296 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3297 * to a string containing updated options for the submount. Otherwise it
3298 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003299 *
3300 * Returns the rc from get_dfs_path to the caller, which can be used to
3301 * determine whether there were referrals.
3302 */
3303static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003304expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003305 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003306 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003307{
3308 int rc;
3309 unsigned int num_referrals = 0;
3310 struct dfs_info3_param *referrals = NULL;
3311 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3312
3313 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3314 if (IS_ERR(full_path))
3315 return PTR_ERR(full_path);
3316
3317 /* For DFS paths, skip the first '\' of the UNC */
3318 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3319
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003320 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Sean Finneydd613942011-04-11 13:19:30 +00003321 &num_referrals, &referrals,
3322 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3323
3324 if (!rc && num_referrals > 0) {
3325 char *fake_devname = NULL;
3326
3327 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3328 full_path + 1, referrals,
3329 &fake_devname);
3330
3331 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003332
Sean Finneydd613942011-04-11 13:19:30 +00003333 if (IS_ERR(mdata)) {
3334 rc = PTR_ERR(mdata);
3335 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003336 } else {
3337 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003338 rc = cifs_setup_volume_info(volume_info, mdata,
3339 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003340 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003341 kfree(fake_devname);
3342 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003343 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003344 }
3345 kfree(full_path);
3346 return rc;
3347}
Steve French2d6d5892009-04-09 00:36:44 +00003348#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003349
Jeff Layton04db79b2011-07-06 08:10:38 -04003350static int
3351cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3352 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003354 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003355
Jeff Layton04db79b2011-07-06 08:10:38 -04003356 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3357 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358
Jeff Layton7586b762008-12-01 18:41:49 -05003359 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003360 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003361 kfree(volume_info->username);
3362 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003363 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003365 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003367 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003368 /* In userspace mount helper we can get user name from alternate
3369 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003370 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 }
3372
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003374 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003375 /* load_nls_default cannot return null */
3376 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003378 volume_info->local_nls = load_nls(volume_info->iocharset);
3379 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003380 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003381 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003382 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 }
3384 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003385
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003386 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003387}
3388
3389struct smb_vol *
3390cifs_get_volume_info(char *mount_data, const char *devname)
3391{
3392 int rc;
3393 struct smb_vol *volume_info;
3394
Jeff Layton6ee95422012-11-26 11:09:57 -05003395 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003396 if (!volume_info)
3397 return ERR_PTR(-ENOMEM);
3398
3399 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3400 if (rc) {
3401 cifs_cleanup_volume_info(volume_info);
3402 volume_info = ERR_PTR(rc);
3403 }
3404
3405 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003406}
3407
3408int
Al Viro2c6292a2011-06-17 09:05:48 -04003409cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003410{
Jeff Layton1daaae82012-03-21 06:30:40 -04003411 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003412 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003413 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003414 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003415 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003416 char *full_path;
3417 struct tcon_link *tlink;
3418#ifdef CONFIG_CIFS_DFS_UPCALL
3419 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003420#endif
Al Virodd854462011-06-17 08:24:42 -04003421
3422 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3423 if (rc)
3424 return rc;
3425
Jeff Layton20547492011-07-09 12:21:07 -04003426#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003427try_mount_again:
3428 /* cleanup activities if we're chasing a referral */
3429 if (referral_walks_count) {
3430 if (tcon)
3431 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003432 else if (ses)
3433 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003434
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003435 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003436 }
3437#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003438 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003439 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003440 ses = NULL;
3441 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003442 full_path = NULL;
3443 tlink = NULL;
3444
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003445 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446
Jeff Layton63c038c2008-12-01 18:41:46 -05003447 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003448 server = cifs_get_tcp_session(volume_info);
3449 if (IS_ERR(server)) {
3450 rc = PTR_ERR(server);
Al Virodd854462011-06-17 08:24:42 -04003451 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003452 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 }
3454
Jeff Layton36988c72010-04-24 07:57:43 -04003455 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003456 ses = cifs_get_smb_ses(server, volume_info);
3457 if (IS_ERR(ses)) {
3458 rc = PTR_ERR(ses);
3459 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003460 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 }
Steve French50c2f752007-07-13 00:33:32 +00003462
Jeff Laytond00c28d2010-04-24 07:57:44 -04003463 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003464 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003465 if (IS_ERR(tcon)) {
3466 rc = PTR_ERR(tcon);
3467 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003468 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003469 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003470
Steve French6848b732011-05-26 18:38:54 +00003471 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003472 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003473 /* reset of caps checks mount to see if unix extensions
3474 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003475 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003476 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3477 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3478 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3479 rc = -EACCES;
3480 goto mount_fail_check;
3481 }
3482 } else
3483 tcon->unix_ext = 0; /* server does not support them */
3484
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003485 /* do not care if a following call succeed - informational */
3486 if (!tcon->ipc && server->ops->qfs_tcon)
3487 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003488
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003489 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3490 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003491
Jeff Layton66bfaad2011-10-19 15:30:35 -04003492 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003493 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003494
Igor Mammedove4cce942009-02-10 14:10:26 +03003495remote_path_check:
3496#ifdef CONFIG_CIFS_DFS_UPCALL
3497 /*
3498 * Perform an unconditional check for whether there are DFS
3499 * referrals for this path without prefix, to provide support
3500 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003501 * with PATH_NOT_COVERED to requests that include the prefix.
3502 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003503 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003504 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003505 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3506 false);
Steve Frencheeac8042006-01-13 21:34:58 -08003507 if (!refrc) {
Steve French4523cc32007-04-30 20:13:06 +00003508 referral_walks_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 goto try_mount_again;
3510 }
3511 }
3512#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003513
Steve Frenchf87d39d2011-05-27 03:50:55 +00003514 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003516 if (!server->ops->is_path_accessible) {
3517 rc = -ENOSYS;
3518 goto mount_fail_check;
3519 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003520 /*
3521 * cifs_build_path_to_root works only when we have a valid tcon
3522 */
3523 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 if (full_path == NULL) {
3525 rc = -ENOMEM;
3526 goto mount_fail_check;
3527 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003528 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3529 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530 if (rc != 0 && rc != -EREMOTE) {
3531 kfree(full_path);
3532 goto mount_fail_check;
3533 }
3534 kfree(full_path);
3535 }
3536
3537 /* get referral if needed */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003538 if (rc == -EREMOTE) {
3539#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003540 if (referral_walks_count > MAX_NESTED_LINKS) {
3541 /*
3542 * BB: when we implement proper loop detection,
3543 * we will remove this check. But now we need it
3544 * to prevent an indefinite loop if 'DFS tree' is
3545 * misconfigured (i.e. has loops).
3546 */
3547 rc = -ELOOP;
3548 goto mount_fail_check;
3549 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003550
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003551 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003552
Sean Finneydd613942011-04-11 13:19:30 +00003553 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003554 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003555 goto try_mount_again;
3556 }
Sean Finneydd613942011-04-11 13:19:30 +00003557 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003558#else /* No DFS support, return error on mount */
3559 rc = -EOPNOTSUPP;
3560#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003561 }
3562
Jeff Layton9d002df2010-10-06 19:51:11 -04003563 if (rc)
3564 goto mount_fail_check;
3565
3566 /* now, hang the tcon off of the superblock */
3567 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3568 if (tlink == NULL) {
3569 rc = -ENOMEM;
3570 goto mount_fail_check;
3571 }
3572
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003573 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003574 tlink->tl_tcon = tcon;
3575 tlink->tl_time = jiffies;
3576 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3577 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3578
Jeff Layton413e6612010-10-28 13:33:38 -04003579 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003580 spin_lock(&cifs_sb->tlink_tree_lock);
3581 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3582 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003583
Jeff Laytonda472fc2012-03-23 14:40:53 -04003584 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003585 TLINK_IDLE_EXPIRE);
3586
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003587mount_fail_check:
3588 /* on error free sesinfo and tcon struct if needed */
3589 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003590 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003591 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003592 if (tcon)
3593 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003594 else if (ses)
3595 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003596 else
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003597 cifs_put_tcp_session(server);
Al Virodd854462011-06-17 08:24:42 -04003598 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003599 }
3600
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003602 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 return rc;
3604}
3605
Jeff Layton8d1bca32011-06-11 21:17:10 -04003606/*
3607 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3608 * pointer may be NULL.
3609 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003611CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00003612 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 const struct nls_table *nls_codepage)
3614{
3615 struct smb_hdr *smb_buffer;
3616 struct smb_hdr *smb_buffer_response;
3617 TCONX_REQ *pSMB;
3618 TCONX_RSP *pSMBr;
3619 unsigned char *bcc_ptr;
3620 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003621 int length;
3622 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623
3624 if (ses == NULL)
3625 return -EIO;
3626
3627 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003628 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003630
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 smb_buffer_response = smb_buffer;
3632
3633 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3634 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003635
Pavel Shilovsky88257362012-05-23 14:01:59 +04003636 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 smb_buffer->Uid = ses->Suid;
3638 pSMB = (TCONX_REQ *) smb_buffer;
3639 pSMBr = (TCONX_RSP *) smb_buffer_response;
3640
3641 pSMB->AndXCommand = 0xFF;
3642 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003644 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003645 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003646 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003647 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003648 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003649 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003650 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003651 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3652 specified as required (when that support is added to
3653 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003654 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003655 by Samba (not sure whether other servers allow
3656 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003657#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003658 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003659 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003660 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003661 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003662 SECMODE_PW_ENCRYPT ? true : false,
3663 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003664 else
3665#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003666 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003667 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003668
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003669 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003670 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003671 /* must align unicode strings */
3672 *bcc_ptr = 0; /* null byte password */
3673 bcc_ptr++;
3674 }
Steve Frencheeac8042006-01-13 21:34:58 -08003675 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676
Steve French96daf2b2011-05-27 04:34:02 +00003677 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003678 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3680
3681 if (ses->capabilities & CAP_STATUS32) {
3682 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3683 }
3684 if (ses->capabilities & CAP_DFS) {
3685 smb_buffer->Flags2 |= SMBFLG2_DFS;
3686 }
3687 if (ses->capabilities & CAP_UNICODE) {
3688 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3689 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003690 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003691 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003692 (/* server len*/ + 256 /* share len */), nls_codepage);
3693 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 bcc_ptr += 2; /* skip trailing null */
3695 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 strcpy(bcc_ptr, tree);
3697 bcc_ptr += strlen(tree) + 1;
3698 }
3699 strcpy(bcc_ptr, "?????");
3700 bcc_ptr += strlen("?????");
3701 bcc_ptr += 1;
3702 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003703 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3704 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 pSMB->ByteCount = cpu_to_le16(count);
3706
Steve French133672e2007-11-13 22:41:37 +00003707 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003708 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 /* above now done in SendReceive */
3711 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003712 bool is_unicode;
3713
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003715 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 tcon->tid = smb_buffer_response->Tid;
3717 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003718 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003719 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003720 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
3721 is_unicode = true;
3722 else
3723 is_unicode = false;
3724
Jeff Laytoncc20c032009-04-30 07:16:21 -04003725
Steve French50c2f752007-07-13 00:33:32 +00003726 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00003727 if (length == 3) {
3728 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3729 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003730 cifs_dbg(FYI, "IPC connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003731 tcon->ipc = 1;
3732 }
3733 } else if (length == 2) {
3734 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3735 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05003736 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003737 }
3738 }
Steve French50c2f752007-07-13 00:33:32 +00003739 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04003740 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003742
3743 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04003744 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06003745 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00003746 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04003747 nls_codepage);
3748
Joe Perchesf96637b2013-05-04 22:12:25 -05003749 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003750
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003751 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00003752 (smb_buffer_response->WordCount == 7))
3753 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00003754 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3755 else
3756 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05003757 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003759 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 ses->ipc_tid = smb_buffer_response->Tid;
3761 }
3762
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00003763 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 return rc;
3765}
3766
Al Viro2a9b9952011-06-17 09:27:16 -04003767void
3768cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769{
Jeff Laytonb647c352010-10-28 11:16:44 -04003770 struct rb_root *root = &cifs_sb->tlink_tree;
3771 struct rb_node *node;
3772 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773
Jeff Layton2de970f2010-10-06 19:51:12 -04003774 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
3775
Jeff Laytonb647c352010-10-28 11:16:44 -04003776 spin_lock(&cifs_sb->tlink_tree_lock);
3777 while ((node = rb_first(root))) {
3778 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3779 cifs_get_tlink(tlink);
3780 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3781 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00003782
Jeff Laytonb647c352010-10-28 11:16:44 -04003783 spin_unlock(&cifs_sb->tlink_tree_lock);
3784 cifs_put_tlink(tlink);
3785 spin_lock(&cifs_sb->tlink_tree_lock);
3786 }
3787 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003788
Al Virodd854462011-06-17 08:24:42 -04003789 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04003790 kfree(cifs_sb->mountdata);
3791 unload_nls(cifs_sb->local_nls);
3792 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00003793}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003795int
3796cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797{
3798 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04003799 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003801 if (!server->ops->need_neg || !server->ops->negotiate)
3802 return -ENOSYS;
3803
Jeff Layton198b5682010-04-24 07:57:48 -04003804 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003805 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04003806 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
Pavel Shilovsky45275782012-05-17 17:53:29 +04003808 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003809
3810 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04003811 if (rc == 0) {
3812 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04003813 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04003814 server->tcpStatus = CifsGood;
3815 else
3816 rc = -EHOSTDOWN;
3817 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818 }
Steve French26b994f2008-08-06 05:11:33 +00003819
Jeff Layton198b5682010-04-24 07:57:48 -04003820 return rc;
3821}
Steve French26b994f2008-08-06 05:11:33 +00003822
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003823int
3824cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
3825 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04003826{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003827 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04003828 struct TCP_Server_Info *server = ses->server;
3829
3830 ses->flags = 0;
3831 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00003832 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003833 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00003834
Joe Perchesf96637b2013-05-04 22:12:25 -05003835 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00003836 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04003837
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003838 if (server->ops->sess_setup)
3839 rc = server->ops->sess_setup(xid, ses, nls_info);
3840
Steve French26b994f2008-08-06 05:11:33 +00003841 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003842 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Steve French26b994f2008-08-06 05:11:33 +00003843 } else {
Dan Carpenterb13ce4b2013-04-10 14:43:00 +03003844 mutex_lock(&server->srv_mutex);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003845 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003846 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003847 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003848 server->sequence_number = 0x2;
3849 server->session_estab = true;
3850 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003851 }
3852 mutex_unlock(&server->srv_mutex);
3853
Joe Perchesf96637b2013-05-04 22:12:25 -05003854 cifs_dbg(FYI, "CIFS Session Established successfully\n");
Steve French20418ac2009-04-30 16:13:32 +00003855 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04003856 ses->status = CifsGood;
3857 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00003858 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00003859 }
3860
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003861 kfree(ses->auth_key.response);
3862 ses->auth_key.response = NULL;
3863 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003864 kfree(ses->ntlmssp);
3865 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003866
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 return rc;
3868}
3869
Jeff Layton8a8798a2012-01-17 16:09:15 -05003870static int
3871cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
3872{
3873 switch (ses->server->secType) {
3874 case Kerberos:
3875 vol->secFlg = CIFSSEC_MUST_KRB5;
3876 return 0;
3877 case NTLMv2:
3878 vol->secFlg = CIFSSEC_MUST_NTLMV2;
3879 break;
3880 case NTLM:
3881 vol->secFlg = CIFSSEC_MUST_NTLM;
3882 break;
3883 case RawNTLMSSP:
3884 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
3885 break;
3886 case LANMAN:
3887 vol->secFlg = CIFSSEC_MUST_LANMAN;
3888 break;
3889 }
3890
3891 return cifs_set_cifscreds(vol, ses);
3892}
3893
Steve French96daf2b2011-05-27 04:34:02 +00003894static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003895cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04003896{
Jeff Layton8a8798a2012-01-17 16:09:15 -05003897 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00003898 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
3899 struct cifs_ses *ses;
3900 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04003901 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04003902
3903 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03003904 if (vol_info == NULL)
3905 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04003906
Jeff Layton9d002df2010-10-06 19:51:11 -04003907 vol_info->local_nls = cifs_sb->local_nls;
3908 vol_info->linux_uid = fsuid;
3909 vol_info->cred_uid = fsuid;
3910 vol_info->UNC = master_tcon->treeName;
3911 vol_info->retry = master_tcon->retry;
3912 vol_info->nocase = master_tcon->nocase;
3913 vol_info->local_lease = master_tcon->local_lease;
3914 vol_info->no_linux_ext = !master_tcon->unix_ext;
3915
Jeff Layton8a8798a2012-01-17 16:09:15 -05003916 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
3917 if (rc) {
3918 tcon = ERR_PTR(rc);
3919 goto out;
3920 }
Jeff Layton9d002df2010-10-06 19:51:11 -04003921
3922 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303923 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003924 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303925 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003926
3927 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
3928 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00003929 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04003930 cifs_put_tcp_session(master_tcon->ses->server);
3931 goto out;
3932 }
3933
3934 tcon = cifs_get_tcon(ses, vol_info);
3935 if (IS_ERR(tcon)) {
3936 cifs_put_smb_ses(ses);
3937 goto out;
3938 }
3939
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003940 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04003941 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
3942out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05003943 kfree(vol_info->username);
3944 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04003945 kfree(vol_info);
3946
3947 return tcon;
3948}
3949
Steve French96daf2b2011-05-27 04:34:02 +00003950struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04003951cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
3952{
3953 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
3954}
3955
3956static int
3957cifs_sb_tcon_pending_wait(void *unused)
3958{
3959 schedule();
3960 return signal_pending(current) ? -ERESTARTSYS : 0;
3961}
3962
Jeff Laytonb647c352010-10-28 11:16:44 -04003963/* find and return a tlink with given uid */
3964static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003965tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04003966{
3967 struct rb_node *node = root->rb_node;
3968 struct tcon_link *tlink;
3969
3970 while (node) {
3971 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3972
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003973 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003974 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003975 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003976 node = node->rb_right;
3977 else
3978 return tlink;
3979 }
3980 return NULL;
3981}
3982
3983/* insert a tcon_link into the tree */
3984static void
3985tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
3986{
3987 struct rb_node **new = &(root->rb_node), *parent = NULL;
3988 struct tcon_link *tlink;
3989
3990 while (*new) {
3991 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
3992 parent = *new;
3993
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003994 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003995 new = &((*new)->rb_left);
3996 else
3997 new = &((*new)->rb_right);
3998 }
3999
4000 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4001 rb_insert_color(&new_tlink->tl_rbnode, root);
4002}
4003
Jeff Layton9d002df2010-10-06 19:51:11 -04004004/*
4005 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4006 * current task.
4007 *
4008 * If the superblock doesn't refer to a multiuser mount, then just return
4009 * the master tcon for the mount.
4010 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304011 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004012 * exists, then check to see if it's pending construction. If it is then wait
4013 * for construction to complete. Once it's no longer pending, check to see if
4014 * it failed and either return an error or retry construction, depending on
4015 * the timeout.
4016 *
4017 * If one doesn't exist then insert a new tcon_link struct into the tree and
4018 * try to construct a new one.
4019 */
4020struct tcon_link *
4021cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4022{
4023 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004024 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004025 struct tcon_link *tlink, *newtlink;
4026
4027 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4028 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4029
4030 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004031 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004032 if (tlink)
4033 cifs_get_tlink(tlink);
4034 spin_unlock(&cifs_sb->tlink_tree_lock);
4035
4036 if (tlink == NULL) {
4037 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4038 if (newtlink == NULL)
4039 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004040 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004041 newtlink->tl_tcon = ERR_PTR(-EACCES);
4042 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4043 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4044 cifs_get_tlink(newtlink);
4045
Jeff Layton9d002df2010-10-06 19:51:11 -04004046 spin_lock(&cifs_sb->tlink_tree_lock);
4047 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004048 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004049 if (tlink) {
4050 cifs_get_tlink(tlink);
4051 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004052 kfree(newtlink);
4053 goto wait_for_construction;
4054 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004055 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004056 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4057 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004058 } else {
4059wait_for_construction:
4060 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4061 cifs_sb_tcon_pending_wait,
4062 TASK_INTERRUPTIBLE);
4063 if (ret) {
4064 cifs_put_tlink(tlink);
4065 return ERR_PTR(ret);
4066 }
4067
4068 /* if it's good, return it */
4069 if (!IS_ERR(tlink->tl_tcon))
4070 return tlink;
4071
4072 /* return error if we tried this already recently */
4073 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4074 cifs_put_tlink(tlink);
4075 return ERR_PTR(-EACCES);
4076 }
4077
4078 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4079 goto wait_for_construction;
4080 }
4081
4082 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4083 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4084 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4085
4086 if (IS_ERR(tlink->tl_tcon)) {
4087 cifs_put_tlink(tlink);
4088 return ERR_PTR(-EACCES);
4089 }
4090
4091 return tlink;
4092}
Jeff Layton2de970f2010-10-06 19:51:12 -04004093
4094/*
4095 * periodic workqueue job that scans tcon_tree for a superblock and closes
4096 * out tcons.
4097 */
4098static void
4099cifs_prune_tlinks(struct work_struct *work)
4100{
4101 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4102 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004103 struct rb_root *root = &cifs_sb->tlink_tree;
4104 struct rb_node *node = rb_first(root);
4105 struct rb_node *tmp;
4106 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004107
Jeff Laytonb647c352010-10-28 11:16:44 -04004108 /*
4109 * Because we drop the spinlock in the loop in order to put the tlink
4110 * it's not guarded against removal of links from the tree. The only
4111 * places that remove entries from the tree are this function and
4112 * umounts. Because this function is non-reentrant and is canceled
4113 * before umount can proceed, this is safe.
4114 */
4115 spin_lock(&cifs_sb->tlink_tree_lock);
4116 node = rb_first(root);
4117 while (node != NULL) {
4118 tmp = node;
4119 node = rb_next(tmp);
4120 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4121
4122 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4123 atomic_read(&tlink->tl_count) != 0 ||
4124 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4125 continue;
4126
4127 cifs_get_tlink(tlink);
4128 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4129 rb_erase(tmp, root);
4130
Jeff Layton2de970f2010-10-06 19:51:12 -04004131 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004132 cifs_put_tlink(tlink);
4133 spin_lock(&cifs_sb->tlink_tree_lock);
4134 }
4135 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004136
Jeff Laytonda472fc2012-03-23 14:40:53 -04004137 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004138 TLINK_IDLE_EXPIRE);
4139}