blob: 0a7fdc31f253b59e85137ecd39dd4c17cd10547a [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 Laytond387a5c2012-12-10 06:10:46 -05001261 /*
1262 * For now, we ignore -EINVAL errors under the assumption that the
1263 * unc= and prefixpath= options will be usable.
1264 */
1265 if (cifs_parse_devname(devname, vol) == -ENOMEM) {
1266 printk(KERN_ERR "CIFS: Unable to allocate memory to parse "
1267 "device string.\n");
1268 goto out_nomem;
1269 }
1270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001272 substring_t args[MAX_OPT_ARGS];
1273 unsigned long option;
1274 int token;
1275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 if (!*data)
1277 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001279 token = match_token(data, cifs_mount_option_tokens, args);
1280
1281 switch (token) {
1282
1283 /* Ingnore the following */
1284 case Opt_ignore:
1285 break;
1286
1287 /* Boolean values */
1288 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001290 break;
1291 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001293 break;
1294 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001295 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001296 break;
1297 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001298 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001299 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001300 case Opt_forcegid:
1301 override_gid = 1;
1302 break;
1303 case Opt_noforcegid:
1304 override_gid = 0;
1305 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001306 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001307 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001308 break;
1309 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001310 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001311 break;
1312 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001314 break;
1315 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001317 break;
1318 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001320 break;
1321 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001323 break;
1324 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001325 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001326 break;
1327 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001328 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001329 break;
1330 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001331 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001332 break;
1333 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001334 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001335 break;
1336 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001337 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001338 break;
1339 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001340 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001341 break;
1342 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001343 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001344 break;
1345 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001346 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001347 break;
1348 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001349 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001350 break;
1351 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001352 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001353 break;
1354 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001355 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001356 /*
1357 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001358 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001359 * local vfs will do advisory
1360 */
Steve French50c2f752007-07-13 00:33:32 +00001361 if (vol->file_mode ==
1362 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001363 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001364 break;
1365 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001366 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001367 break;
1368 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001370 break;
1371 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001373 break;
1374 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001375 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001376 break;
1377 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001378 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001379 break;
1380 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001382 break;
1383 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001385 break;
1386 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001388 break;
1389 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001391 break;
1392 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001393 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001394 break;
1395 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001396 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001397 break;
1398 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001400 break;
1401 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001403 break;
1404 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001405 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001406 break;
1407 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001408 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001409 break;
1410 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001411 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001412 break;
1413 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001420 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001423 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
1425 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001426 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 * is a per tree connection (mount) not a per socket
1428 * or per-smb connection option in the protocol
1429 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1430 */
Steve French95b1cb92008-05-15 16:44:38 +00001431 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001432 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001434 printk(KERN_WARNING "CIFS: Mount option noac not "
1435 "supported. Instead set "
1436 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001437 break;
1438 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301439#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001440 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001441 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301442#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301443 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001444 break;
1445 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001446 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001447 break;
1448 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001449 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001450 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001451 case Opt_sloppy:
1452 sloppy = true;
1453 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001454
1455 /* Numeric Values */
1456 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001457 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001458 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1459 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001460 goto cifs_parse_mount_err;
1461 }
1462 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001463 break;
1464 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001465 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001466 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1467 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001468 goto cifs_parse_mount_err;
1469 }
1470 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001471 break;
1472 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001473 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001474 cifs_dbg(VFS, "%s: Invalid uid value\n",
1475 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001476 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001478 uid_specified = true;
1479 break;
1480 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001481 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001482 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1483 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001484 goto cifs_parse_mount_err;
1485 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001486 break;
1487 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001488 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001489 cifs_dbg(VFS, "%s: Invalid gid value\n",
1490 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001491 goto cifs_parse_mount_err;
1492 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001493 gid_specified = true;
1494 break;
1495 case Opt_file_mode:
1496 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001497 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
1498 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001499 goto cifs_parse_mount_err;
1500 }
1501 vol->file_mode = option;
1502 break;
1503 case Opt_dirmode:
1504 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001505 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
1506 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001507 goto cifs_parse_mount_err;
1508 }
1509 vol->dir_mode = option;
1510 break;
1511 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001512 if (get_option_ul(args, &option) ||
1513 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001514 cifs_dbg(VFS, "%s: Invalid port value\n",
1515 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001516 goto cifs_parse_mount_err;
1517 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001518 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001519 break;
1520 case Opt_rsize:
1521 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001522 cifs_dbg(VFS, "%s: Invalid rsize value\n",
1523 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001524 goto cifs_parse_mount_err;
1525 }
1526 vol->rsize = option;
1527 break;
1528 case Opt_wsize:
1529 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001530 cifs_dbg(VFS, "%s: Invalid wsize value\n",
1531 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001532 goto cifs_parse_mount_err;
1533 }
1534 vol->wsize = option;
1535 break;
1536 case Opt_actimeo:
1537 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001538 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
1539 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001540 goto cifs_parse_mount_err;
1541 }
1542 vol->actimeo = HZ * option;
1543 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001544 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001545 goto cifs_parse_mount_err;
1546 }
1547 break;
1548
1549 /* String Arguments */
1550
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001551 case Opt_blank_user:
1552 /* null user, ie. anonymous authentication */
1553 vol->nullauth = 1;
1554 vol->username = NULL;
1555 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001556 case Opt_user:
1557 string = match_strdup(args);
1558 if (string == NULL)
1559 goto out_nomem;
1560
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001561 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001562 MAX_USERNAME_SIZE) {
1563 printk(KERN_WARNING "CIFS: username too long\n");
1564 goto cifs_parse_mount_err;
1565 }
1566 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05001567 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001568 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001569 break;
1570 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001571 /* passwords have to be handled differently
1572 * to allow the character used for deliminator
1573 * to be passed within them
1574 */
1575
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01001576 /*
1577 * Check if this is a case where the password
1578 * starts with a delimiter
1579 */
1580 tmp_end = strchr(data, '=');
1581 tmp_end++;
1582 if (!(tmp_end < end && tmp_end[1] == delim)) {
1583 /* No it is not. Set the password to NULL */
1584 vol->password = NULL;
1585 break;
1586 }
1587 /* Yes it is. Drop down to Opt_pass below.*/
1588 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001589 /* Obtain the value string */
1590 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001591 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001592
1593 /* Set tmp_end to end of the string */
1594 tmp_end = (char *) value + strlen(value);
1595
1596 /* Check if following character is the deliminator
1597 * If yes, we have encountered a double deliminator
1598 * reset the NULL character to the deliminator
1599 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301600 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001601 tmp_end[0] = delim;
1602
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301603 /* Keep iterating until we get to a single
1604 * deliminator OR the end
1605 */
1606 while ((tmp_end = strchr(tmp_end, delim))
1607 != NULL && (tmp_end[1] == delim)) {
1608 tmp_end = (char *) &tmp_end[2];
1609 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001610
Suresh Jayaramane73f8432012-06-12 07:15:50 +05301611 /* Reset var options to point to next element */
1612 if (tmp_end) {
1613 tmp_end[0] = '\0';
1614 options = (char *) &tmp_end[1];
1615 } else
1616 /* Reached the end of the mount option
1617 * string */
1618 options = end;
1619 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001620
1621 /* Now build new password string */
1622 temp_len = strlen(value);
1623 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1624 if (vol->password == NULL) {
1625 printk(KERN_WARNING "CIFS: no memory "
1626 "for password\n");
1627 goto cifs_parse_mount_err;
1628 }
1629
1630 for (i = 0, j = 0; i < temp_len; i++, j++) {
1631 vol->password[j] = value[i];
1632 if ((value[i] == delim) &&
1633 value[i+1] == delim)
1634 /* skip the second deliminator */
1635 i++;
1636 }
1637 vol->password[j] = '\0';
1638 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001639 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001640 /* FIXME: should this be an error instead? */
1641 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001642 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001643 case Opt_ip:
1644 string = match_strdup(args);
1645 if (string == NULL)
1646 goto out_nomem;
1647
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001648 if (!cifs_convert_address(dstaddr, string,
1649 strlen(string))) {
1650 printk(KERN_ERR "CIFS: bad ip= option (%s).\n",
1651 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001652 goto cifs_parse_mount_err;
1653 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001654 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001655 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001656 case Opt_domain:
1657 string = match_strdup(args);
1658 if (string == NULL)
1659 goto out_nomem;
1660
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001661 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001662 printk(KERN_WARNING "CIFS: domain name too"
1663 " long\n");
1664 goto cifs_parse_mount_err;
1665 }
1666
1667 vol->domainname = kstrdup(string, GFP_KERNEL);
1668 if (!vol->domainname) {
1669 printk(KERN_WARNING "CIFS: no memory "
1670 "for domainname\n");
1671 goto cifs_parse_mount_err;
1672 }
Joe Perchesf96637b2013-05-04 22:12:25 -05001673 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001674 break;
1675 case Opt_srcaddr:
1676 string = match_strdup(args);
1677 if (string == NULL)
1678 goto out_nomem;
1679
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001680 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001681 (struct sockaddr *)&vol->srcaddr,
1682 string, strlen(string))) {
1683 printk(KERN_WARNING "CIFS: Could not parse"
1684 " srcaddr: %s\n", string);
1685 goto cifs_parse_mount_err;
1686 }
1687 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001688 case Opt_iocharset:
1689 string = match_strdup(args);
1690 if (string == NULL)
1691 goto out_nomem;
1692
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001693 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001694 printk(KERN_WARNING "CIFS: iocharset name "
1695 "too long.\n");
1696 goto cifs_parse_mount_err;
1697 }
1698
1699 if (strnicmp(string, "default", 7) != 0) {
1700 vol->iocharset = kstrdup(string,
1701 GFP_KERNEL);
1702 if (!vol->iocharset) {
1703 printk(KERN_WARNING "CIFS: no memory"
1704 "for charset\n");
1705 goto cifs_parse_mount_err;
1706 }
1707 }
1708 /* if iocharset not set then load_nls_default
1709 * is used by caller
1710 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001711 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001712 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001713 case Opt_netbiosname:
1714 string = match_strdup(args);
1715 if (string == NULL)
1716 goto out_nomem;
1717
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001718 memset(vol->source_rfc1001_name, 0x20,
1719 RFC1001_NAME_LEN);
1720 /*
1721 * FIXME: are there cases in which a comma can
1722 * be valid in workstation netbios name (and
1723 * need special handling)?
1724 */
1725 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1726 /* don't ucase netbiosname for user */
1727 if (string[i] == 0)
1728 break;
1729 vol->source_rfc1001_name[i] = string[i];
1730 }
1731 /* The string has 16th byte zero still from
1732 * set at top of the function
1733 */
1734 if (i == RFC1001_NAME_LEN && string[i] != 0)
1735 printk(KERN_WARNING "CIFS: netbiosname"
1736 " longer than 15 truncated.\n");
1737
1738 break;
1739 case Opt_servern:
1740 /* servernetbiosname specified override *SMBSERVER */
1741 string = match_strdup(args);
1742 if (string == NULL)
1743 goto out_nomem;
1744
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 /* last byte, type, is 0x20 for servr type */
1746 memset(vol->target_rfc1001_name, 0x20,
1747 RFC1001_NAME_LEN_WITH_NULL);
1748
1749 /* BB are there cases in which a comma can be
1750 valid in this workstation netbios name
1751 (and need special handling)? */
1752
1753 /* user or mount helper must uppercase the
1754 netbios name */
1755 for (i = 0; i < 15; i++) {
1756 if (string[i] == 0)
1757 break;
1758 vol->target_rfc1001_name[i] = string[i];
1759 }
1760 /* The string has 16th byte zero still from
1761 set at top of the function */
1762 if (i == RFC1001_NAME_LEN && string[i] != 0)
1763 printk(KERN_WARNING "CIFS: server net"
1764 "biosname longer than 15 truncated.\n");
1765 break;
1766 case Opt_ver:
1767 string = match_strdup(args);
1768 if (string == NULL)
1769 goto out_nomem;
1770
Jeff Layton5249af32012-05-15 12:04:03 -04001771 if (strnicmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001772 /* This is the default */
1773 break;
1774 }
1775 /* For all other value, error */
1776 printk(KERN_WARNING "CIFS: Invalid version"
1777 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001778 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001779 case Opt_vers:
1780 string = match_strdup(args);
1781 if (string == NULL)
1782 goto out_nomem;
1783
1784 if (cifs_parse_smb_version(string, vol) != 0)
1785 goto cifs_parse_mount_err;
1786 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001787 case Opt_sec:
1788 string = match_strdup(args);
1789 if (string == NULL)
1790 goto out_nomem;
1791
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 if (cifs_parse_security_flavors(string, vol) != 0)
1793 goto cifs_parse_mount_err;
1794 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001795 case Opt_cache:
1796 string = match_strdup(args);
1797 if (string == NULL)
1798 goto out_nomem;
1799
1800 if (cifs_parse_cache_flavor(string, vol) != 0)
1801 goto cifs_parse_mount_err;
1802 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001804 /*
1805 * An option we don't recognize. Save it off for later
1806 * if we haven't already found one
1807 */
1808 if (!invalid)
1809 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001810 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 /* Free up any allocated string */
1813 kfree(string);
1814 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001816
Jeff Laytond8162552012-03-23 14:40:56 -04001817 if (!sloppy && invalid) {
1818 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1819 goto cifs_parse_mount_err;
1820 }
1821
Jeff Layton8a8798a2012-01-17 16:09:15 -05001822#ifndef CONFIG_KEYS
1823 /* Muliuser mounts require CONFIG_KEYS support */
1824 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001825 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001826 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001827 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001828#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001829 if (!vol->UNC) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001830 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string or in unc= option!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05001831 goto cifs_parse_mount_err;
1832 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001833
Jeff Layton62a1a4392012-12-10 06:10:45 -05001834 /* make sure UNC has a share name */
1835 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001836 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a4392012-12-10 06:10:45 -05001837 goto cifs_parse_mount_err;
1838 }
1839
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001840 if (!got_ip) {
1841 /* No ip= option specified? Try to get it from UNC */
1842 if (!cifs_convert_address(dstaddr, &vol->UNC[2],
1843 strlen(&vol->UNC[2]))) {
1844 printk(KERN_ERR "Unable to determine destination "
1845 "address.\n");
1846 goto cifs_parse_mount_err;
1847 }
1848 }
1849
1850 /* set the port that we got earlier */
1851 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001853 if (uid_specified)
1854 vol->override_uid = override_uid;
1855 else if (override_uid == 1)
1856 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1857 "specified with no uid= option.\n");
1858
1859 if (gid_specified)
1860 vol->override_gid = override_gid;
1861 else if (override_gid == 1)
1862 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1863 "specified with no gid= option.\n");
1864
Sean Finneyb9468452011-04-11 13:19:32 +00001865 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001867
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001868out_nomem:
1869 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001870cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001871 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001872 kfree(mountdata_copy);
1873 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874}
1875
Ben Greear3eb9a882010-09-01 17:06:02 -07001876/** Returns true if srcaddr isn't specified and rhs isn't
1877 * specified, or if srcaddr is specified and
1878 * matches the IP address of the rhs argument.
1879 */
Jeff Layton45151482010-07-06 20:43:02 -04001880static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001881srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1882{
1883 switch (srcaddr->sa_family) {
1884 case AF_UNSPEC:
1885 return (rhs->sa_family == AF_UNSPEC);
1886 case AF_INET: {
1887 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1888 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1889 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1890 }
1891 case AF_INET6: {
1892 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05001893 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07001894 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1895 }
1896 default:
1897 WARN_ON(1);
1898 return false; /* don't expect to be here */
1899 }
1900}
1901
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001902/*
1903 * If no port is specified in addr structure, we try to match with 445 port
1904 * and if it fails - with 139 ports. It should be called only if address
1905 * families of server and addr are equal.
1906 */
1907static bool
1908match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1909{
Steve French6da97912011-03-13 18:55:55 +00001910 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001911
1912 switch (addr->sa_family) {
1913 case AF_INET:
1914 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1915 port = ((struct sockaddr_in *) addr)->sin_port;
1916 break;
1917 case AF_INET6:
1918 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1919 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1920 break;
1921 default:
1922 WARN_ON(1);
1923 return false;
1924 }
1925
1926 if (!port) {
1927 port = htons(CIFS_PORT);
1928 if (port == *sport)
1929 return true;
1930
1931 port = htons(RFC1001_PORT);
1932 }
1933
1934 return port == *sport;
1935}
Ben Greear3eb9a882010-09-01 17:06:02 -07001936
1937static bool
1938match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
1939 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940{
Jeff Layton45151482010-07-06 20:43:02 -04001941 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001942 case AF_INET: {
1943 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1944 struct sockaddr_in *srv_addr4 =
1945 (struct sockaddr_in *)&server->dstaddr;
1946
1947 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04001948 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001949 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001950 }
1951 case AF_INET6: {
1952 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1953 struct sockaddr_in6 *srv_addr6 =
1954 (struct sockaddr_in6 *)&server->dstaddr;
1955
Jeff Layton45151482010-07-06 20:43:02 -04001956 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001957 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04001958 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001959 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04001960 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001961 break;
1962 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001963 default:
1964 WARN_ON(1);
1965 return false; /* don't expect to be here */
1966 }
Jeff Layton45151482010-07-06 20:43:02 -04001967
Ben Greear3eb9a882010-09-01 17:06:02 -07001968 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
1969 return false;
1970
Jeff Layton45151482010-07-06 20:43:02 -04001971 return true;
1972}
1973
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001974static bool
1975match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
1976{
1977 unsigned int secFlags;
1978
1979 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
1980 secFlags = vol->secFlg;
1981 else
1982 secFlags = global_secflags | vol->secFlg;
1983
1984 switch (server->secType) {
1985 case LANMAN:
1986 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
1987 return false;
1988 break;
1989 case NTLMv2:
1990 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
1991 return false;
1992 break;
1993 case NTLM:
1994 if (!(secFlags & CIFSSEC_MAY_NTLM))
1995 return false;
1996 break;
1997 case Kerberos:
1998 if (!(secFlags & CIFSSEC_MAY_KRB5))
1999 return false;
2000 break;
2001 case RawNTLMSSP:
2002 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2003 return false;
2004 break;
2005 default:
2006 /* shouldn't happen */
2007 return false;
2008 }
2009
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002010 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002011 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002012 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002013 return false;
2014 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002015 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002016 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2017 return false;
2018
2019 return true;
2020}
2021
Jeff Layton9fa114f2012-11-26 11:09:57 -05002022static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002023{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002024 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2025
Jeff Layton23db65f2012-05-15 12:20:51 -04002026 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2027 return 0;
2028
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002029 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2030 return 0;
2031
2032 if (!match_address(server, addr,
2033 (struct sockaddr *)&vol->srcaddr))
2034 return 0;
2035
2036 if (!match_port(server, addr))
2037 return 0;
2038
2039 if (!match_security(server, vol))
2040 return 0;
2041
2042 return 1;
2043}
2044
Jeff Layton45151482010-07-06 20:43:02 -04002045static struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002046cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002047{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002048 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302050 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002051 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002052 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002053 continue;
2054
Jeff Laytone7ddee92008-11-14 13:44:38 -05002055 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302056 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002057 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002058 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302060 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 return NULL;
2062}
2063
Jeff Layton14fbf502008-11-14 13:53:46 -05002064static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002065cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002067 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302069 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002070 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302071 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002072 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002074
Rob Landleyf1d0c992011-01-22 15:44:05 -06002075 put_net(cifs_net_ns(server));
2076
Jeff Laytone7ddee92008-11-14 13:44:38 -05002077 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302078 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002079
Jeff Laytonc74093b2011-01-11 07:24:23 -05002080 cancel_delayed_work_sync(&server->echo);
2081
Jeff Laytone7ddee92008-11-14 13:44:38 -05002082 spin_lock(&GlobalMid_Lock);
2083 server->tcpStatus = CifsExiting;
2084 spin_unlock(&GlobalMid_Lock);
2085
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002086 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302087 cifs_fscache_release_client_cookie(server);
2088
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002089 kfree(server->session_key.response);
2090 server->session_key.response = NULL;
2091 server->session_key.len = 0;
2092
Jeff Laytone7ddee92008-11-14 13:44:38 -05002093 task = xchg(&server->tsk, NULL);
2094 if (task)
2095 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096}
2097
Jeff Layton63c038c2008-12-01 18:41:46 -05002098static struct TCP_Server_Info *
2099cifs_get_tcp_session(struct smb_vol *volume_info)
2100{
2101 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002102 int rc;
2103
Joe Perchesf96637b2013-05-04 22:12:25 -05002104 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002105
2106 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002107 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002108 if (tcp_ses)
2109 return tcp_ses;
2110
2111 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2112 if (!tcp_ses) {
2113 rc = -ENOMEM;
2114 goto out_err;
2115 }
2116
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002117 rc = cifs_crypto_shash_allocate(tcp_ses);
2118 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002119 cifs_dbg(VFS, "could not setup hash structures rc %d\n", rc);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002120 goto out_err;
2121 }
2122
Jeff Layton23db65f2012-05-15 12:20:51 -04002123 tcp_ses->ops = volume_info->ops;
2124 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002125 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002126 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2127 if (IS_ERR(tcp_ses->hostname)) {
2128 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002129 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002130 }
2131
2132 tcp_ses->noblocksnd = volume_info->noblocksnd;
2133 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002134 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002135 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002136 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002137 init_waitqueue_head(&tcp_ses->response_q);
2138 init_waitqueue_head(&tcp_ses->request_q);
2139 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2140 mutex_init(&tcp_ses->srv_mutex);
2141 memcpy(tcp_ses->workstation_RFC1001_name,
2142 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2143 memcpy(tcp_ses->server_RFC1001_name,
2144 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002145 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002146 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002147 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002148 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002149 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2150 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002151 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002152 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2153 sizeof(tcp_ses->srcaddr));
2154 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2155 sizeof(tcp_ses->dstaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002156 /*
2157 * at this point we are the only ones with the pointer
2158 * to the struct since the kernel thread not created yet
2159 * no need to spinlock this init of tcpStatus or srv_count
2160 */
2161 tcp_ses->tcpStatus = CifsNew;
2162 ++tcp_ses->srv_count;
2163
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002164 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002165 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002166 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002167 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002168 }
2169
2170 /*
2171 * since we're in a cifs function already, we know that
2172 * this will succeed. No need for try_module_get().
2173 */
2174 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002175 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002176 tcp_ses, "cifsd");
2177 if (IS_ERR(tcp_ses->tsk)) {
2178 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002179 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002180 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002181 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002182 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002183 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002184
2185 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302186 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002187 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302188 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002189
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302190 cifs_fscache_get_client_cookie(tcp_ses);
2191
Jeff Laytonc74093b2011-01-11 07:24:23 -05002192 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002193 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002194
Jeff Layton63c038c2008-12-01 18:41:46 -05002195 return tcp_ses;
2196
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002197out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002198 cifs_crypto_shash_release(tcp_ses);
2199
Rob Landleyf1d0c992011-01-22 15:44:05 -06002200 put_net(cifs_net_ns(tcp_ses));
2201
Jeff Layton63c038c2008-12-01 18:41:46 -05002202out_err:
2203 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002204 if (!IS_ERR(tcp_ses->hostname))
2205 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002206 if (tcp_ses->ssocket)
2207 sock_release(tcp_ses->ssocket);
2208 kfree(tcp_ses);
2209 }
2210 return ERR_PTR(rc);
2211}
2212
Steve French96daf2b2011-05-27 04:34:02 +00002213static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002214{
2215 switch (ses->server->secType) {
2216 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002217 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002218 return 0;
2219 break;
2220 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002221 /* NULL username means anonymous session */
2222 if (ses->user_name == NULL) {
2223 if (!vol->nullauth)
2224 return 0;
2225 break;
2226 }
2227
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002228 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002229 if (strncmp(ses->user_name,
2230 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002231 MAX_USERNAME_SIZE))
2232 return 0;
2233 if (strlen(vol->username) != 0 &&
2234 ses->password != NULL &&
2235 strncmp(ses->password,
2236 vol->password ? vol->password : "",
2237 MAX_PASSWORD_SIZE))
2238 return 0;
2239 }
2240 return 1;
2241}
2242
Steve French96daf2b2011-05-27 04:34:02 +00002243static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002244cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245{
Steve French96daf2b2011-05-27 04:34:02 +00002246 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302248 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002249 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002250 if (!match_session(ses, vol))
2251 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002252 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302253 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002254 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302256 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 return NULL;
2258}
2259
Jeff Layton14fbf502008-11-14 13:53:46 -05002260static void
Steve French96daf2b2011-05-27 04:34:02 +00002261cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002262{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04002263 unsigned int xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002264 struct TCP_Server_Info *server = ses->server;
2265
Joe Perchesf96637b2013-05-04 22:12:25 -05002266 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302267 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002268 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302269 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002270 return;
2271 }
2272
2273 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302274 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002275
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04002276 if (ses->status == CifsGood && server->ops->logoff) {
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002277 xid = get_xid();
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04002278 server->ops->logoff(xid, ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002279 _free_xid(xid);
Jeff Layton14fbf502008-11-14 13:53:46 -05002280 }
2281 sesInfoFree(ses);
2282 cifs_put_tcp_session(server);
2283}
2284
Jeff Layton8a8798a2012-01-17 16:09:15 -05002285#ifdef CONFIG_KEYS
2286
2287/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2288#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2289
2290/* Populate username and pw fields from keyring if possible */
2291static int
2292cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2293{
2294 int rc = 0;
2295 char *desc, *delim, *payload;
2296 ssize_t len;
2297 struct key *key;
2298 struct TCP_Server_Info *server = ses->server;
2299 struct sockaddr_in *sa;
2300 struct sockaddr_in6 *sa6;
2301 struct user_key_payload *upayload;
2302
2303 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2304 if (!desc)
2305 return -ENOMEM;
2306
2307 /* try to find an address key first */
2308 switch (server->dstaddr.ss_family) {
2309 case AF_INET:
2310 sa = (struct sockaddr_in *)&server->dstaddr;
2311 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2312 break;
2313 case AF_INET6:
2314 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2315 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2316 break;
2317 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05002318 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
2319 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002320 rc = -EINVAL;
2321 goto out_err;
2322 }
2323
Joe Perchesf96637b2013-05-04 22:12:25 -05002324 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002325 key = request_key(&key_type_logon, desc, "");
2326 if (IS_ERR(key)) {
2327 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002328 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05002329 rc = PTR_ERR(key);
2330 goto out_err;
2331 }
2332
2333 /* didn't work, try to find a domain key */
2334 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05002335 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002336 key = request_key(&key_type_logon, desc, "");
2337 if (IS_ERR(key)) {
2338 rc = PTR_ERR(key);
2339 goto out_err;
2340 }
2341 }
2342
2343 down_read(&key->sem);
2344 upayload = key->payload.data;
2345 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002346 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002347 goto out_key_put;
2348 }
2349
2350 /* find first : in payload */
2351 payload = (char *)upayload->data;
2352 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05002353 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002354 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002355 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
2356 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002357 rc = -EINVAL;
2358 goto out_key_put;
2359 }
2360
2361 len = delim - payload;
2362 if (len > MAX_USERNAME_SIZE || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002363 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
2364 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002365 rc = -EINVAL;
2366 goto out_key_put;
2367 }
2368
2369 vol->username = kstrndup(payload, len, GFP_KERNEL);
2370 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002371 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
2372 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002373 rc = -ENOMEM;
2374 goto out_key_put;
2375 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002376 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002377
2378 len = key->datalen - (len + 1);
2379 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002380 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002381 rc = -EINVAL;
2382 kfree(vol->username);
2383 vol->username = NULL;
2384 goto out_key_put;
2385 }
2386
2387 ++delim;
2388 vol->password = kstrndup(delim, len, GFP_KERNEL);
2389 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002390 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
2391 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002392 rc = -ENOMEM;
2393 kfree(vol->username);
2394 vol->username = NULL;
2395 goto out_key_put;
2396 }
2397
2398out_key_put:
2399 up_read(&key->sem);
2400 key_put(key);
2401out_err:
2402 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05002403 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002404 return rc;
2405}
2406#else /* ! CONFIG_KEYS */
2407static inline int
2408cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2409 struct cifs_ses *ses __attribute__((unused)))
2410{
2411 return -ENOSYS;
2412}
2413#endif /* CONFIG_KEYS */
2414
Steve French96daf2b2011-05-27 04:34:02 +00002415static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002416cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2417{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04002418 int rc = -ENOMEM;
2419 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002420 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002421 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2422 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002423
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002424 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04002425
Jeff Layton4ff67b72010-07-06 20:43:02 -04002426 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002427 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002428 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
2429 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04002430
Jeff Layton36988c72010-04-24 07:57:43 -04002431 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002432 rc = cifs_negotiate_protocol(xid, ses);
2433 if (rc) {
2434 mutex_unlock(&ses->session_mutex);
2435 /* problem -- put our ses reference */
2436 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002437 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04002438 return ERR_PTR(rc);
2439 }
Jeff Layton36988c72010-04-24 07:57:43 -04002440 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002441 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002442 rc = cifs_setup_session(xid, ses,
2443 volume_info->local_nls);
2444 if (rc) {
2445 mutex_unlock(&ses->session_mutex);
2446 /* problem -- put our reference */
2447 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002448 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002449 return ERR_PTR(rc);
2450 }
2451 }
2452 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002453
2454 /* existing SMB ses has a server reference already */
2455 cifs_put_tcp_session(server);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002456 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002457 return ses;
2458 }
2459
Joe Perchesf96637b2013-05-04 22:12:25 -05002460 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04002461 ses = sesInfoAlloc();
2462 if (ses == NULL)
2463 goto get_ses_fail;
2464
2465 /* new SMB session uses our server ref */
2466 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002467 if (server->dstaddr.ss_family == AF_INET6)
2468 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002469 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002470 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002471
Steve French8727c8a2011-02-25 01:11:56 -06002472 if (volume_info->username) {
2473 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2474 if (!ses->user_name)
2475 goto get_ses_fail;
2476 }
Jeff Layton36988c72010-04-24 07:57:43 -04002477
2478 /* volume_info->password freed at unmount */
2479 if (volume_info->password) {
2480 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2481 if (!ses->password)
2482 goto get_ses_fail;
2483 }
2484 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002485 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2486 if (!ses->domainName)
2487 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002488 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002489 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002490 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002491
Jeff Layton36988c72010-04-24 07:57:43 -04002492 ses->overrideSecFlg = volume_info->secFlg;
2493
2494 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002495 rc = cifs_negotiate_protocol(xid, ses);
2496 if (!rc)
2497 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002498 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002499 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002500 goto get_ses_fail;
2501
2502 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302503 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002504 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302505 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002506
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002507 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002508 return ses;
2509
2510get_ses_fail:
2511 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002512 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04002513 return ERR_PTR(rc);
2514}
2515
Steve French96daf2b2011-05-27 04:34:02 +00002516static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002517{
2518 if (tcon->tidStatus == CifsExiting)
2519 return 0;
2520 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2521 return 0;
2522 return 1;
2523}
2524
Steve French96daf2b2011-05-27 04:34:02 +00002525static struct cifs_tcon *
2526cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527{
2528 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002529 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302531 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002532 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002533 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002534 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002535 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002536 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302537 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 return tcon;
2539 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302540 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 return NULL;
2542}
2543
Jeff Laytonf1987b42008-11-15 11:12:47 -05002544static void
Steve French96daf2b2011-05-27 04:34:02 +00002545cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002546{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002547 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002548 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002549
Joe Perchesf96637b2013-05-04 22:12:25 -05002550 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302551 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002552 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302553 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002554 return;
2555 }
2556
2557 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302558 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002559
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002560 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002561 if (ses->server->ops->tree_disconnect)
2562 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002563 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002564
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302565 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002566 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002567 cifs_put_smb_ses(ses);
2568}
2569
Steve French96daf2b2011-05-27 04:34:02 +00002570static struct cifs_tcon *
2571cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002572{
2573 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002574 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002575
2576 tcon = cifs_find_tcon(ses, volume_info->UNC);
2577 if (tcon) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002578 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002579 /* existing tcon already has a reference */
2580 cifs_put_smb_ses(ses);
2581 if (tcon->seal != volume_info->seal)
Joe Perchesf96637b2013-05-04 22:12:25 -05002582 cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04002583 return tcon;
2584 }
2585
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002586 if (!ses->server->ops->tree_connect) {
2587 rc = -ENOSYS;
2588 goto out_fail;
2589 }
2590
Jeff Laytond00c28d2010-04-24 07:57:44 -04002591 tcon = tconInfoAlloc();
2592 if (tcon == NULL) {
2593 rc = -ENOMEM;
2594 goto out_fail;
2595 }
2596
2597 tcon->ses = ses;
2598 if (volume_info->password) {
2599 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2600 if (!tcon->password) {
2601 rc = -ENOMEM;
2602 goto out_fail;
2603 }
2604 }
2605
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002606 /*
2607 * BB Do we need to wrap session_mutex around this TCon call and Unix
2608 * SetFS as we do on SessSetup and reconnect?
2609 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002610 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002611 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
2612 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04002613 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05002614 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002615 if (rc)
2616 goto out_fail;
2617
2618 if (volume_info->nodfs) {
2619 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
Joe Perchesf96637b2013-05-04 22:12:25 -05002620 cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002621 }
2622 tcon->seal = volume_info->seal;
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002623 /*
2624 * We can have only one retry value for a connection to a share so for
2625 * resources mounted more than once to the same server share the last
2626 * value passed in for the retry flag is used.
2627 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04002628 tcon->retry = volume_info->retry;
2629 tcon->nocase = volume_info->nocase;
2630 tcon->local_lease = volume_info->local_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07002631 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002632
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302633 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002634 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302635 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002636
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302637 cifs_fscache_get_super_cookie(tcon);
2638
Jeff Laytond00c28d2010-04-24 07:57:44 -04002639 return tcon;
2640
2641out_fail:
2642 tconInfoFree(tcon);
2643 return ERR_PTR(rc);
2644}
2645
Jeff Layton9d002df2010-10-06 19:51:11 -04002646void
2647cifs_put_tlink(struct tcon_link *tlink)
2648{
2649 if (!tlink || IS_ERR(tlink))
2650 return;
2651
2652 if (!atomic_dec_and_test(&tlink->tl_count) ||
2653 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2654 tlink->tl_time = jiffies;
2655 return;
2656 }
2657
2658 if (!IS_ERR(tlink_tcon(tlink)))
2659 cifs_put_tcon(tlink_tcon(tlink));
2660 kfree(tlink);
2661 return;
2662}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002663
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002664static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002665cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2666{
2667 return cifs_sb->master_tlink;
2668}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002669
2670static int
2671compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2672{
2673 struct cifs_sb_info *old = CIFS_SB(sb);
2674 struct cifs_sb_info *new = mnt_data->cifs_sb;
2675
2676 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2677 return 0;
2678
2679 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2680 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2681 return 0;
2682
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002683 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002684 * We want to share sb only if we don't specify an r/wsize or
2685 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002686 */
2687 if (new->wsize && new->wsize < old->wsize)
2688 return 0;
2689
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002690 if (new->rsize && new->rsize < old->rsize)
2691 return 0;
2692
Eric W. Biederman1f682332013-02-06 01:20:20 -08002693 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002694 return 0;
2695
2696 if (old->mnt_file_mode != new->mnt_file_mode ||
2697 old->mnt_dir_mode != new->mnt_dir_mode)
2698 return 0;
2699
2700 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2701 return 0;
2702
2703 if (old->actimeo != new->actimeo)
2704 return 0;
2705
2706 return 1;
2707}
2708
2709int
2710cifs_match_super(struct super_block *sb, void *data)
2711{
2712 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2713 struct smb_vol *volume_info;
2714 struct cifs_sb_info *cifs_sb;
2715 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002716 struct cifs_ses *ses;
2717 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002718 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002719 int rc = 0;
2720
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002721 spin_lock(&cifs_tcp_ses_lock);
2722 cifs_sb = CIFS_SB(sb);
2723 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2724 if (IS_ERR(tlink)) {
2725 spin_unlock(&cifs_tcp_ses_lock);
2726 return rc;
2727 }
2728 tcon = tlink_tcon(tlink);
2729 ses = tcon->ses;
2730 tcp_srv = ses->server;
2731
2732 volume_info = mnt_data->vol;
2733
Jeff Layton9fa114f2012-11-26 11:09:57 -05002734 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002735 !match_session(ses, volume_info) ||
2736 !match_tcon(tcon, volume_info->UNC)) {
2737 rc = 0;
2738 goto out;
2739 }
2740
2741 rc = compare_mount_options(sb, mnt_data);
2742out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002743 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002744 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002745 return rc;
2746}
2747
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002749get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002750 const struct nls_table *nls_codepage, unsigned int *num_referrals,
2751 struct dfs_info3_param **referrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752{
2753 char *temp_unc;
2754 int rc = 0;
2755
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002756 if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002757 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002759 *num_referrals = 0;
2760 *referrals = NULL;
2761
2762 if (ses->ipc_tid == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 temp_unc = kmalloc(2 /* for slashes */ +
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002764 strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
2765 + 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 if (temp_unc == NULL)
2767 return -ENOMEM;
2768 temp_unc[0] = '\\';
2769 temp_unc[1] = '\\';
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002770 strcpy(temp_unc + 2, ses->serverName);
2771 strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
2772 rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
2773 nls_codepage);
Joe Perchesf96637b2013-05-04 22:12:25 -05002774 cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d\n", rc, ses->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 kfree(temp_unc);
2776 }
2777 if (rc == 0)
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002778 rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
2779 referrals, num_referrals,
2780 nls_codepage, remap);
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002781 /*
2782 * BB - map targetUNCs to dfs_info3 structures, here or in
Pavel Shilovskyb669f332012-05-27 20:21:53 +04002783 * ses->server->ops->get_dfs_refer.
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04002784 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785
2786 return rc;
2787}
2788
Jeff Layton09e50d52008-07-23 10:11:19 -04002789#ifdef CONFIG_DEBUG_LOCK_ALLOC
2790static struct lock_class_key cifs_key[2];
2791static struct lock_class_key cifs_slock_key[2];
2792
2793static inline void
2794cifs_reclassify_socket4(struct socket *sock)
2795{
2796 struct sock *sk = sock->sk;
2797 BUG_ON(sock_owned_by_user(sk));
2798 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2799 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2800}
2801
2802static inline void
2803cifs_reclassify_socket6(struct socket *sock)
2804{
2805 struct sock *sk = sock->sk;
2806 BUG_ON(sock_owned_by_user(sk));
2807 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2808 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2809}
2810#else
2811static inline void
2812cifs_reclassify_socket4(struct socket *sock)
2813{
2814}
2815
2816static inline void
2817cifs_reclassify_socket6(struct socket *sock)
2818{
2819}
2820#endif
2821
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002823static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824{
Steve French50c2f752007-07-13 00:33:32 +00002825 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
Steve French50c2f752007-07-13 00:33:32 +00002827 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 /* mask a nibble at a time and encode */
2829 target[j] = 'A' + (0x0F & (source[i] >> 4));
2830 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002831 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 }
2833
2834}
2835
Ben Greear3eb9a882010-09-01 17:06:02 -07002836static int
2837bind_socket(struct TCP_Server_Info *server)
2838{
2839 int rc = 0;
2840 if (server->srcaddr.ss_family != AF_UNSPEC) {
2841 /* Bind to the specified local IP address */
2842 struct socket *socket = server->ssocket;
2843 rc = socket->ops->bind(socket,
2844 (struct sockaddr *) &server->srcaddr,
2845 sizeof(server->srcaddr));
2846 if (rc < 0) {
2847 struct sockaddr_in *saddr4;
2848 struct sockaddr_in6 *saddr6;
2849 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2850 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2851 if (saddr6->sin6_family == AF_INET6)
Joe Perchesf96637b2013-05-04 22:12:25 -05002852 cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
2853 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002854 else
Joe Perchesf96637b2013-05-04 22:12:25 -05002855 cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
2856 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07002857 }
2858 }
2859 return rc;
2860}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861
2862static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002863ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864{
2865 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002866 /*
2867 * some servers require RFC1001 sessinit before sending
2868 * negprot - BB check reconnection in case where second
2869 * sessinit is sent but no second negprot
2870 */
2871 struct rfc1002_session_packet *ses_init_buf;
2872 struct smb_hdr *smb_buf;
2873 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2874 GFP_KERNEL);
2875 if (ses_init_buf) {
2876 ses_init_buf->trailer.session_req.called_len = 32;
2877
2878 if (server->server_RFC1001_name &&
2879 server->server_RFC1001_name[0] != 0)
2880 rfc1002mangle(ses_init_buf->trailer.
2881 session_req.called_name,
2882 server->server_RFC1001_name,
2883 RFC1001_NAME_LEN_WITH_NULL);
2884 else
2885 rfc1002mangle(ses_init_buf->trailer.
2886 session_req.called_name,
2887 DEFAULT_CIFS_CALLED_NAME,
2888 RFC1001_NAME_LEN_WITH_NULL);
2889
2890 ses_init_buf->trailer.session_req.calling_len = 32;
2891
2892 /*
2893 * calling name ends in null (byte 16) from old smb
2894 * convention.
2895 */
2896 if (server->workstation_RFC1001_name &&
2897 server->workstation_RFC1001_name[0] != 0)
2898 rfc1002mangle(ses_init_buf->trailer.
2899 session_req.calling_name,
2900 server->workstation_RFC1001_name,
2901 RFC1001_NAME_LEN_WITH_NULL);
2902 else
2903 rfc1002mangle(ses_init_buf->trailer.
2904 session_req.calling_name,
2905 "LINUX_CIFS_CLNT",
2906 RFC1001_NAME_LEN_WITH_NULL);
2907
2908 ses_init_buf->trailer.session_req.scope1 = 0;
2909 ses_init_buf->trailer.session_req.scope2 = 0;
2910 smb_buf = (struct smb_hdr *)ses_init_buf;
2911
2912 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00002913 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002914 rc = smb_send(server, smb_buf, 0x44);
2915 kfree(ses_init_buf);
2916 /*
2917 * RFC1001 layer in at least one server
2918 * requires very short break before negprot
2919 * presumably because not expecting negprot
2920 * to follow so fast. This is a simple
2921 * solution that works without
2922 * complicating the code and causes no
2923 * significant slowing down on mount
2924 * for everyone else
2925 */
2926 usleep_range(1000, 2000);
2927 }
2928 /*
2929 * else the negprot may still work without this
2930 * even though malloc failed
2931 */
2932
2933 return rc;
2934}
2935
2936static int
2937generic_ip_connect(struct TCP_Server_Info *server)
2938{
2939 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00002940 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002941 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002942 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002943 struct sockaddr *saddr;
2944
2945 saddr = (struct sockaddr *) &server->dstaddr;
2946
2947 if (server->dstaddr.ss_family == AF_INET6) {
2948 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
2949 slen = sizeof(struct sockaddr_in6);
2950 sfamily = AF_INET6;
2951 } else {
2952 sport = ((struct sockaddr_in *) saddr)->sin_port;
2953 slen = sizeof(struct sockaddr_in);
2954 sfamily = AF_INET;
2955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002957 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06002958 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
2959 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002961 cifs_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002962 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002965
2966 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05002967 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002968 server->ssocket = socket;
2969 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002970 if (sfamily == AF_INET6)
2971 cifs_reclassify_socket6(socket);
2972 else
2973 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974 }
2975
Ben Greear3eb9a882010-09-01 17:06:02 -07002976 rc = bind_socket(server);
2977 if (rc < 0)
2978 return rc;
2979
Jeff Laytond5c56052008-12-01 18:42:33 -05002980 /*
2981 * Eventually check for other socket options to change from
2982 * the default. sock_setsockopt not used because it expects
2983 * user space buffer
2984 */
2985 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00002986 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00002987
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002988 /* make the bufsizes depend on wsize/rsize and max requests */
2989 if (server->noautotune) {
2990 if (socket->sk->sk_sndbuf < (200 * 1024))
2991 socket->sk->sk_sndbuf = 200 * 1024;
2992 if (socket->sk->sk_rcvbuf < (140 * 1024))
2993 socket->sk->sk_rcvbuf = 140 * 1024;
2994 }
2995
Steve French6a5fa2362010-01-01 01:28:43 +00002996 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002997 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00002998 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
2999 (char *)&val, sizeof(val));
3000 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003001 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3002 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003003 }
3004
Joe Perchesf96637b2013-05-04 22:12:25 -05003005 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003006 socket->sk->sk_sndbuf,
3007 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3008
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003009 rc = socket->ops->connect(socket, saddr, slen, 0);
3010 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003011 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003012 sock_release(socket);
3013 server->ssocket = NULL;
3014 return rc;
3015 }
3016
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003017 if (sport == htons(RFC1001_PORT))
3018 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003019
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 return rc;
3021}
3022
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003023static int
3024ip_connect(struct TCP_Server_Info *server)
3025{
Steve French6da97912011-03-13 18:55:55 +00003026 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003027 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3028 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3029
3030 if (server->dstaddr.ss_family == AF_INET6)
3031 sport = &addr6->sin6_port;
3032 else
3033 sport = &addr->sin_port;
3034
3035 if (*sport == 0) {
3036 int rc;
3037
3038 /* try with 445 port at first */
3039 *sport = htons(CIFS_PORT);
3040
3041 rc = generic_ip_connect(server);
3042 if (rc >= 0)
3043 return rc;
3044
3045 /* if it failed, try with 139 port */
3046 *sport = htons(RFC1001_PORT);
3047 }
3048
3049 return generic_ip_connect(server);
3050}
3051
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003052void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003053 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003054{
3055 /* if we are reconnecting then should we check to see if
3056 * any requested capabilities changed locally e.g. via
3057 * remount but we can not do much about it here
3058 * if they have (even if we could detect it by the following)
3059 * Perhaps we could add a backpointer to array of sb from tcon
3060 * or if we change to make all sb to same share the same
3061 * sb as NFS - then we only have one backpointer to sb.
3062 * What if we wanted to mount the server share twice once with
3063 * and once without posixacls or posix paths? */
3064 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003065
Steve Frenchc18c8422007-07-18 23:21:09 +00003066 if (vol_info && vol_info->no_linux_ext) {
3067 tcon->fsUnixInfo.Capability = 0;
3068 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003069 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003070 return;
3071 } else if (vol_info)
3072 tcon->unix_ext = 1; /* Unix Extensions supported */
3073
3074 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003075 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003076 return;
3077 }
Steve French50c2f752007-07-13 00:33:32 +00003078
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003079 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003080 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003081 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003082 /* check for reconnect case in which we do not
3083 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003084 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003085 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003086 originally at mount time */
3087 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3088 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003089 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3090 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003091 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003092 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003093 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003094 cifs_dbg(VFS, "possible reconnect error\n");
3095 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003096 }
Steve French8af18972007-02-14 04:42:51 +00003097 }
Steve French50c2f752007-07-13 00:33:32 +00003098
Steve French6848b732011-05-26 18:38:54 +00003099 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003100 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003101
Steve French8af18972007-02-14 04:42:51 +00003102 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003103 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003104 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003105 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003106 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003107 if (cifs_sb)
3108 cifs_sb->mnt_cifs_flags |=
3109 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003110 }
3111
Steve French75865f8c2007-06-24 18:30:48 +00003112 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003113 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003114 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003115 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003116 if (cifs_sb)
3117 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003118 CIFS_MOUNT_POSIX_PATHS;
3119 }
Steve French50c2f752007-07-13 00:33:32 +00003120
Joe Perchesf96637b2013-05-04 22:12:25 -05003121 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003122#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003123 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003124 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003125 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003126 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003127 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003128 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003129 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003130 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003131 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003132 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003133 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003134 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003135 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003136 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00003137 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003138 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00003139 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003140 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00003141#endif /* CIFS_DEBUG2 */
3142 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003143 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003144 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00003145 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05003146 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 +00003147
Steve French8af18972007-02-14 04:42:51 +00003148 }
3149 }
3150}
3151
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003152void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3153 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003154{
Jeff Layton2de970f2010-10-06 19:51:12 -04003155 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3156
Al Viro2ced6f62011-06-17 09:20:04 -04003157 spin_lock_init(&cifs_sb->tlink_tree_lock);
3158 cifs_sb->tlink_tree = RB_ROOT;
3159
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003160 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003161 * Temporarily set r/wsize for matching superblock. If we end up using
3162 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003163 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003164 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003165 cifs_sb->wsize = pvolume_info->wsize;
3166
Steve French3b795212008-11-13 19:45:32 +00003167 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3168 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3169 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3170 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05003171 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
3172 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003173
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303174 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003175 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303176
Steve French3b795212008-11-13 19:45:32 +00003177 if (pvolume_info->noperm)
3178 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3179 if (pvolume_info->setuids)
3180 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3181 if (pvolume_info->server_ino)
3182 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3183 if (pvolume_info->remap)
3184 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3185 if (pvolume_info->no_xattr)
3186 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3187 if (pvolume_info->sfu_emul)
3188 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3189 if (pvolume_info->nobrl)
3190 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003191 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003192 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003193 if (pvolume_info->mand_lock)
3194 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003195 if (pvolume_info->rwpidforward)
3196 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003197 if (pvolume_info->cifs_acl)
3198 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003199 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003200 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003201 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3202 }
3203 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003204 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003205 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3206 }
Steve French3b795212008-11-13 19:45:32 +00003207 if (pvolume_info->override_uid)
3208 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3209 if (pvolume_info->override_gid)
3210 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3211 if (pvolume_info->dynperm)
3212 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303213 if (pvolume_info->fsc)
3214 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003215 if (pvolume_info->multiuser)
3216 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3217 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003218 if (pvolume_info->strict_io)
3219 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003220 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003221 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00003222 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3223 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003224 if (pvolume_info->mfsymlinks) {
3225 if (pvolume_info->sfu_emul) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003226 cifs_dbg(VFS, "mount option mfsymlinks ignored if sfu mount option is used\n");
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003227 } else {
3228 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3229 }
3230 }
Steve French3b795212008-11-13 19:45:32 +00003231
3232 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05003233 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003234}
3235
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003236static void
3237cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003238{
Sean Finneyb9468452011-04-11 13:19:32 +00003239 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003240 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02003241 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003242 kfree(volume_info->domainname);
3243 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003244 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003245}
3246
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003247void
3248cifs_cleanup_volume_info(struct smb_vol *volume_info)
3249{
3250 if (!volume_info)
3251 return;
3252 cleanup_volume_info_contents(volume_info);
3253 kfree(volume_info);
3254}
3255
3256
Steve French2d6d5892009-04-09 00:36:44 +00003257#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06003258/*
3259 * cifs_build_path_to_root returns full path to root when we do not have an
3260 * exiting connection (tcon)
3261 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003262static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003263build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003264 const struct cifs_sb_info *cifs_sb)
3265{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003266 char *full_path, *pos;
Jeff Layton839db3d2012-12-10 06:10:45 -05003267 unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003268 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003269
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003270 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003271 if (full_path == NULL)
3272 return ERR_PTR(-ENOMEM);
3273
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003274 strncpy(full_path, vol->UNC, unc_len);
3275 pos = full_path + unc_len;
3276
3277 if (pplen) {
Jeff Layton839db3d2012-12-10 06:10:45 -05003278 *pos++ = CIFS_DIR_SEP(cifs_sb);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003279 strncpy(pos, vol->prepath, pplen);
3280 pos += pplen;
3281 }
3282
3283 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003284 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05003285 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003286 return full_path;
3287}
Sean Finneydd613942011-04-11 13:19:30 +00003288
3289/*
3290 * Perform a dfs referral query for a share and (optionally) prefix
3291 *
Sean Finney046462a2011-04-11 13:19:33 +00003292 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3293 * to a string containing updated options for the submount. Otherwise it
3294 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003295 *
3296 * Returns the rc from get_dfs_path to the caller, which can be used to
3297 * determine whether there were referrals.
3298 */
3299static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003300expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00003301 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003302 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003303{
3304 int rc;
3305 unsigned int num_referrals = 0;
3306 struct dfs_info3_param *referrals = NULL;
3307 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3308
3309 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3310 if (IS_ERR(full_path))
3311 return PTR_ERR(full_path);
3312
3313 /* For DFS paths, skip the first '\' of the UNC */
3314 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3315
Pavel Shilovskyb669f332012-05-27 20:21:53 +04003316 rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
Sean Finneydd613942011-04-11 13:19:30 +00003317 &num_referrals, &referrals,
3318 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3319
3320 if (!rc && num_referrals > 0) {
3321 char *fake_devname = NULL;
3322
3323 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3324 full_path + 1, referrals,
3325 &fake_devname);
3326
3327 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003328
Sean Finneydd613942011-04-11 13:19:30 +00003329 if (IS_ERR(mdata)) {
3330 rc = PTR_ERR(mdata);
3331 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003332 } else {
3333 cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003334 rc = cifs_setup_volume_info(volume_info, mdata,
3335 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003336 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003337 kfree(fake_devname);
3338 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003339 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003340 }
3341 kfree(full_path);
3342 return rc;
3343}
Steve French2d6d5892009-04-09 00:36:44 +00003344#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003345
Jeff Layton04db79b2011-07-06 08:10:38 -04003346static int
3347cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3348 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003350 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003351
Jeff Layton04db79b2011-07-06 08:10:38 -04003352 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3353 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354
Jeff Layton7586b762008-12-01 18:41:49 -05003355 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003356 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05003357 kfree(volume_info->username);
3358 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003359 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05003361 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05003363 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00003364 /* In userspace mount helper we can get user name from alternate
3365 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003366 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 }
3368
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003370 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003371 /* load_nls_default cannot return null */
3372 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003374 volume_info->local_nls = load_nls(volume_info->iocharset);
3375 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003376 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003377 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003378 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 }
3380 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003381
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003382 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003383}
3384
3385struct smb_vol *
3386cifs_get_volume_info(char *mount_data, const char *devname)
3387{
3388 int rc;
3389 struct smb_vol *volume_info;
3390
Jeff Layton6ee95422012-11-26 11:09:57 -05003391 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003392 if (!volume_info)
3393 return ERR_PTR(-ENOMEM);
3394
3395 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3396 if (rc) {
3397 cifs_cleanup_volume_info(volume_info);
3398 volume_info = ERR_PTR(rc);
3399 }
3400
3401 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003402}
3403
3404int
Al Viro2c6292a2011-06-17 09:05:48 -04003405cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003406{
Jeff Layton1daaae82012-03-21 06:30:40 -04003407 int rc;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003408 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003409 struct cifs_ses *ses;
Steve French96daf2b2011-05-27 04:34:02 +00003410 struct cifs_tcon *tcon;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003411 struct TCP_Server_Info *server;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003412 char *full_path;
3413 struct tcon_link *tlink;
3414#ifdef CONFIG_CIFS_DFS_UPCALL
3415 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003416#endif
Al Virodd854462011-06-17 08:24:42 -04003417
3418 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3419 if (rc)
3420 return rc;
3421
Jeff Layton20547492011-07-09 12:21:07 -04003422#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003423try_mount_again:
3424 /* cleanup activities if we're chasing a referral */
3425 if (referral_walks_count) {
3426 if (tcon)
3427 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003428 else if (ses)
3429 cifs_put_smb_ses(ses);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003430
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003431 free_xid(xid);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003432 }
3433#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003434 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003435 tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003436 ses = NULL;
3437 server = NULL;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003438 full_path = NULL;
3439 tlink = NULL;
3440
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003441 xid = get_xid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442
Jeff Layton63c038c2008-12-01 18:41:46 -05003443 /* get a reference to a tcp session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003444 server = cifs_get_tcp_session(volume_info);
3445 if (IS_ERR(server)) {
3446 rc = PTR_ERR(server);
Al Virodd854462011-06-17 08:24:42 -04003447 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003448 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 }
3450
Jeff Layton36988c72010-04-24 07:57:43 -04003451 /* get a reference to a SMB session */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003452 ses = cifs_get_smb_ses(server, volume_info);
3453 if (IS_ERR(ses)) {
3454 rc = PTR_ERR(ses);
3455 ses = NULL;
Jeff Layton36988c72010-04-24 07:57:43 -04003456 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 }
Steve French50c2f752007-07-13 00:33:32 +00003458
Jeff Laytond00c28d2010-04-24 07:57:44 -04003459 /* search for existing tcon to this server share */
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003460 tcon = cifs_get_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003461 if (IS_ERR(tcon)) {
3462 rc = PTR_ERR(tcon);
3463 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003464 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003465 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003466
Steve French6848b732011-05-26 18:38:54 +00003467 /* tell server which Unix caps we support */
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003468 if (cap_unix(tcon->ses)) {
Steve French6848b732011-05-26 18:38:54 +00003469 /* reset of caps checks mount to see if unix extensions
3470 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003471 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003472 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3473 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3474 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3475 rc = -EACCES;
3476 goto mount_fail_check;
3477 }
3478 } else
3479 tcon->unix_ext = 0; /* server does not support them */
3480
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003481 /* do not care if a following call succeed - informational */
3482 if (!tcon->ipc && server->ops->qfs_tcon)
3483 server->ops->qfs_tcon(xid, tcon);
Steve Frenchd82c2df2008-11-15 00:07:26 +00003484
Pavel Shilovsky24985c52012-09-18 16:20:28 -07003485 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
3486 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003487
Jeff Layton66bfaad2011-10-19 15:30:35 -04003488 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003489 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003490
Igor Mammedove4cce942009-02-10 14:10:26 +03003491remote_path_check:
3492#ifdef CONFIG_CIFS_DFS_UPCALL
3493 /*
3494 * Perform an unconditional check for whether there are DFS
3495 * referrals for this path without prefix, to provide support
3496 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003497 * with PATH_NOT_COVERED to requests that include the prefix.
3498 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003499 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003500 if (referral_walks_count == 0) {
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003501 int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
3502 false);
Steve Frencheeac8042006-01-13 21:34:58 -08003503 if (!refrc) {
Steve French4523cc32007-04-30 20:13:06 +00003504 referral_walks_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 goto try_mount_again;
3506 }
3507 }
3508#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003509
Steve Frenchf87d39d2011-05-27 03:50:55 +00003510 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 if (!rc && tcon) {
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003512 if (!server->ops->is_path_accessible) {
3513 rc = -ENOSYS;
3514 goto mount_fail_check;
3515 }
Steve French6d3ea7e2012-11-28 22:34:41 -06003516 /*
3517 * cifs_build_path_to_root works only when we have a valid tcon
3518 */
3519 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 if (full_path == NULL) {
3521 rc = -ENOMEM;
3522 goto mount_fail_check;
3523 }
Pavel Shilovsky68889f22012-05-25 14:40:22 +04003524 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
3525 full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 if (rc != 0 && rc != -EREMOTE) {
3527 kfree(full_path);
3528 goto mount_fail_check;
3529 }
3530 kfree(full_path);
3531 }
3532
3533 /* get referral if needed */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003534 if (rc == -EREMOTE) {
3535#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003536 if (referral_walks_count > MAX_NESTED_LINKS) {
3537 /*
3538 * BB: when we implement proper loop detection,
3539 * we will remove this check. But now we need it
3540 * to prevent an indefinite loop if 'DFS tree' is
3541 * misconfigured (i.e. has loops).
3542 */
3543 rc = -ELOOP;
3544 goto mount_fail_check;
3545 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003546
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003547 rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003548
Sean Finneydd613942011-04-11 13:19:30 +00003549 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003550 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003551 goto try_mount_again;
3552 }
Sean Finneydd613942011-04-11 13:19:30 +00003553 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003554#else /* No DFS support, return error on mount */
3555 rc = -EOPNOTSUPP;
3556#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003557 }
3558
Jeff Layton9d002df2010-10-06 19:51:11 -04003559 if (rc)
3560 goto mount_fail_check;
3561
3562 /* now, hang the tcon off of the superblock */
3563 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3564 if (tlink == NULL) {
3565 rc = -ENOMEM;
3566 goto mount_fail_check;
3567 }
3568
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003569 tlink->tl_uid = ses->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003570 tlink->tl_tcon = tcon;
3571 tlink->tl_time = jiffies;
3572 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3573 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3574
Jeff Layton413e6612010-10-28 13:33:38 -04003575 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003576 spin_lock(&cifs_sb->tlink_tree_lock);
3577 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3578 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003579
Jeff Laytonda472fc2012-03-23 14:40:53 -04003580 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003581 TLINK_IDLE_EXPIRE);
3582
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003583mount_fail_check:
3584 /* on error free sesinfo and tcon struct if needed */
3585 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003586 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003587 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003588 if (tcon)
3589 cifs_put_tcon(tcon);
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003590 else if (ses)
3591 cifs_put_smb_ses(ses);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003592 else
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04003593 cifs_put_tcp_session(server);
Al Virodd854462011-06-17 08:24:42 -04003594 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003595 }
3596
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003598 free_xid(xid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 return rc;
3600}
3601
Jeff Layton8d1bca32011-06-11 21:17:10 -04003602/*
3603 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3604 * pointer may be NULL.
3605 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003607CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00003608 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 const struct nls_table *nls_codepage)
3610{
3611 struct smb_hdr *smb_buffer;
3612 struct smb_hdr *smb_buffer_response;
3613 TCONX_REQ *pSMB;
3614 TCONX_RSP *pSMBr;
3615 unsigned char *bcc_ptr;
3616 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003617 int length;
3618 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619
3620 if (ses == NULL)
3621 return -EIO;
3622
3623 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003624 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003626
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 smb_buffer_response = smb_buffer;
3628
3629 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3630 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003631
Pavel Shilovsky88257362012-05-23 14:01:59 +04003632 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 smb_buffer->Uid = ses->Suid;
3634 pSMB = (TCONX_REQ *) smb_buffer;
3635 pSMBr = (TCONX_RSP *) smb_buffer_response;
3636
3637 pSMB->AndXCommand = 0xFF;
3638 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003640 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003641 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003642 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003643 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003644 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003645 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003646 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003647 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3648 specified as required (when that support is added to
3649 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003650 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003651 by Samba (not sure whether other servers allow
3652 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003653#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003654 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003655 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003656 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003657 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003658 SECMODE_PW_ENCRYPT ? true : false,
3659 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003660 else
3661#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003662 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003663 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003664
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003665 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003666 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003667 /* must align unicode strings */
3668 *bcc_ptr = 0; /* null byte password */
3669 bcc_ptr++;
3670 }
Steve Frencheeac8042006-01-13 21:34:58 -08003671 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672
Steve French96daf2b2011-05-27 04:34:02 +00003673 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003674 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3676
3677 if (ses->capabilities & CAP_STATUS32) {
3678 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3679 }
3680 if (ses->capabilities & CAP_DFS) {
3681 smb_buffer->Flags2 |= SMBFLG2_DFS;
3682 }
3683 if (ses->capabilities & CAP_UNICODE) {
3684 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3685 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003686 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003687 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003688 (/* server len*/ + 256 /* share len */), nls_codepage);
3689 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 bcc_ptr += 2; /* skip trailing null */
3691 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 strcpy(bcc_ptr, tree);
3693 bcc_ptr += strlen(tree) + 1;
3694 }
3695 strcpy(bcc_ptr, "?????");
3696 bcc_ptr += strlen("?????");
3697 bcc_ptr += 1;
3698 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003699 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3700 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 pSMB->ByteCount = cpu_to_le16(count);
3702
Steve French133672e2007-11-13 22:41:37 +00003703 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003704 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 /* above now done in SendReceive */
3707 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003708 bool is_unicode;
3709
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003711 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 tcon->tid = smb_buffer_response->Tid;
3713 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003714 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003715 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003716 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
3717 is_unicode = true;
3718 else
3719 is_unicode = false;
3720
Jeff Laytoncc20c032009-04-30 07:16:21 -04003721
Steve French50c2f752007-07-13 00:33:32 +00003722 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00003723 if (length == 3) {
3724 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3725 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003726 cifs_dbg(FYI, "IPC connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003727 tcon->ipc = 1;
3728 }
3729 } else if (length == 2) {
3730 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3731 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05003732 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00003733 }
3734 }
Steve French50c2f752007-07-13 00:33:32 +00003735 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04003736 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003738
3739 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04003740 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06003741 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00003742 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04003743 nls_codepage);
3744
Joe Perchesf96637b2013-05-04 22:12:25 -05003745 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003746
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003747 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00003748 (smb_buffer_response->WordCount == 7))
3749 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00003750 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3751 else
3752 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05003753 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003755 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 ses->ipc_tid = smb_buffer_response->Tid;
3757 }
3758
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00003759 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 return rc;
3761}
3762
Al Viro2a9b9952011-06-17 09:27:16 -04003763void
3764cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765{
Jeff Laytonb647c352010-10-28 11:16:44 -04003766 struct rb_root *root = &cifs_sb->tlink_tree;
3767 struct rb_node *node;
3768 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
Jeff Layton2de970f2010-10-06 19:51:12 -04003770 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
3771
Jeff Laytonb647c352010-10-28 11:16:44 -04003772 spin_lock(&cifs_sb->tlink_tree_lock);
3773 while ((node = rb_first(root))) {
3774 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3775 cifs_get_tlink(tlink);
3776 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3777 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00003778
Jeff Laytonb647c352010-10-28 11:16:44 -04003779 spin_unlock(&cifs_sb->tlink_tree_lock);
3780 cifs_put_tlink(tlink);
3781 spin_lock(&cifs_sb->tlink_tree_lock);
3782 }
3783 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003784
Al Virodd854462011-06-17 08:24:42 -04003785 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04003786 kfree(cifs_sb->mountdata);
3787 unload_nls(cifs_sb->local_nls);
3788 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00003789}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003791int
3792cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793{
3794 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04003795 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003797 if (!server->ops->need_neg || !server->ops->negotiate)
3798 return -ENOSYS;
3799
Jeff Layton198b5682010-04-24 07:57:48 -04003800 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003801 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04003802 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
Pavel Shilovsky45275782012-05-17 17:53:29 +04003804 set_credits(server, 1);
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003805
3806 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04003807 if (rc == 0) {
3808 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04003809 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04003810 server->tcpStatus = CifsGood;
3811 else
3812 rc = -EHOSTDOWN;
3813 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 }
Steve French26b994f2008-08-06 05:11:33 +00003815
Jeff Layton198b5682010-04-24 07:57:48 -04003816 return rc;
3817}
Steve French26b994f2008-08-06 05:11:33 +00003818
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003819int
3820cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
3821 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04003822{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003823 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04003824 struct TCP_Server_Info *server = ses->server;
3825
3826 ses->flags = 0;
3827 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00003828 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003829 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00003830
Joe Perchesf96637b2013-05-04 22:12:25 -05003831 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00003832 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04003833
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04003834 if (server->ops->sess_setup)
3835 rc = server->ops->sess_setup(xid, ses, nls_info);
3836
Steve French26b994f2008-08-06 05:11:33 +00003837 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003838 cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Steve French26b994f2008-08-06 05:11:33 +00003839 } else {
Dan Carpenterb13ce4b2013-04-10 14:43:00 +03003840 mutex_lock(&server->srv_mutex);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003841 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003842 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003843 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003844 server->sequence_number = 0x2;
3845 server->session_estab = true;
3846 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003847 }
3848 mutex_unlock(&server->srv_mutex);
3849
Joe Perchesf96637b2013-05-04 22:12:25 -05003850 cifs_dbg(FYI, "CIFS Session Established successfully\n");
Steve French20418ac2009-04-30 16:13:32 +00003851 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04003852 ses->status = CifsGood;
3853 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00003854 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00003855 }
3856
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003857 kfree(ses->auth_key.response);
3858 ses->auth_key.response = NULL;
3859 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003860 kfree(ses->ntlmssp);
3861 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003862
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 return rc;
3864}
3865
Jeff Layton8a8798a2012-01-17 16:09:15 -05003866static int
3867cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
3868{
3869 switch (ses->server->secType) {
3870 case Kerberos:
3871 vol->secFlg = CIFSSEC_MUST_KRB5;
3872 return 0;
3873 case NTLMv2:
3874 vol->secFlg = CIFSSEC_MUST_NTLMV2;
3875 break;
3876 case NTLM:
3877 vol->secFlg = CIFSSEC_MUST_NTLM;
3878 break;
3879 case RawNTLMSSP:
3880 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
3881 break;
3882 case LANMAN:
3883 vol->secFlg = CIFSSEC_MUST_LANMAN;
3884 break;
3885 }
3886
3887 return cifs_set_cifscreds(vol, ses);
3888}
3889
Steve French96daf2b2011-05-27 04:34:02 +00003890static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003891cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04003892{
Jeff Layton8a8798a2012-01-17 16:09:15 -05003893 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00003894 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
3895 struct cifs_ses *ses;
3896 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04003897 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04003898
3899 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03003900 if (vol_info == NULL)
3901 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04003902
Jeff Layton9d002df2010-10-06 19:51:11 -04003903 vol_info->local_nls = cifs_sb->local_nls;
3904 vol_info->linux_uid = fsuid;
3905 vol_info->cred_uid = fsuid;
3906 vol_info->UNC = master_tcon->treeName;
3907 vol_info->retry = master_tcon->retry;
3908 vol_info->nocase = master_tcon->nocase;
3909 vol_info->local_lease = master_tcon->local_lease;
3910 vol_info->no_linux_ext = !master_tcon->unix_ext;
3911
Jeff Layton8a8798a2012-01-17 16:09:15 -05003912 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
3913 if (rc) {
3914 tcon = ERR_PTR(rc);
3915 goto out;
3916 }
Jeff Layton9d002df2010-10-06 19:51:11 -04003917
3918 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303919 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003920 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303921 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003922
3923 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
3924 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00003925 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04003926 cifs_put_tcp_session(master_tcon->ses->server);
3927 goto out;
3928 }
3929
3930 tcon = cifs_get_tcon(ses, vol_info);
3931 if (IS_ERR(tcon)) {
3932 cifs_put_smb_ses(ses);
3933 goto out;
3934 }
3935
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04003936 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04003937 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
3938out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05003939 kfree(vol_info->username);
3940 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04003941 kfree(vol_info);
3942
3943 return tcon;
3944}
3945
Steve French96daf2b2011-05-27 04:34:02 +00003946struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04003947cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
3948{
3949 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
3950}
3951
3952static int
3953cifs_sb_tcon_pending_wait(void *unused)
3954{
3955 schedule();
3956 return signal_pending(current) ? -ERESTARTSYS : 0;
3957}
3958
Jeff Laytonb647c352010-10-28 11:16:44 -04003959/* find and return a tlink with given uid */
3960static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003961tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04003962{
3963 struct rb_node *node = root->rb_node;
3964 struct tcon_link *tlink;
3965
3966 while (node) {
3967 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3968
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003969 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003970 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003971 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003972 node = node->rb_right;
3973 else
3974 return tlink;
3975 }
3976 return NULL;
3977}
3978
3979/* insert a tcon_link into the tree */
3980static void
3981tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
3982{
3983 struct rb_node **new = &(root->rb_node), *parent = NULL;
3984 struct tcon_link *tlink;
3985
3986 while (*new) {
3987 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
3988 parent = *new;
3989
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08003990 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04003991 new = &((*new)->rb_left);
3992 else
3993 new = &((*new)->rb_right);
3994 }
3995
3996 rb_link_node(&new_tlink->tl_rbnode, parent, new);
3997 rb_insert_color(&new_tlink->tl_rbnode, root);
3998}
3999
Jeff Layton9d002df2010-10-06 19:51:11 -04004000/*
4001 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4002 * current task.
4003 *
4004 * If the superblock doesn't refer to a multiuser mount, then just return
4005 * the master tcon for the mount.
4006 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304007 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004008 * exists, then check to see if it's pending construction. If it is then wait
4009 * for construction to complete. Once it's no longer pending, check to see if
4010 * it failed and either return an error or retry construction, depending on
4011 * the timeout.
4012 *
4013 * If one doesn't exist then insert a new tcon_link struct into the tree and
4014 * try to construct a new one.
4015 */
4016struct tcon_link *
4017cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4018{
4019 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08004020 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004021 struct tcon_link *tlink, *newtlink;
4022
4023 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4024 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4025
4026 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004027 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004028 if (tlink)
4029 cifs_get_tlink(tlink);
4030 spin_unlock(&cifs_sb->tlink_tree_lock);
4031
4032 if (tlink == NULL) {
4033 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4034 if (newtlink == NULL)
4035 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004036 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004037 newtlink->tl_tcon = ERR_PTR(-EACCES);
4038 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4039 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4040 cifs_get_tlink(newtlink);
4041
Jeff Layton9d002df2010-10-06 19:51:11 -04004042 spin_lock(&cifs_sb->tlink_tree_lock);
4043 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004044 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004045 if (tlink) {
4046 cifs_get_tlink(tlink);
4047 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004048 kfree(newtlink);
4049 goto wait_for_construction;
4050 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004051 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004052 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4053 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004054 } else {
4055wait_for_construction:
4056 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4057 cifs_sb_tcon_pending_wait,
4058 TASK_INTERRUPTIBLE);
4059 if (ret) {
4060 cifs_put_tlink(tlink);
4061 return ERR_PTR(ret);
4062 }
4063
4064 /* if it's good, return it */
4065 if (!IS_ERR(tlink->tl_tcon))
4066 return tlink;
4067
4068 /* return error if we tried this already recently */
4069 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4070 cifs_put_tlink(tlink);
4071 return ERR_PTR(-EACCES);
4072 }
4073
4074 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4075 goto wait_for_construction;
4076 }
4077
4078 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4079 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4080 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4081
4082 if (IS_ERR(tlink->tl_tcon)) {
4083 cifs_put_tlink(tlink);
4084 return ERR_PTR(-EACCES);
4085 }
4086
4087 return tlink;
4088}
Jeff Layton2de970f2010-10-06 19:51:12 -04004089
4090/*
4091 * periodic workqueue job that scans tcon_tree for a superblock and closes
4092 * out tcons.
4093 */
4094static void
4095cifs_prune_tlinks(struct work_struct *work)
4096{
4097 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4098 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004099 struct rb_root *root = &cifs_sb->tlink_tree;
4100 struct rb_node *node = rb_first(root);
4101 struct rb_node *tmp;
4102 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004103
Jeff Laytonb647c352010-10-28 11:16:44 -04004104 /*
4105 * Because we drop the spinlock in the loop in order to put the tlink
4106 * it's not guarded against removal of links from the tree. The only
4107 * places that remove entries from the tree are this function and
4108 * umounts. Because this function is non-reentrant and is canceled
4109 * before umount can proceed, this is safe.
4110 */
4111 spin_lock(&cifs_sb->tlink_tree_lock);
4112 node = rb_first(root);
4113 while (node != NULL) {
4114 tmp = node;
4115 node = rb_next(tmp);
4116 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4117
4118 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4119 atomic_read(&tlink->tl_count) != 0 ||
4120 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4121 continue;
4122
4123 cifs_get_tlink(tlink);
4124 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4125 rb_erase(tmp, root);
4126
Jeff Layton2de970f2010-10-06 19:51:12 -04004127 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004128 cifs_put_tlink(tlink);
4129 spin_lock(&cifs_sb->tlink_tree_lock);
4130 }
4131 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004132
Jeff Laytonda472fc2012-03-23 14:40:53 -04004133 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004134 TLINK_IDLE_EXPIRE);
4135}