blob: ce033d74f315087695b8bc83d27f15876938f8d3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve Frenchd185cda2009-04-30 17:45:10 +00004 * Copyright (C) International Business Machines Corp., 2002,2009
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
Jeff Laytonc74093b2011-01-11 07:24:23 -050059/* SMB echo "timeout" -- FIXME: tunable? */
60#define SMB_ECHO_INTERVAL (60 * HZ)
61
Linus Torvalds1da177e2005-04-16 15:20:36 -070062extern mempool_t *cifs_req_poolp;
63
Jeff Layton2de970f2010-10-06 19:51:12 -040064/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040065#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040066#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040067
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040068enum {
69
70 /* Mount options that take no arguments */
71 Opt_user_xattr, Opt_nouser_xattr,
72 Opt_forceuid, Opt_noforceuid,
73 Opt_noblocksend, Opt_noautotune,
74 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
75 Opt_mapchars, Opt_nomapchars, Opt_sfu,
76 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
77 Opt_noposixpaths, Opt_nounix,
78 Opt_nocase,
79 Opt_brl, Opt_nobrl,
80 Opt_forcemandatorylock, Opt_setuids,
81 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
82 Opt_nohard, Opt_nosoft,
83 Opt_nointr, Opt_intr,
84 Opt_nostrictsync, Opt_strictsync,
85 Opt_serverino, Opt_noserverino,
86 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
87 Opt_acl, Opt_noacl, Opt_locallease,
88 Opt_sign, Opt_seal, Opt_direct,
89 Opt_strictcache, Opt_noac,
90 Opt_fsc, Opt_mfsymlinks,
Jeff Laytond8162552012-03-23 14:40:56 -040091 Opt_multiuser, Opt_sloppy,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040092
93 /* Mount options which take numeric value */
94 Opt_backupuid, Opt_backupgid, Opt_uid,
95 Opt_cruid, Opt_gid, Opt_file_mode,
96 Opt_dirmode, Opt_port,
97 Opt_rsize, Opt_wsize, Opt_actimeo,
98
99 /* Mount options which take string value */
100 Opt_user, Opt_pass, Opt_ip,
101 Opt_unc, Opt_domain,
102 Opt_srcaddr, Opt_prefixpath,
103 Opt_iocharset, Opt_sockopt,
104 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400105 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400106
107 /* Mount options to be ignored */
108 Opt_ignore,
109
110 /* Options which could be blank */
111 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100112 Opt_blank_user,
113 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400114
115 Opt_err
116};
117
118static const match_table_t cifs_mount_option_tokens = {
119
120 { Opt_user_xattr, "user_xattr" },
121 { Opt_nouser_xattr, "nouser_xattr" },
122 { Opt_forceuid, "forceuid" },
123 { Opt_noforceuid, "noforceuid" },
124 { Opt_noblocksend, "noblocksend" },
125 { Opt_noautotune, "noautotune" },
126 { Opt_hard, "hard" },
127 { Opt_soft, "soft" },
128 { Opt_perm, "perm" },
129 { Opt_noperm, "noperm" },
130 { Opt_mapchars, "mapchars" },
131 { Opt_nomapchars, "nomapchars" },
132 { Opt_sfu, "sfu" },
133 { Opt_nosfu, "nosfu" },
134 { Opt_nodfs, "nodfs" },
135 { Opt_posixpaths, "posixpaths" },
136 { Opt_noposixpaths, "noposixpaths" },
137 { Opt_nounix, "nounix" },
138 { Opt_nounix, "nolinux" },
139 { Opt_nocase, "nocase" },
140 { Opt_nocase, "ignorecase" },
141 { Opt_brl, "brl" },
142 { Opt_nobrl, "nobrl" },
143 { Opt_nobrl, "nolock" },
144 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400145 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400146 { Opt_setuids, "setuids" },
147 { Opt_nosetuids, "nosetuids" },
148 { Opt_dynperm, "dynperm" },
149 { Opt_nodynperm, "nodynperm" },
150 { Opt_nohard, "nohard" },
151 { Opt_nosoft, "nosoft" },
152 { Opt_nointr, "nointr" },
153 { Opt_intr, "intr" },
154 { Opt_nostrictsync, "nostrictsync" },
155 { Opt_strictsync, "strictsync" },
156 { Opt_serverino, "serverino" },
157 { Opt_noserverino, "noserverino" },
158 { Opt_rwpidforward, "rwpidforward" },
159 { Opt_cifsacl, "cifsacl" },
160 { Opt_nocifsacl, "nocifsacl" },
161 { Opt_acl, "acl" },
162 { Opt_noacl, "noacl" },
163 { Opt_locallease, "locallease" },
164 { Opt_sign, "sign" },
165 { Opt_seal, "seal" },
166 { Opt_direct, "direct" },
Jeff Layton531c8ff2012-05-16 07:12:26 -0400167 { Opt_direct, "directio" },
168 { Opt_direct, "forcedirectio" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400169 { Opt_strictcache, "strictcache" },
170 { Opt_noac, "noac" },
171 { Opt_fsc, "fsc" },
172 { Opt_mfsymlinks, "mfsymlinks" },
173 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400174 { Opt_sloppy, "sloppy" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400175
176 { Opt_backupuid, "backupuid=%s" },
177 { Opt_backupgid, "backupgid=%s" },
178 { Opt_uid, "uid=%s" },
179 { Opt_cruid, "cruid=%s" },
180 { Opt_gid, "gid=%s" },
181 { Opt_file_mode, "file_mode=%s" },
182 { Opt_dirmode, "dirmode=%s" },
183 { Opt_dirmode, "dir_mode=%s" },
184 { Opt_port, "port=%s" },
185 { Opt_rsize, "rsize=%s" },
186 { Opt_wsize, "wsize=%s" },
187 { Opt_actimeo, "actimeo=%s" },
188
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100189 { Opt_blank_user, "user=" },
190 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400191 { Opt_user, "user=%s" },
192 { Opt_user, "username=%s" },
193 { Opt_blank_pass, "pass=" },
194 { Opt_pass, "pass=%s" },
195 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100196 { Opt_blank_ip, "ip=" },
197 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400198 { Opt_ip, "ip=%s" },
199 { Opt_ip, "addr=%s" },
200 { Opt_unc, "unc=%s" },
201 { Opt_unc, "target=%s" },
202 { Opt_unc, "path=%s" },
203 { Opt_domain, "dom=%s" },
204 { Opt_domain, "domain=%s" },
205 { Opt_domain, "workgroup=%s" },
206 { Opt_srcaddr, "srcaddr=%s" },
207 { Opt_prefixpath, "prefixpath=%s" },
208 { Opt_iocharset, "iocharset=%s" },
209 { Opt_sockopt, "sockopt=%s" },
210 { Opt_netbiosname, "netbiosname=%s" },
211 { Opt_servern, "servern=%s" },
212 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400213 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400214 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400215 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400216
217 { Opt_ignore, "cred" },
218 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400219 { Opt_ignore, "cred=%s" },
220 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400221 { Opt_ignore, "guest" },
222 { Opt_ignore, "rw" },
223 { Opt_ignore, "ro" },
224 { Opt_ignore, "suid" },
225 { Opt_ignore, "nosuid" },
226 { Opt_ignore, "exec" },
227 { Opt_ignore, "noexec" },
228 { Opt_ignore, "nodev" },
229 { Opt_ignore, "noauto" },
230 { Opt_ignore, "dev" },
231 { Opt_ignore, "mand" },
232 { Opt_ignore, "nomand" },
233 { Opt_ignore, "_netdev" },
234
235 { Opt_err, NULL }
236};
237
238enum {
239 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
240 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
241 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i,
242 Opt_sec_nontlm, Opt_sec_lanman,
243 Opt_sec_none,
244
245 Opt_sec_err
246};
247
248static const match_table_t cifs_secflavor_tokens = {
249 { Opt_sec_krb5, "krb5" },
250 { Opt_sec_krb5i, "krb5i" },
251 { Opt_sec_krb5p, "krb5p" },
252 { Opt_sec_ntlmsspi, "ntlmsspi" },
253 { Opt_sec_ntlmssp, "ntlmssp" },
254 { Opt_ntlm, "ntlm" },
255 { Opt_sec_ntlmi, "ntlmi" },
256 { Opt_sec_ntlmv2i, "ntlmv2i" },
257 { Opt_sec_nontlm, "nontlm" },
258 { Opt_sec_lanman, "lanman" },
259 { Opt_sec_none, "none" },
260
261 { Opt_sec_err, NULL }
262};
263
Jeff Layton15b6a472012-05-16 07:50:15 -0400264/* cache flavors */
265enum {
266 Opt_cache_loose,
267 Opt_cache_strict,
268 Opt_cache_none,
269 Opt_cache_err
270};
271
272static const match_table_t cifs_cacheflavor_tokens = {
273 { Opt_cache_loose, "loose" },
274 { Opt_cache_strict, "strict" },
275 { Opt_cache_none, "none" },
276 { Opt_cache_err, NULL }
277};
278
Jeff Layton23db65f2012-05-15 12:20:51 -0400279static const match_table_t cifs_smb_version_tokens = {
280 { Smb_1, SMB1_VERSION_STRING },
281};
282
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300283static int ip_connect(struct TCP_Server_Info *server);
284static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400285static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400286static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400287static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
288 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Jeff Laytond5c56052008-12-01 18:42:33 -0500290/*
291 * cifs tcp session reconnection
292 *
293 * mark tcp session as reconnecting so temporarily locked
294 * mark all smb sessions as reconnecting for tcp session
295 * reconnect tcp session
296 * wake up waiters on reconnection? - (not needed currently)
297 */
Steve French2cd646a2006-09-28 19:43:08 +0000298static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299cifs_reconnect(struct TCP_Server_Info *server)
300{
301 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500302 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000303 struct cifs_ses *ses;
304 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000305 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400306 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000307
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000309 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000310 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 next time through the loop */
312 spin_unlock(&GlobalMid_Lock);
313 return rc;
314 } else
315 server->tcpStatus = CifsNeedReconnect;
316 spin_unlock(&GlobalMid_Lock);
317 server->maxBuf = 0;
318
Joe Perchesb6b38f72010-04-21 03:50:45 +0000319 cFYI(1, "Reconnecting tcp session");
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 */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500323 cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530324 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500325 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000326 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500327 ses->need_reconnect = true;
328 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500329 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000330 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500331 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530334 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500335
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 /* do not want to be sending data on a socket we are freeing */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500337 cFYI(1, "%s: tearing down socket", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500338 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000339 if (server->ssocket) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000340 cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
341 server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800342 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000343 cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx",
Steve French467a8f82007-06-27 22:41:32 +0000344 server->ssocket->state,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000345 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);
359 cFYI(1, "%s: moving mids to private list", __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
369 cFYI(1, "%s: issuing mid callbacks", __func__);
370 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 Perchesb6b38f72010-04-21 03:50:45 +0000382 cFYI(1, "reconnect error %d", 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
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000396/*
Steve Frenche4eb2952005-04-28 22:41:09 -0700397 return codes:
398 0 not a transact2, or all data present
399 >0 transact2 with that much data missing
400 -EINVAL = invalid transact2
401
402 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400403static int check2ndT2(char *buf)
Steve Frenche4eb2952005-04-28 22:41:09 -0700404{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400405 struct smb_hdr *pSMB = (struct smb_hdr *)buf;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000406 struct smb_t2_rsp *pSMBt;
Steve Frenche4eb2952005-04-28 22:41:09 -0700407 int remaining;
Jeff Layton26ec2542011-01-20 13:36:51 -0500408 __u16 total_data_size, data_in_this_rsp;
Steve Frenche4eb2952005-04-28 22:41:09 -0700409
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000410 if (pSMB->Command != SMB_COM_TRANSACTION2)
Steve Frenche4eb2952005-04-28 22:41:09 -0700411 return 0;
412
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000413 /* check for plausible wct, bcc and t2 data and parm sizes */
414 /* check for parm and data offset going beyond end of smb */
415 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
Joe Perchesb6b38f72010-04-21 03:50:45 +0000416 cFYI(1, "invalid transact2 word count");
Steve Frenche4eb2952005-04-28 22:41:09 -0700417 return -EINVAL;
418 }
419
420 pSMBt = (struct smb_t2_rsp *)pSMB;
421
Jeff Layton26ec2542011-01-20 13:36:51 -0500422 total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
423 data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700424
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400425 if (total_data_size == data_in_this_rsp)
Steve Frenche4eb2952005-04-28 22:41:09 -0700426 return 0;
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400427 else if (total_data_size < data_in_this_rsp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000428 cFYI(1, "total data %d smaller than data in frame %d",
429 total_data_size, data_in_this_rsp);
Steve Frenche4eb2952005-04-28 22:41:09 -0700430 return -EINVAL;
Steve Frenche4eb2952005-04-28 22:41:09 -0700431 }
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400432
433 remaining = total_data_size - data_in_this_rsp;
434
435 cFYI(1, "missing %d bytes from transact2, check next response",
436 remaining);
Jeff Laytonc974bef2011-10-11 06:41:32 -0400437 if (total_data_size > CIFSMaxBufSize) {
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400438 cERROR(1, "TotalDataSize %d is over maximum buffer %d",
Jeff Laytonc974bef2011-10-11 06:41:32 -0400439 total_data_size, CIFSMaxBufSize);
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400440 return -EINVAL;
441 }
442 return remaining;
Steve Frenche4eb2952005-04-28 22:41:09 -0700443}
444
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400445static int coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
Steve Frenche4eb2952005-04-28 22:41:09 -0700446{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400447 struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
448 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500449 char *data_area_of_tgt;
450 char *data_area_of_src;
Jeff Layton26ec2542011-01-20 13:36:51 -0500451 int remaining;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500452 unsigned int byte_count, total_in_tgt;
453 __u16 tgt_total_cnt, src_total_cnt, total_in_src;
Steve Frenche4eb2952005-04-28 22:41:09 -0700454
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500455 src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
456 tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700457
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500458 if (tgt_total_cnt != src_total_cnt)
459 cFYI(1, "total data count of primary and secondary t2 differ "
460 "source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
Steve Frenche4eb2952005-04-28 22:41:09 -0700461
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500462 total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700463
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500464 remaining = tgt_total_cnt - total_in_tgt;
Steve French50c2f752007-07-13 00:33:32 +0000465
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500466 if (remaining < 0) {
467 cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
468 "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400469 return -EPROTO;
Steve Frenche4eb2952005-04-28 22:41:09 -0700470 }
471
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500472 if (remaining == 0) {
473 /* nothing to do, ignore */
474 cFYI(1, "no more data remains");
475 return 0;
476 }
477
478 total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
479 if (remaining < total_in_src)
480 cFYI(1, "transact2 2nd response contains too much data");
481
Steve Frenche4eb2952005-04-28 22:41:09 -0700482 /* find end of first SMB data area */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500483 data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
Jeff Layton26ec2542011-01-20 13:36:51 -0500484 get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500485
Steve Frenche4eb2952005-04-28 22:41:09 -0700486 /* validate target area */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500487 data_area_of_src = (char *)&pSMBs->hdr.Protocol +
488 get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
Steve Frenche4eb2952005-04-28 22:41:09 -0700489
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500490 data_area_of_tgt += total_in_tgt;
Steve Frenche4eb2952005-04-28 22:41:09 -0700491
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500492 total_in_tgt += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400493 /* is the result too big for the field? */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500494 if (total_in_tgt > USHRT_MAX) {
495 cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400496 return -EPROTO;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500497 }
498 put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400499
500 /* fix up the BCC */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400501 byte_count = get_bcc(target_hdr);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500502 byte_count += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400503 /* is the result too big for the field? */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500504 if (byte_count > USHRT_MAX) {
505 cFYI(1, "coalesced BCC too large (%u)", byte_count);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400506 return -EPROTO;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500507 }
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400508 put_bcc(byte_count, target_hdr);
Steve Frenche4eb2952005-04-28 22:41:09 -0700509
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400510 byte_count = be32_to_cpu(target_hdr->smb_buf_length);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500511 byte_count += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400512 /* don't allow buffer to overflow */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500513 if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
514 cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400515 return -ENOBUFS;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500516 }
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400517 target_hdr->smb_buf_length = cpu_to_be32(byte_count);
Steve Frenche4eb2952005-04-28 22:41:09 -0700518
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500519 /* copy second buffer into end of first buffer */
520 memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400521
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500522 if (remaining != total_in_src) {
523 /* more responses to go */
524 cFYI(1, "waiting for more secondary responses");
Steve Frenche4eb2952005-04-28 22:41:09 -0700525 return 1;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500526 }
527
528 /* we are done */
529 cFYI(1, "found the last secondary response");
530 return 0;
Steve Frenche4eb2952005-04-28 22:41:09 -0700531}
532
Jeff Laytonc74093b2011-01-11 07:24:23 -0500533static void
534cifs_echo_request(struct work_struct *work)
535{
536 int rc;
537 struct TCP_Server_Info *server = container_of(work,
538 struct TCP_Server_Info, echo.work);
539
Jeff Layton247ec9b2011-02-04 17:09:50 -0500540 /*
Jeff Layton195291e2011-02-09 12:01:42 -0500541 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is
542 * done, which is indicated by maxBuf != 0. Also, no need to ping if
543 * we got a response recently
Jeff Layton247ec9b2011-02-04 17:09:50 -0500544 */
Jeff Layton195291e2011-02-09 12:01:42 -0500545 if (server->maxBuf == 0 ||
Jeff Layton247ec9b2011-02-04 17:09:50 -0500546 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500547 goto requeue_echo;
548
549 rc = CIFSSMBEcho(server);
550 if (rc)
551 cFYI(1, "Unable to send echo request to server: %s",
552 server->hostname);
553
554requeue_echo:
Jeff Laytonda472fc2012-03-23 14:40:53 -0400555 queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500556}
557
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400558static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400559allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400560{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400561 if (!server->bigbuf) {
562 server->bigbuf = (char *)cifs_buf_get();
563 if (!server->bigbuf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400564 cERROR(1, "No memory for large SMB response");
565 msleep(3000);
566 /* retry will check if exiting */
567 return false;
568 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400569 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400570 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400571 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400572 }
573
Jeff Layton2a37ef92011-10-19 15:29:23 -0400574 if (!server->smallbuf) {
575 server->smallbuf = (char *)cifs_small_buf_get();
576 if (!server->smallbuf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400577 cERROR(1, "No memory for SMB response");
578 msleep(1000);
579 /* retry will check if exiting */
580 return false;
581 }
582 /* beginning of smb buffer is cleared in our buf_get */
583 } else {
584 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400585 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400586 }
587
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400588 return true;
589}
590
Jeff Laytonba749e62011-10-11 06:41:32 -0400591static bool
592server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400593{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300594 /*
595 * We need to wait 2 echo intervals to make sure we handle such
596 * situations right:
597 * 1s client sends a normal SMB request
598 * 2s client gets a response
599 * 30s echo workqueue job pops, and decides we got a response recently
600 * and don't need to send another
601 * ...
602 * 65s kernel_recvmsg times out, and we see that we haven't gotten
603 * a response in >60s.
604 */
605 if (server->tcpStatus == CifsGood &&
606 time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
Jeff Laytonba749e62011-10-11 06:41:32 -0400607 cERROR(1, "Server %s has not responded in %d seconds. "
608 "Reconnecting...", server->hostname,
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300609 (2 * SMB_ECHO_INTERVAL) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400610 cifs_reconnect(server);
611 wake_up(&server->response_q);
612 return true;
613 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400614
Jeff Laytonba749e62011-10-11 06:41:32 -0400615 return false;
616}
617
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400618/*
619 * kvec_array_init - clone a kvec array, and advance into it
620 * @new: pointer to memory for cloned array
621 * @iov: pointer to original array
622 * @nr_segs: number of members in original array
623 * @bytes: number of bytes to advance into the cloned array
624 *
625 * This function will copy the array provided in iov to a section of memory
626 * and advance the specified number of bytes into the new array. It returns
627 * the number of segments in the new array. "new" must be at least as big as
628 * the original iov array.
629 */
630static unsigned int
631kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
632 size_t bytes)
633{
634 size_t base = 0;
635
636 while (bytes || !iov->iov_len) {
637 int copy = min(bytes, iov->iov_len);
638
639 bytes -= copy;
640 base += copy;
641 if (iov->iov_len == base) {
642 iov++;
643 nr_segs--;
644 base = 0;
645 }
646 }
647 memcpy(new, iov, sizeof(*iov) * nr_segs);
648 new->iov_base += base;
649 new->iov_len -= base;
650 return nr_segs;
651}
652
Jeff Layton1041e3f2011-10-19 15:28:27 -0400653static struct kvec *
654get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
655{
656 struct kvec *new_iov;
657
658 if (server->iov && nr_segs <= server->nr_iov)
659 return server->iov;
660
661 /* not big enough -- allocate a new one and release the old */
662 new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
663 if (new_iov) {
664 kfree(server->iov);
665 server->iov = new_iov;
666 server->nr_iov = nr_segs;
667 }
668 return new_iov;
669}
670
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400671int
672cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
673 unsigned int nr_segs, unsigned int to_read)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400674{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400675 int length = 0;
676 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400677 unsigned int segs;
Jeff Laytone831e6c2011-10-11 06:41:32 -0400678 struct msghdr smb_msg;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400679 struct kvec *iov;
680
Jeff Layton1041e3f2011-10-19 15:28:27 -0400681 iov = get_server_iovec(server, nr_segs);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400682 if (!iov)
683 return -ENOMEM;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400684
Jeff Laytone831e6c2011-10-11 06:41:32 -0400685 smb_msg.msg_control = NULL;
686 smb_msg.msg_controllen = 0;
687
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400688 for (total_read = 0; to_read; total_read += length, to_read -= length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500689 try_to_freeze();
690
Jeff Laytonba749e62011-10-11 06:41:32 -0400691 if (server_unresponsive(server)) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400692 total_read = -EAGAIN;
Jeff Laytonba749e62011-10-11 06:41:32 -0400693 break;
694 }
695
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400696 segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
697
698 length = kernel_recvmsg(server->ssocket, &smb_msg,
699 iov, segs, to_read, 0);
700
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400701 if (server->tcpStatus == CifsExiting) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400702 total_read = -ESHUTDOWN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400703 break;
704 } else if (server->tcpStatus == CifsNeedReconnect) {
705 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400706 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400707 break;
708 } else if (length == -ERESTARTSYS ||
709 length == -EAGAIN ||
710 length == -EINTR) {
711 /*
712 * Minimum sleep to prevent looping, allowing socket
713 * to clear and app threads to set tcpStatus
714 * CifsNeedReconnect if server hung.
715 */
716 usleep_range(1000, 2000);
717 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400718 continue;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400719 } else if (length <= 0) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400720 cFYI(1, "Received no data or error: expecting %d "
721 "got %d", to_read, length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400722 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400723 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400724 break;
725 }
726 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400727 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400728}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400729
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400730int
731cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
732 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400733{
734 struct kvec iov;
735
736 iov.iov_base = buf;
737 iov.iov_len = to_read;
738
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400739 return cifs_readv_from_socket(server, &iov, 1, to_read);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400740}
741
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400742static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400743is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400744{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400745 /*
746 * The first byte big endian of the length field,
747 * is actually not part of the length but the type
748 * with the most common, zero, as regular data.
749 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400750 switch (type) {
751 case RFC1002_SESSION_MESSAGE:
752 /* Regular SMB response */
753 return true;
754 case RFC1002_SESSION_KEEP_ALIVE:
755 cFYI(1, "RFC 1002 session keep alive");
756 break;
757 case RFC1002_POSITIVE_SESSION_RESPONSE:
758 cFYI(1, "RFC 1002 positive session response");
759 break;
760 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400761 /*
762 * We get this from Windows 98 instead of an error on
763 * SMB negprot response.
764 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400765 cFYI(1, "RFC 1002 negative session response");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400766 /* give server a second to clean up */
767 msleep(1000);
768 /*
769 * Always try 445 first on reconnect since we get NACK
770 * on some if we ever connected to port 139 (the NACK
771 * is since we do not begin with RFC1001 session
772 * initialize frame).
773 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400774 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400775 cifs_reconnect(server);
776 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400777 break;
778 default:
779 cERROR(1, "RFC 1002 unknown response type 0x%x", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400780 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400781 }
782
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400783 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400784}
785
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400786void
787dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400788{
789#ifdef CONFIG_CIFS_STATS2
790 mid->when_received = jiffies;
791#endif
792 spin_lock(&GlobalMid_Lock);
793 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400794 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400795 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400796 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400797 list_del_init(&mid->qhead);
798 spin_unlock(&GlobalMid_Lock);
799}
800
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400801static void
802handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400803 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400804{
Jeff Laytonffc00e22011-10-19 15:29:13 -0400805 if (malformed == 0 && check2ndT2(buf) > 0) {
806 mid->multiRsp = true;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400807 if (mid->resp_buf) {
808 /* merge response - fix up 1st*/
Jeff Laytonffc00e22011-10-19 15:29:13 -0400809 malformed = coalesce_t2(buf, mid->resp_buf);
810 if (malformed > 0)
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400811 return;
Jeff Laytonffc00e22011-10-19 15:29:13 -0400812
Jeff Laytonea1f4502011-10-19 15:29:05 -0400813 /* All parts received or packet is malformed. */
814 mid->multiEnd = true;
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400815 return dequeue_mid(mid, malformed);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400816 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400817 if (!server->large_buf) {
Jeff Laytonea1f4502011-10-19 15:29:05 -0400818 /*FIXME: switch to already allocated largebuf?*/
819 cERROR(1, "1st trans2 resp needs bigbuf");
820 } else {
821 /* Have first buffer */
822 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400823 mid->large_buf = true;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400824 server->bigbuf = NULL;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400825 }
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400826 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400827 }
828 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400829 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400830 /* Was previous buf put in mpx struct for multi-rsp? */
831 if (!mid->multiRsp) {
832 /* smb buffer will be freed by user thread */
833 if (server->large_buf)
834 server->bigbuf = NULL;
835 else
836 server->smallbuf = NULL;
837 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400838 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400839}
840
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400841static void clean_demultiplex_info(struct TCP_Server_Info *server)
842{
843 int length;
844
845 /* take it off the list, if it's not already */
846 spin_lock(&cifs_tcp_ses_lock);
847 list_del_init(&server->tcp_ses_list);
848 spin_unlock(&cifs_tcp_ses_lock);
849
850 spin_lock(&GlobalMid_Lock);
851 server->tcpStatus = CifsExiting;
852 spin_unlock(&GlobalMid_Lock);
853 wake_up_all(&server->response_q);
854
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400855 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300856 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400857 if (server->credits <= 0)
858 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300859 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400860 /*
861 * Although there should not be any requests blocked on this queue it
862 * can not hurt to be paranoid and try to wake up requests that may
863 * haven been blocked when more than 50 at time were on the wire to the
864 * same server - they now will see the session is in exit state and get
865 * out of SendReceive.
866 */
867 wake_up_all(&server->request_q);
868 /* give those requests time to exit */
869 msleep(125);
870
871 if (server->ssocket) {
872 sock_release(server->ssocket);
873 server->ssocket = NULL;
874 }
875
876 if (!list_empty(&server->pending_mid_q)) {
877 struct list_head dispose_list;
878 struct mid_q_entry *mid_entry;
879 struct list_head *tmp, *tmp2;
880
881 INIT_LIST_HEAD(&dispose_list);
882 spin_lock(&GlobalMid_Lock);
883 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
884 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400885 cFYI(1, "Clearing mid 0x%llx", mid_entry->mid);
886 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400887 list_move(&mid_entry->qhead, &dispose_list);
888 }
889 spin_unlock(&GlobalMid_Lock);
890
891 /* now walk dispose list and issue callbacks */
892 list_for_each_safe(tmp, tmp2, &dispose_list) {
893 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400894 cFYI(1, "Callback mid 0x%llx", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400895 list_del_init(&mid_entry->qhead);
896 mid_entry->callback(mid_entry);
897 }
898 /* 1/8th of sec is more than enough time for them to exit */
899 msleep(125);
900 }
901
902 if (!list_empty(&server->pending_mid_q)) {
903 /*
904 * mpx threads have not exited yet give them at least the smb
905 * send timeout time for long ops.
906 *
907 * Due to delays on oplock break requests, we need to wait at
908 * least 45 seconds before giving up on a request getting a
909 * response and going ahead and killing cifsd.
910 */
911 cFYI(1, "Wait for exit from demultiplex thread");
912 msleep(46000);
913 /*
914 * If threads still have not exited they are probably never
915 * coming home not much else we can do but free the memory.
916 */
917 }
918
919 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400920 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400921 kfree(server);
922
923 length = atomic_dec_return(&tcpSesAllocCount);
924 if (length > 0)
925 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
926 GFP_KERNEL);
927}
928
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400929static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400930standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
931{
932 int length;
933 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400934 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400935
936 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400937 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Jeff Laytone9097ab2011-10-19 15:29:40 -0400938 cERROR(1, "SMB response too long (%u bytes)",
939 pdu_length);
940 cifs_reconnect(server);
941 wake_up(&server->response_q);
942 return -EAGAIN;
943 }
944
945 /* switch to large buffer if too big for a small one */
946 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
947 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400948 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400949 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400950 }
951
952 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400953 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
954 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400955 if (length < 0)
956 return length;
957 server->total_read += length;
958
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400959 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400960
961 /*
962 * We know that we received enough to get to the MID as we
963 * checked the pdu_length earlier. Now check to see
964 * if the rest of the header is OK. We borrow the length
965 * var for the rest of the loop to avoid a new stack var.
966 *
967 * 48 bytes is enough to display the header and a little bit
968 * into the payload for debugging purposes.
969 */
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400970 length = server->ops->check_message(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400971 if (length != 0)
972 cifs_dump_mem("Bad SMB: ", buf,
973 min_t(unsigned int, server->total_read, 48));
974
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500975 if (!mid)
976 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400977
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400978 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500979 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400980}
981
982static int
Al Viro7c97c202011-06-21 08:51:28 -0400983cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984{
985 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400986 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400987 unsigned int pdu_length;
988 char *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 struct task_struct *task_to_wake = NULL;
990 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 current->flags |= PF_MEMALLOC;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000993 cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400994
995 length = atomic_inc_return(&tcpSesAllocCount);
996 if (length > 1)
Steve French26f57362007-08-30 22:09:15 +0000997 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
998 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001000 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +00001001 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001002 if (try_to_freeze())
1003 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001004
Jeff Layton2a37ef92011-10-19 15:29:23 -04001005 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001006 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001007
Jeff Layton2a37ef92011-10-19 15:29:23 -04001008 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001009 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001010 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001011
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001012 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001013 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001014 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001015 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001016
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001017 /*
1018 * The right amount was read from socket - 4 bytes,
1019 * so we can now interpret the length field.
1020 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001021 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001022
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001023 cFYI(1, "RFC1002 header 0x%x", pdu_length);
1024 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001025 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001026
Jeff Layton89482a52011-10-19 15:28:57 -04001027 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001028 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Jeff Layton89482a52011-10-19 15:28:57 -04001029 cERROR(1, "SMB response too short (%u bytes)",
1030 pdu_length);
1031 cifs_reconnect(server);
1032 wake_up(&server->response_q);
1033 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001034 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001035
Jeff Layton89482a52011-10-19 15:28:57 -04001036 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001037 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001038 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -04001039 if (length < 0)
1040 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001041 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001042
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +04001043 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001044
Jeff Layton44d22d82011-10-19 15:29:49 -04001045 if (!mid_entry || !mid_entry->receive)
1046 length = standard_receive3(server, mid_entry);
1047 else
1048 length = mid_entry->receive(server, mid_entry);
1049
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001050 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -07001051 continue;
1052
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001053 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001054 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001055
Steve Frenchfda35942011-01-20 18:06:34 +00001056 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -05001057 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -04001058 if (!mid_entry->multiRsp || mid_entry->multiEnd)
1059 mid_entry->callback(mid_entry);
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +04001060 } else if (!server->ops->is_oplock_break(buf, server)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001061 cERROR(1, "No task to wake, unknown frame received! "
Jeff Layton80975312011-01-11 07:24:02 -05001062 "NumMids %d", atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001063 cifs_dump_mem("Received Data is: ", buf,
1064 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +00001065#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +04001066 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +00001067 cifs_dump_mids(server);
1068#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +00001069
Steve Frenche4eb2952005-04-28 22:41:09 -07001070 }
1071 } /* end while !EXITING */
1072
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001073 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001074 cifs_buf_release(server->bigbuf);
1075 if (server->smallbuf) /* no sense logging a debug message if NULL */
1076 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001078 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001079 clean_demultiplex_info(server);
Steve French50c2f752007-07-13 00:33:32 +00001080
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001081 /* if server->tsk was NULL then wait for a signal before exiting */
1082 if (!task_to_wake) {
1083 set_current_state(TASK_INTERRUPTIBLE);
1084 while (!signal_pending(current)) {
1085 schedule();
1086 set_current_state(TASK_INTERRUPTIBLE);
1087 }
1088 set_current_state(TASK_RUNNING);
1089 }
1090
Jeff Layton0468a2c2008-12-01 07:09:35 -05001091 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
Jeff Laytonc359cf32007-11-16 22:22:06 +00001094/* extract the host portion of the UNC string */
1095static char *
1096extract_hostname(const char *unc)
1097{
1098 const char *src;
1099 char *dst, *delim;
1100 unsigned int len;
1101
1102 /* skip double chars at beginning of string */
1103 /* BB: check validity of these bytes? */
1104 src = unc + 2;
1105
1106 /* delimiter between hostname and sharename is always '\\' now */
1107 delim = strchr(src, '\\');
1108 if (!delim)
1109 return ERR_PTR(-EINVAL);
1110
1111 len = delim - src;
1112 dst = kmalloc((len + 1), GFP_KERNEL);
1113 if (dst == NULL)
1114 return ERR_PTR(-ENOMEM);
1115
1116 memcpy(dst, src, len);
1117 dst[len] = '\0';
1118
1119 return dst;
1120}
1121
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001122static int get_option_ul(substring_t args[], unsigned long *option)
1123{
1124 int rc;
1125 char *string;
1126
1127 string = match_strdup(args);
1128 if (string == NULL)
1129 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001130 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001131 kfree(string);
1132
1133 return rc;
1134}
1135
1136
1137static int cifs_parse_security_flavors(char *value,
1138 struct smb_vol *vol)
1139{
1140
1141 substring_t args[MAX_OPT_ARGS];
1142
1143 switch (match_token(value, cifs_secflavor_tokens, args)) {
1144 case Opt_sec_krb5:
1145 vol->secFlg |= CIFSSEC_MAY_KRB5;
1146 break;
1147 case Opt_sec_krb5i:
1148 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
1149 break;
1150 case Opt_sec_krb5p:
1151 /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
1152 cERROR(1, "Krb5 cifs privacy not supported");
1153 break;
1154 case Opt_sec_ntlmssp:
1155 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1156 break;
1157 case Opt_sec_ntlmsspi:
1158 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
1159 break;
1160 case Opt_ntlm:
1161 /* ntlm is default so can be turned off too */
1162 vol->secFlg |= CIFSSEC_MAY_NTLM;
1163 break;
1164 case Opt_sec_ntlmi:
1165 vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
1166 break;
1167 case Opt_sec_nontlm:
1168 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1169 break;
1170 case Opt_sec_ntlmv2i:
1171 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
1172 break;
1173#ifdef CONFIG_CIFS_WEAK_PW_HASH
1174 case Opt_sec_lanman:
1175 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1176 break;
1177#endif
1178 case Opt_sec_none:
1179 vol->nullauth = 1;
1180 break;
1181 default:
1182 cERROR(1, "bad security option: %s", value);
1183 return 1;
1184 }
1185
1186 return 0;
1187}
1188
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001190cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1191{
1192 substring_t args[MAX_OPT_ARGS];
1193
1194 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1195 case Opt_cache_loose:
1196 vol->direct_io = false;
1197 vol->strict_io = false;
1198 break;
1199 case Opt_cache_strict:
1200 vol->direct_io = false;
1201 vol->strict_io = true;
1202 break;
1203 case Opt_cache_none:
1204 vol->direct_io = true;
1205 vol->strict_io = false;
1206 break;
1207 default:
1208 cERROR(1, "bad cache= option: %s", value);
1209 return 1;
1210 }
1211 return 0;
1212}
1213
1214static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001215cifs_parse_smb_version(char *value, struct smb_vol *vol)
1216{
1217 substring_t args[MAX_OPT_ARGS];
1218
1219 switch (match_token(value, cifs_smb_version_tokens, args)) {
1220 case Smb_1:
1221 vol->ops = &smb1_operations;
1222 vol->vals = &smb1_values;
1223 break;
1224 default:
1225 cERROR(1, "Unknown vers= option specified: %s", value);
1226 return 1;
1227 }
1228 return 0;
1229}
1230
1231static int
Sean Finneyb9468452011-04-11 13:19:32 +00001232cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001233 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001235 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001236 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 unsigned int temp_len, i, j;
1238 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001239 short int override_uid = -1;
1240 short int override_gid = -1;
1241 bool uid_specified = false;
1242 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001243 bool sloppy = false;
1244 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001245 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001246 char *string = NULL;
1247 char *tmp_end, *value;
1248 char delim;
Jeff Layton296838b2012-05-16 07:53:01 -04001249 bool cache_specified = false;
1250 static bool cache_warned = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
1252 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001253 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001254 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Jeff Layton88463992010-11-22 15:31:03 -05001256 /*
1257 * does not have to be perfect mapping since field is
1258 * informational, only used for servers that do not support
1259 * port 445 and it can be overridden at mount time
1260 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001261 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1262 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001263 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1264
Jeff Layton1397f2e2011-01-07 11:30:28 -05001265 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001266 /* null target name indicates to use *SMBSERVR default called name
1267 if we end up sending RFC1001 session initialize */
1268 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001269 vol->cred_uid = current_uid();
1270 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001271 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001272
1273 /* default to only allowing write access to owner of the mount */
1274 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
1276 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001277 /* default is always to request posix paths. */
1278 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001279 /* default to using server inode numbers where available */
1280 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001281
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301282 vol->actimeo = CIFS_DEF_ACTIMEO;
1283
Jeff Layton23db65f2012-05-15 12:20:51 -04001284 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1285 vol->ops = &smb1_operations;
1286 vol->vals = &smb1_values;
1287
Sean Finneyb9468452011-04-11 13:19:32 +00001288 if (!mountdata)
1289 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Sean Finneyb9468452011-04-11 13:19:32 +00001291 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1292 if (!mountdata_copy)
1293 goto cifs_parse_mount_err;
1294
1295 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001296 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001297
Steve French50c2f752007-07-13 00:33:32 +00001298 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001299 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 separator[0] = options[4];
1301 options += 5;
1302 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001303 cFYI(1, "Null separator not allowed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 }
1305 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001306 vol->backupuid_specified = false; /* no backup intent for a user */
1307 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001308
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001310 substring_t args[MAX_OPT_ARGS];
1311 unsigned long option;
1312 int token;
1313
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 if (!*data)
1315 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001317 token = match_token(data, cifs_mount_option_tokens, args);
1318
1319 switch (token) {
1320
1321 /* Ingnore the following */
1322 case Opt_ignore:
1323 break;
1324
1325 /* Boolean values */
1326 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001328 break;
1329 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001331 break;
1332 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001333 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001334 break;
1335 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001336 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001337 break;
1338 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001339 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001340 break;
1341 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001342 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001343 break;
1344 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001346 break;
1347 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001349 break;
1350 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001352 break;
1353 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001355 break;
1356 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001357 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001358 break;
1359 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001360 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001361 break;
1362 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001363 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001364 break;
1365 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001366 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001367 break;
1368 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001369 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001370 break;
1371 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001372 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001373 break;
1374 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001375 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001376 break;
1377 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001378 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001379 break;
1380 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001381 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001382 break;
1383 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001384 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001385 break;
1386 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001387 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001388 /*
1389 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001390 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001391 * local vfs will do advisory
1392 */
Steve French50c2f752007-07-13 00:33:32 +00001393 if (vol->file_mode ==
1394 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001395 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001396 break;
1397 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001398 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001399 break;
1400 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001402 break;
1403 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001405 break;
1406 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001407 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001408 break;
1409 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001410 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001411 break;
1412 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001414 break;
1415 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001417 break;
1418 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001420 break;
1421 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001423 break;
1424 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001425 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001426 break;
1427 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001428 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001429 break;
1430 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001432 break;
1433 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001435 break;
1436 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001437 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001438 break;
1439 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001440 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001441 break;
1442 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001443 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001444 break;
1445 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001447 break;
1448 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001450 break;
1451 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001452 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001453 break;
1454 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001455 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001456 break;
1457 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001458 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001459 * is a per tree connection (mount) not a per socket
1460 * or per-smb connection option in the protocol
1461 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1462 */
Steve French95b1cb92008-05-15 16:44:38 +00001463 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001464 break;
1465 case Opt_direct:
Jeff Layton296838b2012-05-16 07:53:01 -04001466 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001467 vol->direct_io = true;
1468 vol->strict_io = false;
Jeff Layton09983b22012-05-16 07:53:00 -04001469 cERROR(1, "The \"directio\" option will be removed in "
1470 "3.7. Please switch to the \"cache=none\" "
1471 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001472 break;
1473 case Opt_strictcache:
Jeff Layton296838b2012-05-16 07:53:01 -04001474 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001475 vol->direct_io = false;
1476 vol->strict_io = true;
Jeff Layton09983b22012-05-16 07:53:00 -04001477 cERROR(1, "The \"strictcache\" option will be removed "
1478 "in 3.7. Please switch to the \"cache=strict\" "
1479 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001480 break;
1481 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001482 printk(KERN_WARNING "CIFS: Mount option noac not "
1483 "supported. Instead set "
1484 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001485 break;
1486 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301487#ifndef CONFIG_CIFS_FSCACHE
Jeff Layton83fb0862011-06-08 07:35:24 -04001488 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301489 "kernel config option set");
Sean Finneyb9468452011-04-11 13:19:32 +00001490 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301491#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301492 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001493 break;
1494 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001495 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001496 break;
1497 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001498 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001499 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001500 case Opt_sloppy:
1501 sloppy = true;
1502 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001503
1504 /* Numeric Values */
1505 case Opt_backupuid:
1506 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001507 cERROR(1, "%s: Invalid backupuid value",
1508 __func__);
1509 goto cifs_parse_mount_err;
1510 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001511 vol->backupuid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001512 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001513 break;
1514 case Opt_backupgid:
1515 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001516 cERROR(1, "%s: Invalid backupgid value",
1517 __func__);
1518 goto cifs_parse_mount_err;
1519 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001520 vol->backupgid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001521 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001522 break;
1523 case Opt_uid:
1524 if (get_option_ul(args, &option)) {
1525 cERROR(1, "%s: Invalid uid value",
1526 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001527 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001529 vol->linux_uid = option;
1530 uid_specified = true;
1531 break;
1532 case Opt_cruid:
1533 if (get_option_ul(args, &option)) {
1534 cERROR(1, "%s: Invalid cruid value",
1535 __func__);
1536 goto cifs_parse_mount_err;
1537 }
1538 vol->cred_uid = option;
1539 break;
1540 case Opt_gid:
1541 if (get_option_ul(args, &option)) {
1542 cERROR(1, "%s: Invalid gid value",
1543 __func__);
1544 goto cifs_parse_mount_err;
1545 }
1546 vol->linux_gid = option;
1547 gid_specified = true;
1548 break;
1549 case Opt_file_mode:
1550 if (get_option_ul(args, &option)) {
1551 cERROR(1, "%s: Invalid file_mode value",
1552 __func__);
1553 goto cifs_parse_mount_err;
1554 }
1555 vol->file_mode = option;
1556 break;
1557 case Opt_dirmode:
1558 if (get_option_ul(args, &option)) {
1559 cERROR(1, "%s: Invalid dir_mode value",
1560 __func__);
1561 goto cifs_parse_mount_err;
1562 }
1563 vol->dir_mode = option;
1564 break;
1565 case Opt_port:
1566 if (get_option_ul(args, &option)) {
1567 cERROR(1, "%s: Invalid port value",
1568 __func__);
1569 goto cifs_parse_mount_err;
1570 }
1571 vol->port = option;
1572 break;
1573 case Opt_rsize:
1574 if (get_option_ul(args, &option)) {
1575 cERROR(1, "%s: Invalid rsize value",
1576 __func__);
1577 goto cifs_parse_mount_err;
1578 }
1579 vol->rsize = option;
1580 break;
1581 case Opt_wsize:
1582 if (get_option_ul(args, &option)) {
1583 cERROR(1, "%s: Invalid wsize value",
1584 __func__);
1585 goto cifs_parse_mount_err;
1586 }
1587 vol->wsize = option;
1588 break;
1589 case Opt_actimeo:
1590 if (get_option_ul(args, &option)) {
1591 cERROR(1, "%s: Invalid actimeo value",
1592 __func__);
1593 goto cifs_parse_mount_err;
1594 }
1595 vol->actimeo = HZ * option;
1596 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1597 cERROR(1, "CIFS: attribute cache"
1598 "timeout too large");
1599 goto cifs_parse_mount_err;
1600 }
1601 break;
1602
1603 /* String Arguments */
1604
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001605 case Opt_blank_user:
1606 /* null user, ie. anonymous authentication */
1607 vol->nullauth = 1;
1608 vol->username = NULL;
1609 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001610 case Opt_user:
1611 string = match_strdup(args);
1612 if (string == NULL)
1613 goto out_nomem;
1614
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001615 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001616 MAX_USERNAME_SIZE) {
1617 printk(KERN_WARNING "CIFS: username too long\n");
1618 goto cifs_parse_mount_err;
1619 }
1620 vol->username = kstrdup(string, GFP_KERNEL);
1621 if (!vol->username) {
1622 printk(KERN_WARNING "CIFS: no memory "
1623 "for username\n");
1624 goto cifs_parse_mount_err;
1625 }
1626 break;
1627 case Opt_blank_pass:
1628 vol->password = NULL;
1629 break;
1630 case Opt_pass:
1631 /* passwords have to be handled differently
1632 * to allow the character used for deliminator
1633 * to be passed within them
1634 */
1635
1636 /* Obtain the value string */
1637 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001638 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001639
1640 /* Set tmp_end to end of the string */
1641 tmp_end = (char *) value + strlen(value);
1642
1643 /* Check if following character is the deliminator
1644 * If yes, we have encountered a double deliminator
1645 * reset the NULL character to the deliminator
1646 */
1647 if (tmp_end < end && tmp_end[1] == delim)
1648 tmp_end[0] = delim;
1649
1650 /* Keep iterating until we get to a single deliminator
1651 * OR the end
1652 */
1653 while ((tmp_end = strchr(tmp_end, delim)) != NULL &&
1654 (tmp_end[1] == delim)) {
1655 tmp_end = (char *) &tmp_end[2];
1656 }
1657
1658 /* Reset var options to point to next element */
1659 if (tmp_end) {
1660 tmp_end[0] = '\0';
1661 options = (char *) &tmp_end[1];
1662 } else
1663 /* Reached the end of the mount option string */
1664 options = end;
1665
1666 /* Now build new password string */
1667 temp_len = strlen(value);
1668 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1669 if (vol->password == NULL) {
1670 printk(KERN_WARNING "CIFS: no memory "
1671 "for password\n");
1672 goto cifs_parse_mount_err;
1673 }
1674
1675 for (i = 0, j = 0; i < temp_len; i++, j++) {
1676 vol->password[j] = value[i];
1677 if ((value[i] == delim) &&
1678 value[i+1] == delim)
1679 /* skip the second deliminator */
1680 i++;
1681 }
1682 vol->password[j] = '\0';
1683 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001684 case Opt_blank_ip:
1685 vol->UNCip = NULL;
1686 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001687 case Opt_ip:
1688 string = match_strdup(args);
1689 if (string == NULL)
1690 goto out_nomem;
1691
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001692 if (strnlen(string, INET6_ADDRSTRLEN) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001693 INET6_ADDRSTRLEN) {
1694 printk(KERN_WARNING "CIFS: ip address "
1695 "too long\n");
1696 goto cifs_parse_mount_err;
1697 }
1698 vol->UNCip = kstrdup(string, GFP_KERNEL);
1699 if (!vol->UNCip) {
1700 printk(KERN_WARNING "CIFS: no memory "
1701 "for UNC IP\n");
1702 goto cifs_parse_mount_err;
1703 }
1704 break;
1705 case Opt_unc:
1706 string = match_strdup(args);
1707 if (string == NULL)
1708 goto out_nomem;
1709
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001710 temp_len = strnlen(string, 300);
1711 if (temp_len == 300) {
1712 printk(KERN_WARNING "CIFS: UNC name too long\n");
1713 goto cifs_parse_mount_err;
1714 }
1715
Sachin Prabhue4b41fb2012-04-04 01:58:56 +01001716 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1717 if (vol->UNC == NULL) {
1718 printk(KERN_WARNING "CIFS: no memory for UNC\n");
1719 goto cifs_parse_mount_err;
1720 }
1721 strcpy(vol->UNC, string);
1722
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001723 if (strncmp(string, "//", 2) == 0) {
1724 vol->UNC[0] = '\\';
1725 vol->UNC[1] = '\\';
1726 } else if (strncmp(string, "\\\\", 2) != 0) {
1727 printk(KERN_WARNING "CIFS: UNC Path does not "
1728 "begin with // or \\\\\n");
1729 goto cifs_parse_mount_err;
1730 }
1731
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001732 break;
1733 case Opt_domain:
1734 string = match_strdup(args);
1735 if (string == NULL)
1736 goto out_nomem;
1737
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001738 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001739 printk(KERN_WARNING "CIFS: domain name too"
1740 " long\n");
1741 goto cifs_parse_mount_err;
1742 }
1743
1744 vol->domainname = kstrdup(string, GFP_KERNEL);
1745 if (!vol->domainname) {
1746 printk(KERN_WARNING "CIFS: no memory "
1747 "for domainname\n");
1748 goto cifs_parse_mount_err;
1749 }
1750 cFYI(1, "Domain name set");
1751 break;
1752 case Opt_srcaddr:
1753 string = match_strdup(args);
1754 if (string == NULL)
1755 goto out_nomem;
1756
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001757 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001758 (struct sockaddr *)&vol->srcaddr,
1759 string, strlen(string))) {
1760 printk(KERN_WARNING "CIFS: Could not parse"
1761 " srcaddr: %s\n", string);
1762 goto cifs_parse_mount_err;
1763 }
1764 break;
1765 case Opt_prefixpath:
1766 string = match_strdup(args);
1767 if (string == NULL)
1768 goto out_nomem;
1769
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001770 temp_len = strnlen(string, 1024);
1771 if (string[0] != '/')
1772 temp_len++; /* missing leading slash */
1773 if (temp_len > 1024) {
1774 printk(KERN_WARNING "CIFS: prefix too long\n");
1775 goto cifs_parse_mount_err;
1776 }
1777
1778 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1779 if (vol->prepath == NULL) {
1780 printk(KERN_WARNING "CIFS: no memory "
1781 "for path prefix\n");
1782 goto cifs_parse_mount_err;
1783 }
1784
1785 if (string[0] != '/') {
1786 vol->prepath[0] = '/';
1787 strcpy(vol->prepath+1, string);
1788 } else
1789 strcpy(vol->prepath, string);
1790
1791 break;
1792 case Opt_iocharset:
1793 string = match_strdup(args);
1794 if (string == NULL)
1795 goto out_nomem;
1796
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001797 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001798 printk(KERN_WARNING "CIFS: iocharset name "
1799 "too long.\n");
1800 goto cifs_parse_mount_err;
1801 }
1802
1803 if (strnicmp(string, "default", 7) != 0) {
1804 vol->iocharset = kstrdup(string,
1805 GFP_KERNEL);
1806 if (!vol->iocharset) {
1807 printk(KERN_WARNING "CIFS: no memory"
1808 "for charset\n");
1809 goto cifs_parse_mount_err;
1810 }
1811 }
1812 /* if iocharset not set then load_nls_default
1813 * is used by caller
1814 */
1815 cFYI(1, "iocharset set to %s", string);
1816 break;
1817 case Opt_sockopt:
1818 string = match_strdup(args);
1819 if (string == NULL)
1820 goto out_nomem;
1821
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001822 if (strnicmp(string, "TCP_NODELAY", 11) == 0)
1823 vol->sockopt_tcp_nodelay = 1;
1824 break;
1825 case Opt_netbiosname:
1826 string = match_strdup(args);
1827 if (string == NULL)
1828 goto out_nomem;
1829
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001830 memset(vol->source_rfc1001_name, 0x20,
1831 RFC1001_NAME_LEN);
1832 /*
1833 * FIXME: are there cases in which a comma can
1834 * be valid in workstation netbios name (and
1835 * need special handling)?
1836 */
1837 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1838 /* don't ucase netbiosname for user */
1839 if (string[i] == 0)
1840 break;
1841 vol->source_rfc1001_name[i] = string[i];
1842 }
1843 /* The string has 16th byte zero still from
1844 * set at top of the function
1845 */
1846 if (i == RFC1001_NAME_LEN && string[i] != 0)
1847 printk(KERN_WARNING "CIFS: netbiosname"
1848 " longer than 15 truncated.\n");
1849
1850 break;
1851 case Opt_servern:
1852 /* servernetbiosname specified override *SMBSERVER */
1853 string = match_strdup(args);
1854 if (string == NULL)
1855 goto out_nomem;
1856
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001857 /* last byte, type, is 0x20 for servr type */
1858 memset(vol->target_rfc1001_name, 0x20,
1859 RFC1001_NAME_LEN_WITH_NULL);
1860
1861 /* BB are there cases in which a comma can be
1862 valid in this workstation netbios name
1863 (and need special handling)? */
1864
1865 /* user or mount helper must uppercase the
1866 netbios name */
1867 for (i = 0; i < 15; i++) {
1868 if (string[i] == 0)
1869 break;
1870 vol->target_rfc1001_name[i] = string[i];
1871 }
1872 /* The string has 16th byte zero still from
1873 set at top of the function */
1874 if (i == RFC1001_NAME_LEN && string[i] != 0)
1875 printk(KERN_WARNING "CIFS: server net"
1876 "biosname longer than 15 truncated.\n");
1877 break;
1878 case Opt_ver:
1879 string = match_strdup(args);
1880 if (string == NULL)
1881 goto out_nomem;
1882
Jeff Layton5249af32012-05-15 12:04:03 -04001883 if (strnicmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001884 /* This is the default */
1885 break;
1886 }
1887 /* For all other value, error */
1888 printk(KERN_WARNING "CIFS: Invalid version"
1889 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001890 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001891 case Opt_vers:
1892 string = match_strdup(args);
1893 if (string == NULL)
1894 goto out_nomem;
1895
1896 if (cifs_parse_smb_version(string, vol) != 0)
1897 goto cifs_parse_mount_err;
1898 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 case Opt_sec:
1900 string = match_strdup(args);
1901 if (string == NULL)
1902 goto out_nomem;
1903
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001904 if (cifs_parse_security_flavors(string, vol) != 0)
1905 goto cifs_parse_mount_err;
1906 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001907 case Opt_cache:
Jeff Layton296838b2012-05-16 07:53:01 -04001908 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001909 string = match_strdup(args);
1910 if (string == NULL)
1911 goto out_nomem;
1912
1913 if (cifs_parse_cache_flavor(string, vol) != 0)
1914 goto cifs_parse_mount_err;
1915 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001916 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001917 /*
1918 * An option we don't recognize. Save it off for later
1919 * if we haven't already found one
1920 */
1921 if (!invalid)
1922 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001923 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001925 /* Free up any allocated string */
1926 kfree(string);
1927 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001929
Jeff Laytond8162552012-03-23 14:40:56 -04001930 if (!sloppy && invalid) {
1931 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1932 goto cifs_parse_mount_err;
1933 }
1934
Jeff Layton8a8798a2012-01-17 16:09:15 -05001935#ifndef CONFIG_KEYS
1936 /* Muliuser mounts require CONFIG_KEYS support */
1937 if (vol->multiuser) {
1938 cERROR(1, "Multiuser mounts require kernels with "
1939 "CONFIG_KEYS enabled.");
Sean Finneyb9468452011-04-11 13:19:32 +00001940 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001941 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001942#endif
Jeff Layton0eb8a132010-10-06 19:51:12 -04001943
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001944 if (vol->UNCip == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 vol->UNCip = &vol->UNC[2];
1946
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001947 if (uid_specified)
1948 vol->override_uid = override_uid;
1949 else if (override_uid == 1)
1950 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1951 "specified with no uid= option.\n");
1952
1953 if (gid_specified)
1954 vol->override_gid = override_gid;
1955 else if (override_gid == 1)
1956 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1957 "specified with no gid= option.\n");
1958
Jeff Layton296838b2012-05-16 07:53:01 -04001959 /* FIXME: remove this block in 3.7 */
1960 if (!cache_specified && !cache_warned) {
1961 cache_warned = true;
1962 printk(KERN_NOTICE "CIFS: no cache= option specified, using "
1963 "\"cache=loose\". This default will change "
1964 "to \"cache=strict\" in 3.7.\n");
1965 }
1966
Sean Finneyb9468452011-04-11 13:19:32 +00001967 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001969
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001970out_nomem:
1971 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001972cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001973 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001974 kfree(mountdata_copy);
1975 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976}
1977
Ben Greear3eb9a882010-09-01 17:06:02 -07001978/** Returns true if srcaddr isn't specified and rhs isn't
1979 * specified, or if srcaddr is specified and
1980 * matches the IP address of the rhs argument.
1981 */
Jeff Layton45151482010-07-06 20:43:02 -04001982static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001983srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1984{
1985 switch (srcaddr->sa_family) {
1986 case AF_UNSPEC:
1987 return (rhs->sa_family == AF_UNSPEC);
1988 case AF_INET: {
1989 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1990 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1991 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1992 }
1993 case AF_INET6: {
1994 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
1995 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
1996 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1997 }
1998 default:
1999 WARN_ON(1);
2000 return false; /* don't expect to be here */
2001 }
2002}
2003
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002004/*
2005 * If no port is specified in addr structure, we try to match with 445 port
2006 * and if it fails - with 139 ports. It should be called only if address
2007 * families of server and addr are equal.
2008 */
2009static bool
2010match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2011{
Steve French6da97912011-03-13 18:55:55 +00002012 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002013
2014 switch (addr->sa_family) {
2015 case AF_INET:
2016 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2017 port = ((struct sockaddr_in *) addr)->sin_port;
2018 break;
2019 case AF_INET6:
2020 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2021 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2022 break;
2023 default:
2024 WARN_ON(1);
2025 return false;
2026 }
2027
2028 if (!port) {
2029 port = htons(CIFS_PORT);
2030 if (port == *sport)
2031 return true;
2032
2033 port = htons(RFC1001_PORT);
2034 }
2035
2036 return port == *sport;
2037}
Ben Greear3eb9a882010-09-01 17:06:02 -07002038
2039static bool
2040match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2041 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042{
Jeff Layton45151482010-07-06 20:43:02 -04002043 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002044 case AF_INET: {
2045 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2046 struct sockaddr_in *srv_addr4 =
2047 (struct sockaddr_in *)&server->dstaddr;
2048
2049 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002050 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002051 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002052 }
2053 case AF_INET6: {
2054 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2055 struct sockaddr_in6 *srv_addr6 =
2056 (struct sockaddr_in6 *)&server->dstaddr;
2057
Jeff Layton45151482010-07-06 20:43:02 -04002058 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002059 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002060 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002061 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002062 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002063 break;
2064 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002065 default:
2066 WARN_ON(1);
2067 return false; /* don't expect to be here */
2068 }
Jeff Layton45151482010-07-06 20:43:02 -04002069
Ben Greear3eb9a882010-09-01 17:06:02 -07002070 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2071 return false;
2072
Jeff Layton45151482010-07-06 20:43:02 -04002073 return true;
2074}
2075
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002076static bool
2077match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2078{
2079 unsigned int secFlags;
2080
2081 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
2082 secFlags = vol->secFlg;
2083 else
2084 secFlags = global_secflags | vol->secFlg;
2085
2086 switch (server->secType) {
2087 case LANMAN:
2088 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
2089 return false;
2090 break;
2091 case NTLMv2:
2092 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
2093 return false;
2094 break;
2095 case NTLM:
2096 if (!(secFlags & CIFSSEC_MAY_NTLM))
2097 return false;
2098 break;
2099 case Kerberos:
2100 if (!(secFlags & CIFSSEC_MAY_KRB5))
2101 return false;
2102 break;
2103 case RawNTLMSSP:
2104 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2105 return false;
2106 break;
2107 default:
2108 /* shouldn't happen */
2109 return false;
2110 }
2111
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002112 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002113 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002114 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002115 return false;
2116 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002117 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002118 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2119 return false;
2120
2121 return true;
2122}
2123
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002124static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
2125 struct smb_vol *vol)
2126{
Jeff Layton23db65f2012-05-15 12:20:51 -04002127 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2128 return 0;
2129
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002130 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2131 return 0;
2132
2133 if (!match_address(server, addr,
2134 (struct sockaddr *)&vol->srcaddr))
2135 return 0;
2136
2137 if (!match_port(server, addr))
2138 return 0;
2139
2140 if (!match_security(server, vol))
2141 return 0;
2142
2143 return 1;
2144}
2145
Jeff Layton45151482010-07-06 20:43:02 -04002146static struct TCP_Server_Info *
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002147cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002148{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002149 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302151 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002152 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002153 if (!match_server(server, addr, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002154 continue;
2155
Jeff Laytone7ddee92008-11-14 13:44:38 -05002156 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302157 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002158 cFYI(1, "Existing tcp session with server found");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002159 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302161 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 return NULL;
2163}
2164
Jeff Layton14fbf502008-11-14 13:53:46 -05002165static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002166cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002168 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302170 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002171 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302172 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002173 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002175
Rob Landleyf1d0c992011-01-22 15:44:05 -06002176 put_net(cifs_net_ns(server));
2177
Jeff Laytone7ddee92008-11-14 13:44:38 -05002178 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302179 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002180
Jeff Laytonc74093b2011-01-11 07:24:23 -05002181 cancel_delayed_work_sync(&server->echo);
2182
Jeff Laytone7ddee92008-11-14 13:44:38 -05002183 spin_lock(&GlobalMid_Lock);
2184 server->tcpStatus = CifsExiting;
2185 spin_unlock(&GlobalMid_Lock);
2186
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002187 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302188 cifs_fscache_release_client_cookie(server);
2189
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002190 kfree(server->session_key.response);
2191 server->session_key.response = NULL;
2192 server->session_key.len = 0;
2193
Jeff Laytone7ddee92008-11-14 13:44:38 -05002194 task = xchg(&server->tsk, NULL);
2195 if (task)
2196 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197}
2198
Jeff Layton63c038c2008-12-01 18:41:46 -05002199static struct TCP_Server_Info *
2200cifs_get_tcp_session(struct smb_vol *volume_info)
2201{
2202 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002203 struct sockaddr_storage addr;
Jeff Layton63c038c2008-12-01 18:41:46 -05002204 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2205 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2206 int rc;
2207
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002208 memset(&addr, 0, sizeof(struct sockaddr_storage));
Jeff Layton63c038c2008-12-01 18:41:46 -05002209
Joe Perchesb6b38f72010-04-21 03:50:45 +00002210 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002211
Jeff Layton63c038c2008-12-01 18:41:46 -05002212 if (volume_info->UNCip && volume_info->UNC) {
Jeff Layton50d97162010-07-06 20:43:01 -04002213 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2214 volume_info->UNCip,
David Howells67b76262010-07-22 18:33:01 +01002215 strlen(volume_info->UNCip),
Jeff Layton50d97162010-07-06 20:43:01 -04002216 volume_info->port);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002217 if (!rc) {
Jeff Layton63c038c2008-12-01 18:41:46 -05002218 /* we failed translating address */
2219 rc = -EINVAL;
2220 goto out_err;
2221 }
Jeff Layton63c038c2008-12-01 18:41:46 -05002222 } else if (volume_info->UNCip) {
2223 /* BB using ip addr as tcp_ses name to connect to the
2224 DFS root below */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002225 cERROR(1, "Connecting to DFS root not implemented yet");
Jeff Layton63c038c2008-12-01 18:41:46 -05002226 rc = -EINVAL;
2227 goto out_err;
2228 } else /* which tcp_sess DFS root would we conect to */ {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002229 cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
2230 "unc=//192.168.1.100/public) specified");
Jeff Layton63c038c2008-12-01 18:41:46 -05002231 rc = -EINVAL;
2232 goto out_err;
2233 }
2234
2235 /* see if we already have a matching tcp_ses */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002236 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002237 if (tcp_ses)
2238 return tcp_ses;
2239
2240 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2241 if (!tcp_ses) {
2242 rc = -ENOMEM;
2243 goto out_err;
2244 }
2245
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002246 rc = cifs_crypto_shash_allocate(tcp_ses);
2247 if (rc) {
2248 cERROR(1, "could not setup hash structures rc %d", rc);
2249 goto out_err;
2250 }
2251
Jeff Layton23db65f2012-05-15 12:20:51 -04002252 tcp_ses->ops = volume_info->ops;
2253 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002254 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002255 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2256 if (IS_ERR(tcp_ses->hostname)) {
2257 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002258 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002259 }
2260
2261 tcp_ses->noblocksnd = volume_info->noblocksnd;
2262 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002263 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002264 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002265 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002266 init_waitqueue_head(&tcp_ses->response_q);
2267 init_waitqueue_head(&tcp_ses->request_q);
2268 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2269 mutex_init(&tcp_ses->srv_mutex);
2270 memcpy(tcp_ses->workstation_RFC1001_name,
2271 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2272 memcpy(tcp_ses->server_RFC1001_name,
2273 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002274 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002275 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002276 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002277 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002278 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2279 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002280 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton63c038c2008-12-01 18:41:46 -05002281
2282 /*
2283 * at this point we are the only ones with the pointer
2284 * to the struct since the kernel thread not created yet
2285 * no need to spinlock this init of tcpStatus or srv_count
2286 */
2287 tcp_ses->tcpStatus = CifsNew;
Ben Greear3eb9a882010-09-01 17:06:02 -07002288 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2289 sizeof(tcp_ses->srcaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002290 ++tcp_ses->srv_count;
2291
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002292 if (addr.ss_family == AF_INET6) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002293 cFYI(1, "attempting ipv6 connect");
Jeff Layton63c038c2008-12-01 18:41:46 -05002294 /* BB should we allow ipv6 on port 139? */
2295 /* other OS never observed in Wild doing 139 with v6 */
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002296 memcpy(&tcp_ses->dstaddr, sin_server6,
2297 sizeof(struct sockaddr_in6));
2298 } else
2299 memcpy(&tcp_ses->dstaddr, sin_server,
2300 sizeof(struct sockaddr_in));
2301
2302 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002303 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002304 cERROR(1, "Error connecting to socket. Aborting operation");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002305 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002306 }
2307
2308 /*
2309 * since we're in a cifs function already, we know that
2310 * this will succeed. No need for try_module_get().
2311 */
2312 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002313 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002314 tcp_ses, "cifsd");
2315 if (IS_ERR(tcp_ses->tsk)) {
2316 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002317 cERROR(1, "error %d create cifsd thread", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002318 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002319 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002320 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002321 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002322
2323 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302324 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002325 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302326 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002327
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302328 cifs_fscache_get_client_cookie(tcp_ses);
2329
Jeff Laytonc74093b2011-01-11 07:24:23 -05002330 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002331 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002332
Jeff Layton63c038c2008-12-01 18:41:46 -05002333 return tcp_ses;
2334
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002335out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002336 cifs_crypto_shash_release(tcp_ses);
2337
Rob Landleyf1d0c992011-01-22 15:44:05 -06002338 put_net(cifs_net_ns(tcp_ses));
2339
Jeff Layton63c038c2008-12-01 18:41:46 -05002340out_err:
2341 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002342 if (!IS_ERR(tcp_ses->hostname))
2343 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002344 if (tcp_ses->ssocket)
2345 sock_release(tcp_ses->ssocket);
2346 kfree(tcp_ses);
2347 }
2348 return ERR_PTR(rc);
2349}
2350
Steve French96daf2b2011-05-27 04:34:02 +00002351static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002352{
2353 switch (ses->server->secType) {
2354 case Kerberos:
2355 if (vol->cred_uid != ses->cred_uid)
2356 return 0;
2357 break;
2358 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002359 /* NULL username means anonymous session */
2360 if (ses->user_name == NULL) {
2361 if (!vol->nullauth)
2362 return 0;
2363 break;
2364 }
2365
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002366 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002367 if (strncmp(ses->user_name,
2368 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002369 MAX_USERNAME_SIZE))
2370 return 0;
2371 if (strlen(vol->username) != 0 &&
2372 ses->password != NULL &&
2373 strncmp(ses->password,
2374 vol->password ? vol->password : "",
2375 MAX_PASSWORD_SIZE))
2376 return 0;
2377 }
2378 return 1;
2379}
2380
Steve French96daf2b2011-05-27 04:34:02 +00002381static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002382cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383{
Steve French96daf2b2011-05-27 04:34:02 +00002384 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302386 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002387 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002388 if (!match_session(ses, vol))
2389 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002390 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302391 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002392 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302394 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 return NULL;
2396}
2397
Jeff Layton14fbf502008-11-14 13:53:46 -05002398static void
Steve French96daf2b2011-05-27 04:34:02 +00002399cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002400{
2401 int xid;
2402 struct TCP_Server_Info *server = ses->server;
2403
Jeff Layton36988c72010-04-24 07:57:43 -04002404 cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302405 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002406 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302407 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002408 return;
2409 }
2410
2411 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302412 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002413
2414 if (ses->status == CifsGood) {
2415 xid = GetXid();
2416 CIFSSMBLogoff(xid, ses);
2417 _FreeXid(xid);
2418 }
2419 sesInfoFree(ses);
2420 cifs_put_tcp_session(server);
2421}
2422
Jeff Layton8a8798a2012-01-17 16:09:15 -05002423#ifdef CONFIG_KEYS
2424
2425/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2426#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2427
2428/* Populate username and pw fields from keyring if possible */
2429static int
2430cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2431{
2432 int rc = 0;
2433 char *desc, *delim, *payload;
2434 ssize_t len;
2435 struct key *key;
2436 struct TCP_Server_Info *server = ses->server;
2437 struct sockaddr_in *sa;
2438 struct sockaddr_in6 *sa6;
2439 struct user_key_payload *upayload;
2440
2441 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2442 if (!desc)
2443 return -ENOMEM;
2444
2445 /* try to find an address key first */
2446 switch (server->dstaddr.ss_family) {
2447 case AF_INET:
2448 sa = (struct sockaddr_in *)&server->dstaddr;
2449 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2450 break;
2451 case AF_INET6:
2452 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2453 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2454 break;
2455 default:
2456 cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
2457 rc = -EINVAL;
2458 goto out_err;
2459 }
2460
2461 cFYI(1, "%s: desc=%s", __func__, desc);
2462 key = request_key(&key_type_logon, desc, "");
2463 if (IS_ERR(key)) {
2464 if (!ses->domainName) {
2465 cFYI(1, "domainName is NULL");
2466 rc = PTR_ERR(key);
2467 goto out_err;
2468 }
2469
2470 /* didn't work, try to find a domain key */
2471 sprintf(desc, "cifs:d:%s", ses->domainName);
2472 cFYI(1, "%s: desc=%s", __func__, desc);
2473 key = request_key(&key_type_logon, desc, "");
2474 if (IS_ERR(key)) {
2475 rc = PTR_ERR(key);
2476 goto out_err;
2477 }
2478 }
2479
2480 down_read(&key->sem);
2481 upayload = key->payload.data;
2482 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002483 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002484 goto out_key_put;
2485 }
2486
2487 /* find first : in payload */
2488 payload = (char *)upayload->data;
2489 delim = strnchr(payload, upayload->datalen, ':');
2490 cFYI(1, "payload=%s", payload);
2491 if (!delim) {
2492 cFYI(1, "Unable to find ':' in payload (datalen=%d)",
2493 upayload->datalen);
2494 rc = -EINVAL;
2495 goto out_key_put;
2496 }
2497
2498 len = delim - payload;
2499 if (len > MAX_USERNAME_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002500 cFYI(1, "Bad value from username search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002501 rc = -EINVAL;
2502 goto out_key_put;
2503 }
2504
2505 vol->username = kstrndup(payload, len, GFP_KERNEL);
2506 if (!vol->username) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002507 cFYI(1, "Unable to allocate %zd bytes for username", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002508 rc = -ENOMEM;
2509 goto out_key_put;
2510 }
2511 cFYI(1, "%s: username=%s", __func__, vol->username);
2512
2513 len = key->datalen - (len + 1);
2514 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002515 cFYI(1, "Bad len for password search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002516 rc = -EINVAL;
2517 kfree(vol->username);
2518 vol->username = NULL;
2519 goto out_key_put;
2520 }
2521
2522 ++delim;
2523 vol->password = kstrndup(delim, len, GFP_KERNEL);
2524 if (!vol->password) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002525 cFYI(1, "Unable to allocate %zd bytes for password", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002526 rc = -ENOMEM;
2527 kfree(vol->username);
2528 vol->username = NULL;
2529 goto out_key_put;
2530 }
2531
2532out_key_put:
2533 up_read(&key->sem);
2534 key_put(key);
2535out_err:
2536 kfree(desc);
2537 cFYI(1, "%s: returning %d", __func__, rc);
2538 return rc;
2539}
2540#else /* ! CONFIG_KEYS */
2541static inline int
2542cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2543 struct cifs_ses *ses __attribute__((unused)))
2544{
2545 return -ENOSYS;
2546}
2547#endif /* CONFIG_KEYS */
2548
Steve Frenchd9b94202011-04-12 01:24:57 +00002549static bool warned_on_ntlm; /* globals init to false automatically */
2550
Steve French96daf2b2011-05-27 04:34:02 +00002551static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002552cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2553{
2554 int rc = -ENOMEM, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002555 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002556 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2557 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002558
2559 xid = GetXid();
2560
Jeff Layton4ff67b72010-07-06 20:43:02 -04002561 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002562 if (ses) {
2563 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
2564
Jeff Layton36988c72010-04-24 07:57:43 -04002565 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002566 rc = cifs_negotiate_protocol(xid, ses);
2567 if (rc) {
2568 mutex_unlock(&ses->session_mutex);
2569 /* problem -- put our ses reference */
2570 cifs_put_smb_ses(ses);
2571 FreeXid(xid);
2572 return ERR_PTR(rc);
2573 }
Jeff Layton36988c72010-04-24 07:57:43 -04002574 if (ses->need_reconnect) {
2575 cFYI(1, "Session needs reconnect");
2576 rc = cifs_setup_session(xid, ses,
2577 volume_info->local_nls);
2578 if (rc) {
2579 mutex_unlock(&ses->session_mutex);
2580 /* problem -- put our reference */
2581 cifs_put_smb_ses(ses);
2582 FreeXid(xid);
2583 return ERR_PTR(rc);
2584 }
2585 }
2586 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002587
2588 /* existing SMB ses has a server reference already */
2589 cifs_put_tcp_session(server);
Jeff Layton36988c72010-04-24 07:57:43 -04002590 FreeXid(xid);
2591 return ses;
2592 }
2593
2594 cFYI(1, "Existing smb sess not found");
2595 ses = sesInfoAlloc();
2596 if (ses == NULL)
2597 goto get_ses_fail;
2598
2599 /* new SMB session uses our server ref */
2600 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002601 if (server->dstaddr.ss_family == AF_INET6)
2602 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002603 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002604 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002605
Steve French8727c8a2011-02-25 01:11:56 -06002606 if (volume_info->username) {
2607 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2608 if (!ses->user_name)
2609 goto get_ses_fail;
2610 }
Jeff Layton36988c72010-04-24 07:57:43 -04002611
2612 /* volume_info->password freed at unmount */
2613 if (volume_info->password) {
2614 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2615 if (!ses->password)
2616 goto get_ses_fail;
2617 }
2618 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002619 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2620 if (!ses->domainName)
2621 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002622 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002623 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002624 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002625
2626 /* ntlmv2 is much stronger than ntlm security, and has been broadly
2627 supported for many years, time to update default security mechanism */
2628 if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
2629 warned_on_ntlm = true;
2630 cERROR(1, "default security mechanism requested. The default "
2631 "security mechanism will be upgraded from ntlm to "
Steve French225de112012-01-03 23:08:24 -06002632 "ntlmv2 in kernel release 3.3");
Steve Frenchd9b94202011-04-12 01:24:57 +00002633 }
Jeff Layton36988c72010-04-24 07:57:43 -04002634 ses->overrideSecFlg = volume_info->secFlg;
2635
2636 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002637 rc = cifs_negotiate_protocol(xid, ses);
2638 if (!rc)
2639 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002640 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002641 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002642 goto get_ses_fail;
2643
2644 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302645 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002646 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302647 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002648
2649 FreeXid(xid);
2650 return ses;
2651
2652get_ses_fail:
2653 sesInfoFree(ses);
2654 FreeXid(xid);
2655 return ERR_PTR(rc);
2656}
2657
Steve French96daf2b2011-05-27 04:34:02 +00002658static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002659{
2660 if (tcon->tidStatus == CifsExiting)
2661 return 0;
2662 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2663 return 0;
2664 return 1;
2665}
2666
Steve French96daf2b2011-05-27 04:34:02 +00002667static struct cifs_tcon *
2668cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669{
2670 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002671 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302673 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002674 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002675 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002676 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002677 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002678 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302679 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 return tcon;
2681 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302682 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 return NULL;
2684}
2685
Jeff Laytonf1987b42008-11-15 11:12:47 -05002686static void
Steve French96daf2b2011-05-27 04:34:02 +00002687cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002688{
2689 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002690 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002691
Jeff Laytond00c28d2010-04-24 07:57:44 -04002692 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302693 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002694 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302695 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002696 return;
2697 }
2698
2699 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302700 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002701
2702 xid = GetXid();
2703 CIFSSMBTDis(xid, tcon);
2704 _FreeXid(xid);
2705
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302706 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002707 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002708 cifs_put_smb_ses(ses);
2709}
2710
Steve French96daf2b2011-05-27 04:34:02 +00002711static struct cifs_tcon *
2712cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002713{
2714 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002715 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002716
2717 tcon = cifs_find_tcon(ses, volume_info->UNC);
2718 if (tcon) {
2719 cFYI(1, "Found match on UNC path");
2720 /* existing tcon already has a reference */
2721 cifs_put_smb_ses(ses);
2722 if (tcon->seal != volume_info->seal)
2723 cERROR(1, "transport encryption setting "
2724 "conflicts with existing tid");
2725 return tcon;
2726 }
2727
2728 tcon = tconInfoAlloc();
2729 if (tcon == NULL) {
2730 rc = -ENOMEM;
2731 goto out_fail;
2732 }
2733
2734 tcon->ses = ses;
2735 if (volume_info->password) {
2736 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2737 if (!tcon->password) {
2738 rc = -ENOMEM;
2739 goto out_fail;
2740 }
2741 }
2742
2743 if (strchr(volume_info->UNC + 3, '\\') == NULL
2744 && strchr(volume_info->UNC + 3, '/') == NULL) {
2745 cERROR(1, "Missing share name");
2746 rc = -ENODEV;
2747 goto out_fail;
2748 }
2749
2750 /* BB Do we need to wrap session_mutex around
2751 * this TCon call and Unix SetFS as
2752 * we do on SessSetup and reconnect? */
2753 xid = GetXid();
2754 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
2755 FreeXid(xid);
2756 cFYI(1, "CIFS Tcon rc = %d", rc);
2757 if (rc)
2758 goto out_fail;
2759
2760 if (volume_info->nodfs) {
2761 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2762 cFYI(1, "DFS disabled (%d)", tcon->Flags);
2763 }
2764 tcon->seal = volume_info->seal;
2765 /* we can have only one retry value for a connection
2766 to a share so for resources mounted more than once
2767 to the same server share the last value passed in
2768 for the retry flag is used */
2769 tcon->retry = volume_info->retry;
2770 tcon->nocase = volume_info->nocase;
2771 tcon->local_lease = volume_info->local_lease;
2772
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302773 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002774 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302775 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002776
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302777 cifs_fscache_get_super_cookie(tcon);
2778
Jeff Laytond00c28d2010-04-24 07:57:44 -04002779 return tcon;
2780
2781out_fail:
2782 tconInfoFree(tcon);
2783 return ERR_PTR(rc);
2784}
2785
Jeff Layton9d002df2010-10-06 19:51:11 -04002786void
2787cifs_put_tlink(struct tcon_link *tlink)
2788{
2789 if (!tlink || IS_ERR(tlink))
2790 return;
2791
2792 if (!atomic_dec_and_test(&tlink->tl_count) ||
2793 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2794 tlink->tl_time = jiffies;
2795 return;
2796 }
2797
2798 if (!IS_ERR(tlink_tcon(tlink)))
2799 cifs_put_tcon(tlink_tcon(tlink));
2800 kfree(tlink);
2801 return;
2802}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002803
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002804static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002805cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2806{
2807 return cifs_sb->master_tlink;
2808}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002809
2810static int
2811compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2812{
2813 struct cifs_sb_info *old = CIFS_SB(sb);
2814 struct cifs_sb_info *new = mnt_data->cifs_sb;
2815
2816 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2817 return 0;
2818
2819 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2820 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2821 return 0;
2822
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002823 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002824 * We want to share sb only if we don't specify an r/wsize or
2825 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002826 */
2827 if (new->wsize && new->wsize < old->wsize)
2828 return 0;
2829
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002830 if (new->rsize && new->rsize < old->rsize)
2831 return 0;
2832
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002833 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2834 return 0;
2835
2836 if (old->mnt_file_mode != new->mnt_file_mode ||
2837 old->mnt_dir_mode != new->mnt_dir_mode)
2838 return 0;
2839
2840 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2841 return 0;
2842
2843 if (old->actimeo != new->actimeo)
2844 return 0;
2845
2846 return 1;
2847}
2848
2849int
2850cifs_match_super(struct super_block *sb, void *data)
2851{
2852 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2853 struct smb_vol *volume_info;
2854 struct cifs_sb_info *cifs_sb;
2855 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002856 struct cifs_ses *ses;
2857 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002858 struct tcon_link *tlink;
2859 struct sockaddr_storage addr;
2860 int rc = 0;
2861
2862 memset(&addr, 0, sizeof(struct sockaddr_storage));
2863
2864 spin_lock(&cifs_tcp_ses_lock);
2865 cifs_sb = CIFS_SB(sb);
2866 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2867 if (IS_ERR(tlink)) {
2868 spin_unlock(&cifs_tcp_ses_lock);
2869 return rc;
2870 }
2871 tcon = tlink_tcon(tlink);
2872 ses = tcon->ses;
2873 tcp_srv = ses->server;
2874
2875 volume_info = mnt_data->vol;
2876
2877 if (!volume_info->UNCip || !volume_info->UNC)
2878 goto out;
2879
2880 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2881 volume_info->UNCip,
2882 strlen(volume_info->UNCip),
2883 volume_info->port);
2884 if (!rc)
2885 goto out;
2886
2887 if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
2888 !match_session(ses, volume_info) ||
2889 !match_tcon(tcon, volume_info->UNC)) {
2890 rc = 0;
2891 goto out;
2892 }
2893
2894 rc = compare_mount_options(sb, mnt_data);
2895out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002896 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002897 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002898 return rc;
2899}
2900
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901int
Steve French96daf2b2011-05-27 04:34:02 +00002902get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
Steve French50c2f752007-07-13 00:33:32 +00002903 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
Steve French366781c2008-01-25 10:12:41 +00002904 struct dfs_info3_param **preferrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905{
2906 char *temp_unc;
2907 int rc = 0;
2908
2909 *pnum_referrals = 0;
Steve French366781c2008-01-25 10:12:41 +00002910 *preferrals = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911
2912 if (pSesInfo->ipc_tid == 0) {
2913 temp_unc = kmalloc(2 /* for slashes */ +
Steve French50c2f752007-07-13 00:33:32 +00002914 strnlen(pSesInfo->serverName,
2915 SERVER_NAME_LEN_WITH_NULL * 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 + 1 + 4 /* slash IPC$ */ + 2,
2917 GFP_KERNEL);
2918 if (temp_unc == NULL)
2919 return -ENOMEM;
2920 temp_unc[0] = '\\';
2921 temp_unc[1] = '\\';
2922 strcpy(temp_unc + 2, pSesInfo->serverName);
2923 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
2924 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002925 cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 kfree(temp_unc);
2927 }
2928 if (rc == 0)
Steve Frenchc2cf07d2008-05-15 06:20:02 +00002929 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
Steve French737b7582005-04-28 22:41:06 -07002930 pnum_referrals, nls_codepage, remap);
Steve French366781c2008-01-25 10:12:41 +00002931 /* BB map targetUNCs to dfs_info3 structures, here or
2932 in CIFSGetDFSRefer BB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933
2934 return rc;
2935}
2936
Jeff Layton09e50d52008-07-23 10:11:19 -04002937#ifdef CONFIG_DEBUG_LOCK_ALLOC
2938static struct lock_class_key cifs_key[2];
2939static struct lock_class_key cifs_slock_key[2];
2940
2941static inline void
2942cifs_reclassify_socket4(struct socket *sock)
2943{
2944 struct sock *sk = sock->sk;
2945 BUG_ON(sock_owned_by_user(sk));
2946 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2947 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2948}
2949
2950static inline void
2951cifs_reclassify_socket6(struct socket *sock)
2952{
2953 struct sock *sk = sock->sk;
2954 BUG_ON(sock_owned_by_user(sk));
2955 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2956 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2957}
2958#else
2959static inline void
2960cifs_reclassify_socket4(struct socket *sock)
2961{
2962}
2963
2964static inline void
2965cifs_reclassify_socket6(struct socket *sock)
2966{
2967}
2968#endif
2969
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002971static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972{
Steve French50c2f752007-07-13 00:33:32 +00002973 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974
Steve French50c2f752007-07-13 00:33:32 +00002975 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 /* mask a nibble at a time and encode */
2977 target[j] = 'A' + (0x0F & (source[i] >> 4));
2978 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002979 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 }
2981
2982}
2983
Ben Greear3eb9a882010-09-01 17:06:02 -07002984static int
2985bind_socket(struct TCP_Server_Info *server)
2986{
2987 int rc = 0;
2988 if (server->srcaddr.ss_family != AF_UNSPEC) {
2989 /* Bind to the specified local IP address */
2990 struct socket *socket = server->ssocket;
2991 rc = socket->ops->bind(socket,
2992 (struct sockaddr *) &server->srcaddr,
2993 sizeof(server->srcaddr));
2994 if (rc < 0) {
2995 struct sockaddr_in *saddr4;
2996 struct sockaddr_in6 *saddr6;
2997 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2998 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2999 if (saddr6->sin6_family == AF_INET6)
3000 cERROR(1, "cifs: "
3001 "Failed to bind to: %pI6c, error: %d\n",
3002 &saddr6->sin6_addr, rc);
3003 else
3004 cERROR(1, "cifs: "
3005 "Failed to bind to: %pI4, error: %d\n",
3006 &saddr4->sin_addr.s_addr, rc);
3007 }
3008 }
3009 return rc;
3010}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
3012static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003013ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014{
3015 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003016 /*
3017 * some servers require RFC1001 sessinit before sending
3018 * negprot - BB check reconnection in case where second
3019 * sessinit is sent but no second negprot
3020 */
3021 struct rfc1002_session_packet *ses_init_buf;
3022 struct smb_hdr *smb_buf;
3023 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3024 GFP_KERNEL);
3025 if (ses_init_buf) {
3026 ses_init_buf->trailer.session_req.called_len = 32;
3027
3028 if (server->server_RFC1001_name &&
3029 server->server_RFC1001_name[0] != 0)
3030 rfc1002mangle(ses_init_buf->trailer.
3031 session_req.called_name,
3032 server->server_RFC1001_name,
3033 RFC1001_NAME_LEN_WITH_NULL);
3034 else
3035 rfc1002mangle(ses_init_buf->trailer.
3036 session_req.called_name,
3037 DEFAULT_CIFS_CALLED_NAME,
3038 RFC1001_NAME_LEN_WITH_NULL);
3039
3040 ses_init_buf->trailer.session_req.calling_len = 32;
3041
3042 /*
3043 * calling name ends in null (byte 16) from old smb
3044 * convention.
3045 */
3046 if (server->workstation_RFC1001_name &&
3047 server->workstation_RFC1001_name[0] != 0)
3048 rfc1002mangle(ses_init_buf->trailer.
3049 session_req.calling_name,
3050 server->workstation_RFC1001_name,
3051 RFC1001_NAME_LEN_WITH_NULL);
3052 else
3053 rfc1002mangle(ses_init_buf->trailer.
3054 session_req.calling_name,
3055 "LINUX_CIFS_CLNT",
3056 RFC1001_NAME_LEN_WITH_NULL);
3057
3058 ses_init_buf->trailer.session_req.scope1 = 0;
3059 ses_init_buf->trailer.session_req.scope2 = 0;
3060 smb_buf = (struct smb_hdr *)ses_init_buf;
3061
3062 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003063 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003064 rc = smb_send(server, smb_buf, 0x44);
3065 kfree(ses_init_buf);
3066 /*
3067 * RFC1001 layer in at least one server
3068 * requires very short break before negprot
3069 * presumably because not expecting negprot
3070 * to follow so fast. This is a simple
3071 * solution that works without
3072 * complicating the code and causes no
3073 * significant slowing down on mount
3074 * for everyone else
3075 */
3076 usleep_range(1000, 2000);
3077 }
3078 /*
3079 * else the negprot may still work without this
3080 * even though malloc failed
3081 */
3082
3083 return rc;
3084}
3085
3086static int
3087generic_ip_connect(struct TCP_Server_Info *server)
3088{
3089 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003090 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003091 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003092 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003093 struct sockaddr *saddr;
3094
3095 saddr = (struct sockaddr *) &server->dstaddr;
3096
3097 if (server->dstaddr.ss_family == AF_INET6) {
3098 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3099 slen = sizeof(struct sockaddr_in6);
3100 sfamily = AF_INET6;
3101 } else {
3102 sport = ((struct sockaddr_in *) saddr)->sin_port;
3103 slen = sizeof(struct sockaddr_in);
3104 sfamily = AF_INET;
3105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003107 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003108 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3109 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003111 cERROR(1, "Error %d creating socket", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003112 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003115
3116 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003117 cFYI(1, "Socket created");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003118 server->ssocket = socket;
3119 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003120 if (sfamily == AF_INET6)
3121 cifs_reclassify_socket6(socket);
3122 else
3123 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 }
3125
Ben Greear3eb9a882010-09-01 17:06:02 -07003126 rc = bind_socket(server);
3127 if (rc < 0)
3128 return rc;
3129
Jeff Laytond5c56052008-12-01 18:42:33 -05003130 /*
3131 * Eventually check for other socket options to change from
3132 * the default. sock_setsockopt not used because it expects
3133 * user space buffer
3134 */
3135 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003136 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003137
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003138 /* make the bufsizes depend on wsize/rsize and max requests */
3139 if (server->noautotune) {
3140 if (socket->sk->sk_sndbuf < (200 * 1024))
3141 socket->sk->sk_sndbuf = 200 * 1024;
3142 if (socket->sk->sk_rcvbuf < (140 * 1024))
3143 socket->sk->sk_rcvbuf = 140 * 1024;
3144 }
3145
Steve French6a5fa2362010-01-01 01:28:43 +00003146 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003147 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003148 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3149 (char *)&val, sizeof(val));
3150 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003151 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003152 }
3153
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003154 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
3155 socket->sk->sk_sndbuf,
3156 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3157
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003158 rc = socket->ops->connect(socket, saddr, slen, 0);
3159 if (rc < 0) {
3160 cFYI(1, "Error %d connecting to server", rc);
3161 sock_release(socket);
3162 server->ssocket = NULL;
3163 return rc;
3164 }
3165
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003166 if (sport == htons(RFC1001_PORT))
3167 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003168
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 return rc;
3170}
3171
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003172static int
3173ip_connect(struct TCP_Server_Info *server)
3174{
Steve French6da97912011-03-13 18:55:55 +00003175 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003176 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3177 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3178
3179 if (server->dstaddr.ss_family == AF_INET6)
3180 sport = &addr6->sin6_port;
3181 else
3182 sport = &addr->sin_port;
3183
3184 if (*sport == 0) {
3185 int rc;
3186
3187 /* try with 445 port at first */
3188 *sport = htons(CIFS_PORT);
3189
3190 rc = generic_ip_connect(server);
3191 if (rc >= 0)
3192 return rc;
3193
3194 /* if it failed, try with 139 port */
3195 *sport = htons(RFC1001_PORT);
3196 }
3197
3198 return generic_ip_connect(server);
3199}
3200
Steve French96daf2b2011-05-27 04:34:02 +00003201void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003202 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003203{
3204 /* if we are reconnecting then should we check to see if
3205 * any requested capabilities changed locally e.g. via
3206 * remount but we can not do much about it here
3207 * if they have (even if we could detect it by the following)
3208 * Perhaps we could add a backpointer to array of sb from tcon
3209 * or if we change to make all sb to same share the same
3210 * sb as NFS - then we only have one backpointer to sb.
3211 * What if we wanted to mount the server share twice once with
3212 * and once without posixacls or posix paths? */
3213 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003214
Steve Frenchc18c8422007-07-18 23:21:09 +00003215 if (vol_info && vol_info->no_linux_ext) {
3216 tcon->fsUnixInfo.Capability = 0;
3217 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003218 cFYI(1, "Linux protocol extensions disabled");
Steve Frenchc18c8422007-07-18 23:21:09 +00003219 return;
3220 } else if (vol_info)
3221 tcon->unix_ext = 1; /* Unix Extensions supported */
3222
3223 if (tcon->unix_ext == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003224 cFYI(1, "Unix extensions disabled so not set on reconnect");
Steve Frenchc18c8422007-07-18 23:21:09 +00003225 return;
3226 }
Steve French50c2f752007-07-13 00:33:32 +00003227
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003228 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003229 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French6848b732011-05-26 18:38:54 +00003230 cFYI(1, "unix caps which server supports %lld", cap);
Steve French8af18972007-02-14 04:42:51 +00003231 /* check for reconnect case in which we do not
3232 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003233 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003234 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003235 originally at mount time */
3236 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3237 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003238 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3239 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003240 cERROR(1, "POSIXPATH support change");
Steve French8af18972007-02-14 04:42:51 +00003241 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003242 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003243 cERROR(1, "possible reconnect error");
3244 cERROR(1, "server disabled POSIX path support");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003245 }
Steve French8af18972007-02-14 04:42:51 +00003246 }
Steve French50c2f752007-07-13 00:33:32 +00003247
Steve French6848b732011-05-26 18:38:54 +00003248 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3249 cERROR(1, "per-share encryption not supported yet");
3250
Steve French8af18972007-02-14 04:42:51 +00003251 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003252 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003253 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003254 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003255 cFYI(1, "negotiated posix acl support");
Al Viro2c6292a2011-06-17 09:05:48 -04003256 if (cifs_sb)
3257 cifs_sb->mnt_cifs_flags |=
3258 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003259 }
3260
Steve French75865f8c2007-06-24 18:30:48 +00003261 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003262 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003263 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003264 cFYI(1, "negotiate posix pathnames");
Al Viro2c6292a2011-06-17 09:05:48 -04003265 if (cifs_sb)
3266 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003267 CIFS_MOUNT_POSIX_PATHS;
3268 }
Steve French50c2f752007-07-13 00:33:32 +00003269
Joe Perchesb6b38f72010-04-21 03:50:45 +00003270 cFYI(1, "Negotiate caps 0x%x", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003271#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003272 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003273 cFYI(1, "FCNTL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003274 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003275 cFYI(1, "EXTATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003276 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003277 cFYI(1, "POSIX path cap");
Steve French75865f8c2007-06-24 18:30:48 +00003278 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003279 cFYI(1, "XATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003280 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003281 cFYI(1, "POSIX ACL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003282 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003283 cFYI(1, "very large read cap");
Steve French75865f8c2007-06-24 18:30:48 +00003284 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003285 cFYI(1, "very large write cap");
Steve French6848b732011-05-26 18:38:54 +00003286 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3287 cFYI(1, "transport encryption cap");
3288 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3289 cFYI(1, "mandatory transport encryption cap");
Steve French8af18972007-02-14 04:42:51 +00003290#endif /* CIFS_DEBUG2 */
3291 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003292 if (vol_info == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003293 cFYI(1, "resetting capabilities failed");
Steve French442aa312007-09-24 20:25:46 +00003294 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003295 cERROR(1, "Negotiating Unix capabilities "
Steve French5a44b312007-09-20 15:16:24 +00003296 "with the server failed. Consider "
3297 "mounting with the Unix Extensions\n"
3298 "disabled, if problems are found, "
3299 "by specifying the nounix mount "
Joe Perchesb6b38f72010-04-21 03:50:45 +00003300 "option.");
Steve French5a44b312007-09-20 15:16:24 +00003301
Steve French8af18972007-02-14 04:42:51 +00003302 }
3303 }
3304}
3305
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003306void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3307 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003308{
Jeff Layton2de970f2010-10-06 19:51:12 -04003309 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3310
Al Viro2ced6f62011-06-17 09:20:04 -04003311 spin_lock_init(&cifs_sb->tlink_tree_lock);
3312 cifs_sb->tlink_tree = RB_ROOT;
3313
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003314 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003315 * Temporarily set r/wsize for matching superblock. If we end up using
3316 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003317 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003318 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003319 cifs_sb->wsize = pvolume_info->wsize;
3320
Steve French3b795212008-11-13 19:45:32 +00003321 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3322 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3323 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3324 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Al Viro5206efd2011-07-26 03:22:14 -04003325 cFYI(1, "file mode: 0x%hx dir mode: 0x%hx",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003326 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003327
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303328 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003329 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303330
Steve French3b795212008-11-13 19:45:32 +00003331 if (pvolume_info->noperm)
3332 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3333 if (pvolume_info->setuids)
3334 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3335 if (pvolume_info->server_ino)
3336 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3337 if (pvolume_info->remap)
3338 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3339 if (pvolume_info->no_xattr)
3340 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3341 if (pvolume_info->sfu_emul)
3342 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3343 if (pvolume_info->nobrl)
3344 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003345 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003346 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003347 if (pvolume_info->mand_lock)
3348 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003349 if (pvolume_info->rwpidforward)
3350 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003351 if (pvolume_info->cifs_acl)
3352 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003353 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003354 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003355 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3356 }
3357 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003358 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003359 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3360 }
Steve French3b795212008-11-13 19:45:32 +00003361 if (pvolume_info->override_uid)
3362 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3363 if (pvolume_info->override_gid)
3364 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3365 if (pvolume_info->dynperm)
3366 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303367 if (pvolume_info->fsc)
3368 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003369 if (pvolume_info->multiuser)
3370 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3371 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003372 if (pvolume_info->strict_io)
3373 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003374 if (pvolume_info->direct_io) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003375 cFYI(1, "mounting share using direct i/o");
Steve French3b795212008-11-13 19:45:32 +00003376 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3377 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003378 if (pvolume_info->mfsymlinks) {
3379 if (pvolume_info->sfu_emul) {
3380 cERROR(1, "mount option mfsymlinks ignored if sfu "
3381 "mount option is used");
3382 } else {
3383 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3384 }
3385 }
Steve French3b795212008-11-13 19:45:32 +00003386
3387 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesb6b38f72010-04-21 03:50:45 +00003388 cERROR(1, "mount option dynperm ignored if cifsacl "
3389 "mount option supported");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003390}
3391
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003392/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003393 * When the server supports very large reads and writes via POSIX extensions,
3394 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
3395 * including the RFC1001 length.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003396 *
3397 * Note that this might make for "interesting" allocation problems during
Jeff Layton1190f6a2011-06-22 17:33:57 -04003398 * writeback however as we have to allocate an array of pointers for the
3399 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003400 *
3401 * For reads, there is a similar problem as we need to allocate an array
3402 * of kvecs to handle the receive, though that should only need to be done
3403 * once.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003404 */
Jeff Layton1190f6a2011-06-22 17:33:57 -04003405#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003406#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003407
3408/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003409 * When the server doesn't allow large posix writes, only allow a rsize/wsize
3410 * of 2^17-1 minus the size of the call header. That allows for a read or
3411 * write up to the maximum size described by RFC1002.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003412 */
Pavel Shilovsky94443f42011-10-07 18:57:45 +04003413#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003414#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003415
3416/*
3417 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
3418 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
3419 * a single wsize request with a single call.
3420 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003421#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
3422
3423/*
Jeff Laytonce91acb2012-01-17 16:08:51 -05003424 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
3425 * those values when posix extensions aren't in force. In actuality here, we
3426 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
3427 * to be ok with the extra byte even though Windows doesn't send writes that
3428 * are that large.
3429 *
3430 * Citation:
3431 *
3432 * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003433 */
3434#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
Jeff Laytonce91acb2012-01-17 16:08:51 -05003435#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003436
3437static unsigned int
Steve French96daf2b2011-05-27 04:34:02 +00003438cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003439{
3440 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3441 struct TCP_Server_Info *server = tcon->ses->server;
Jeff Laytonce91acb2012-01-17 16:08:51 -05003442 unsigned int wsize;
3443
3444 /* start with specified wsize, or default */
3445 if (pvolume_info->wsize)
3446 wsize = pvolume_info->wsize;
3447 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3448 wsize = CIFS_DEFAULT_IOSIZE;
3449 else
3450 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003451
3452 /* can server support 24-bit write sizes? (via UNIX extensions) */
3453 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
Jeff Layton1190f6a2011-06-22 17:33:57 -04003454 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003455
Jeff Layton1190f6a2011-06-22 17:33:57 -04003456 /*
3457 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
3458 * Limit it to max buffer offered by the server, minus the size of the
3459 * WRITEX header, not including the 4 byte RFC1001 length.
3460 */
3461 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
3462 (!(server->capabilities & CAP_UNIX) &&
3463 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
3464 wsize = min_t(unsigned int, wsize,
3465 server->maxBuf - sizeof(WRITE_REQ) + 4);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003466
3467 /* hard limit of CIFS_MAX_WSIZE */
3468 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3469
3470 return wsize;
3471}
3472
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003473static unsigned int
3474cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3475{
3476 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3477 struct TCP_Server_Info *server = tcon->ses->server;
3478 unsigned int rsize, defsize;
3479
3480 /*
3481 * Set default value...
3482 *
3483 * HACK alert! Ancient servers have very small buffers. Even though
3484 * MS-CIFS indicates that servers are only limited by the client's
3485 * bufsize for reads, testing against win98se shows that it throws
3486 * INVALID_PARAMETER errors if you try to request too large a read.
3487 *
3488 * If the server advertises a MaxBufferSize of less than one page,
3489 * assume that it also can't satisfy reads larger than that either.
3490 *
3491 * FIXME: Is there a better heuristic for this?
3492 */
3493 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
3494 defsize = CIFS_DEFAULT_IOSIZE;
3495 else if (server->capabilities & CAP_LARGE_READ_X)
3496 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
3497 else if (server->maxBuf >= PAGE_CACHE_SIZE)
3498 defsize = CIFSMaxBufSize;
3499 else
3500 defsize = server->maxBuf - sizeof(READ_RSP);
3501
3502 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
3503
3504 /*
3505 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
3506 * the client's MaxBufferSize.
3507 */
3508 if (!(server->capabilities & CAP_LARGE_READ_X))
3509 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3510
3511 /* hard limit of CIFS_MAX_RSIZE */
3512 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3513
3514 return rsize;
3515}
3516
Igor Mammedove4cce942009-02-10 14:10:26 +03003517static int
Steve French96daf2b2011-05-27 04:34:02 +00003518is_path_accessible(int xid, struct cifs_tcon *tcon,
Igor Mammedove4cce942009-02-10 14:10:26 +03003519 struct cifs_sb_info *cifs_sb, const char *full_path)
3520{
3521 int rc;
Igor Mammedove4cce942009-02-10 14:10:26 +03003522 FILE_ALL_INFO *pfile_info;
3523
Igor Mammedove4cce942009-02-10 14:10:26 +03003524 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
3525 if (pfile_info == NULL)
3526 return -ENOMEM;
3527
3528 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
3529 0 /* not legacy */, cifs_sb->local_nls,
3530 cifs_sb->mnt_cifs_flags &
3531 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton221d1d72011-05-17 06:40:30 -04003532
3533 if (rc == -EOPNOTSUPP || rc == -EINVAL)
3534 rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
3535 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
3536 CIFS_MOUNT_MAP_SPECIAL_CHR);
Igor Mammedove4cce942009-02-10 14:10:26 +03003537 kfree(pfile_info);
3538 return rc;
3539}
3540
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003541static void
3542cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003543{
Sean Finneyb9468452011-04-11 13:19:32 +00003544 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003545 kzfree(volume_info->password);
Steve French13589c42011-08-18 04:41:55 +00003546 if (volume_info->UNCip != volume_info->UNC + 2)
3547 kfree(volume_info->UNCip);
Jesper Juhl95c75452011-08-27 18:58:34 +02003548 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003549 kfree(volume_info->domainname);
3550 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003551 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003552}
3553
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003554void
3555cifs_cleanup_volume_info(struct smb_vol *volume_info)
3556{
3557 if (!volume_info)
3558 return;
3559 cleanup_volume_info_contents(volume_info);
3560 kfree(volume_info);
3561}
3562
3563
Steve French2d6d5892009-04-09 00:36:44 +00003564#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003565/* build_path_to_root returns full path to root when
3566 * we do not have an exiting connection (tcon) */
3567static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003568build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003569 const struct cifs_sb_info *cifs_sb)
3570{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003571 char *full_path, *pos;
3572 unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
3573 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003574
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003575 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003576 if (full_path == NULL)
3577 return ERR_PTR(-ENOMEM);
3578
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003579 strncpy(full_path, vol->UNC, unc_len);
3580 pos = full_path + unc_len;
3581
3582 if (pplen) {
3583 strncpy(pos, vol->prepath, pplen);
3584 pos += pplen;
3585 }
3586
3587 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003588 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003589 cFYI(1, "%s: full_path=%s", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003590 return full_path;
3591}
Sean Finneydd613942011-04-11 13:19:30 +00003592
3593/*
3594 * Perform a dfs referral query for a share and (optionally) prefix
3595 *
Sean Finney046462a2011-04-11 13:19:33 +00003596 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3597 * to a string containing updated options for the submount. Otherwise it
3598 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003599 *
3600 * Returns the rc from get_dfs_path to the caller, which can be used to
3601 * determine whether there were referrals.
3602 */
3603static int
Steve French96daf2b2011-05-27 04:34:02 +00003604expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
Sean Finneydd613942011-04-11 13:19:30 +00003605 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003606 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003607{
3608 int rc;
3609 unsigned int num_referrals = 0;
3610 struct dfs_info3_param *referrals = NULL;
3611 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3612
3613 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3614 if (IS_ERR(full_path))
3615 return PTR_ERR(full_path);
3616
3617 /* For DFS paths, skip the first '\' of the UNC */
3618 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3619
3620 rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
3621 &num_referrals, &referrals,
3622 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3623
3624 if (!rc && num_referrals > 0) {
3625 char *fake_devname = NULL;
3626
3627 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3628 full_path + 1, referrals,
3629 &fake_devname);
3630
3631 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003632
Sean Finneydd613942011-04-11 13:19:30 +00003633 if (IS_ERR(mdata)) {
3634 rc = PTR_ERR(mdata);
3635 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003636 } else {
3637 cleanup_volume_info_contents(volume_info);
3638 memset(volume_info, '\0', sizeof(*volume_info));
3639 rc = cifs_setup_volume_info(volume_info, mdata,
3640 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003641 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003642 kfree(fake_devname);
3643 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003644 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003645 }
3646 kfree(full_path);
3647 return rc;
3648}
Steve French2d6d5892009-04-09 00:36:44 +00003649#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003650
Jeff Layton04db79b2011-07-06 08:10:38 -04003651static int
3652cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3653 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003655 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003656
Jeff Layton04db79b2011-07-06 08:10:38 -04003657 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3658 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
Jeff Layton23db65f2012-05-15 12:20:51 -04003660
Jeff Layton7586b762008-12-01 18:41:49 -05003661 if (volume_info->nullauth) {
Jeff Layton04febab2012-01-17 16:09:15 -05003662 cFYI(1, "Anonymous login");
3663 kfree(volume_info->username);
3664 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003665 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 /* BB fixme parse for domain name here */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003667 cFYI(1, "Username: %s", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668 } else {
Steve Frenchbf820672005-12-01 22:32:42 -08003669 cifserror("No username specified");
Steve French50c2f752007-07-13 00:33:32 +00003670 /* In userspace mount helper we can get user name from alternate
3671 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003672 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 }
3674
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003676 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003677 /* load_nls_default cannot return null */
3678 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003680 volume_info->local_nls = load_nls(volume_info->iocharset);
3681 if (volume_info->local_nls == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003682 cERROR(1, "CIFS mount error: iocharset %s not found",
3683 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003684 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 }
3686 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003687
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003688 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003689}
3690
3691struct smb_vol *
3692cifs_get_volume_info(char *mount_data, const char *devname)
3693{
3694 int rc;
3695 struct smb_vol *volume_info;
3696
3697 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
3698 if (!volume_info)
3699 return ERR_PTR(-ENOMEM);
3700
3701 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3702 if (rc) {
3703 cifs_cleanup_volume_info(volume_info);
3704 volume_info = ERR_PTR(rc);
3705 }
3706
3707 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003708}
3709
3710int
Al Viro2c6292a2011-06-17 09:05:48 -04003711cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003712{
Jeff Layton1daaae82012-03-21 06:30:40 -04003713 int rc;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003714 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003715 struct cifs_ses *pSesInfo;
3716 struct cifs_tcon *tcon;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003717 struct TCP_Server_Info *srvTcp;
3718 char *full_path;
3719 struct tcon_link *tlink;
3720#ifdef CONFIG_CIFS_DFS_UPCALL
3721 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003722#endif
Al Virodd854462011-06-17 08:24:42 -04003723
3724 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3725 if (rc)
3726 return rc;
3727
Jeff Layton20547492011-07-09 12:21:07 -04003728#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003729try_mount_again:
3730 /* cleanup activities if we're chasing a referral */
3731 if (referral_walks_count) {
3732 if (tcon)
3733 cifs_put_tcon(tcon);
3734 else if (pSesInfo)
3735 cifs_put_smb_ses(pSesInfo);
3736
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003737 FreeXid(xid);
3738 }
3739#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003740 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003741 tcon = NULL;
3742 pSesInfo = NULL;
3743 srvTcp = NULL;
3744 full_path = NULL;
3745 tlink = NULL;
3746
3747 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
Jeff Layton63c038c2008-12-01 18:41:46 -05003749 /* get a reference to a tcp session */
Jeff Layton7586b762008-12-01 18:41:49 -05003750 srvTcp = cifs_get_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05003751 if (IS_ERR(srvTcp)) {
3752 rc = PTR_ERR(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003753 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003754 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 }
3756
Jeff Layton36988c72010-04-24 07:57:43 -04003757 /* get a reference to a SMB session */
3758 pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
3759 if (IS_ERR(pSesInfo)) {
3760 rc = PTR_ERR(pSesInfo);
3761 pSesInfo = NULL;
3762 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 }
Steve French50c2f752007-07-13 00:33:32 +00003764
Jeff Laytond00c28d2010-04-24 07:57:44 -04003765 /* search for existing tcon to this server share */
3766 tcon = cifs_get_tcon(pSesInfo, volume_info);
3767 if (IS_ERR(tcon)) {
3768 rc = PTR_ERR(tcon);
3769 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003770 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003771 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003772
Steve French6848b732011-05-26 18:38:54 +00003773 /* tell server which Unix caps we support */
3774 if (tcon->ses->capabilities & CAP_UNIX) {
3775 /* reset of caps checks mount to see if unix extensions
3776 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003777 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003778 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3779 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3780 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3781 rc = -EACCES;
3782 goto mount_fail_check;
3783 }
3784 } else
3785 tcon->unix_ext = 0; /* server does not support them */
3786
Steve Frenchd82c2df2008-11-15 00:07:26 +00003787 /* do not care if following two calls succeed - informational */
3788 if (!tcon->ipc) {
3789 CIFSSMBQFSDeviceInfo(xid, tcon);
3790 CIFSSMBQFSAttributeInfo(xid, tcon);
3791 }
3792
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003793 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003794 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003795
Jeff Layton66bfaad2011-10-19 15:30:35 -04003796 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003797 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003798
Igor Mammedove4cce942009-02-10 14:10:26 +03003799remote_path_check:
3800#ifdef CONFIG_CIFS_DFS_UPCALL
3801 /*
3802 * Perform an unconditional check for whether there are DFS
3803 * referrals for this path without prefix, to provide support
3804 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003805 * with PATH_NOT_COVERED to requests that include the prefix.
3806 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003807 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003808 if (referral_walks_count == 0) {
3809 int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
3810 cifs_sb, false);
3811 if (!refrc) {
3812 referral_walks_count++;
3813 goto try_mount_again;
3814 }
3815 }
3816#endif
3817
Steve Frenchf87d39d2011-05-27 03:50:55 +00003818 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 if (!rc && tcon) {
3820 /* build_path_to_root works only when we have a valid tcon */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003821 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Steve French7c7b25b2006-06-01 19:20:10 +00003822 if (full_path == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823 rc = -ENOMEM;
3824 goto mount_fail_check;
3825 }
3826 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
3827 if (rc != 0 && rc != -EREMOTE) {
3828 kfree(full_path);
3829 goto mount_fail_check;
3830 }
3831 kfree(full_path);
3832 }
3833
3834 /* get referral if needed */
3835 if (rc == -EREMOTE) {
3836#ifdef CONFIG_CIFS_DFS_UPCALL
3837 if (referral_walks_count > MAX_NESTED_LINKS) {
3838 /*
Steve Frencheeac8042006-01-13 21:34:58 -08003839 * BB: when we implement proper loop detection,
Steve French4523cc32007-04-30 20:13:06 +00003840 * we will remove this check. But now we need it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 * to prevent an indefinite loop if 'DFS tree' is
3842 * misconfigured (i.e. has loops).
3843 */
3844 rc = -ELOOP;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003845 goto mount_fail_check;
3846 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003847
Sean Finneydd613942011-04-11 13:19:30 +00003848 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003849 true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003850
Sean Finneydd613942011-04-11 13:19:30 +00003851 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003852 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003853 goto try_mount_again;
3854 }
Sean Finneydd613942011-04-11 13:19:30 +00003855 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003856#else /* No DFS support, return error on mount */
3857 rc = -EOPNOTSUPP;
3858#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003859 }
3860
Jeff Layton9d002df2010-10-06 19:51:11 -04003861 if (rc)
3862 goto mount_fail_check;
3863
3864 /* now, hang the tcon off of the superblock */
3865 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3866 if (tlink == NULL) {
3867 rc = -ENOMEM;
3868 goto mount_fail_check;
3869 }
3870
Jeff Laytonb647c352010-10-28 11:16:44 -04003871 tlink->tl_uid = pSesInfo->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003872 tlink->tl_tcon = tcon;
3873 tlink->tl_time = jiffies;
3874 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3875 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3876
Jeff Layton413e6612010-10-28 13:33:38 -04003877 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003878 spin_lock(&cifs_sb->tlink_tree_lock);
3879 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3880 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003881
Jeff Laytonda472fc2012-03-23 14:40:53 -04003882 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003883 TLINK_IDLE_EXPIRE);
3884
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003885mount_fail_check:
3886 /* on error free sesinfo and tcon struct if needed */
3887 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003888 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003889 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003890 if (tcon)
3891 cifs_put_tcon(tcon);
3892 else if (pSesInfo)
3893 cifs_put_smb_ses(pSesInfo);
3894 else
3895 cifs_put_tcp_session(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003896 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003897 }
3898
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 FreeXid(xid);
3901 return rc;
3902}
3903
Jeff Layton8d1bca32011-06-11 21:17:10 -04003904/*
3905 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3906 * pointer may be NULL.
3907 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908int
Steve French96daf2b2011-05-27 04:34:02 +00003909CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3910 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 const struct nls_table *nls_codepage)
3912{
3913 struct smb_hdr *smb_buffer;
3914 struct smb_hdr *smb_buffer_response;
3915 TCONX_REQ *pSMB;
3916 TCONX_RSP *pSMBr;
3917 unsigned char *bcc_ptr;
3918 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003919 int length;
3920 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921
3922 if (ses == NULL)
3923 return -EIO;
3924
3925 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003926 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003928
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 smb_buffer_response = smb_buffer;
3930
3931 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3932 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003933
3934 smb_buffer->Mid = GetNextMid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 smb_buffer->Uid = ses->Suid;
3936 pSMB = (TCONX_REQ *) smb_buffer;
3937 pSMBr = (TCONX_RSP *) smb_buffer_response;
3938
3939 pSMB->AndXCommand = 0xFF;
3940 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003942 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003943 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003944 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003945 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003946 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003947 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003948 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003949 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3950 specified as required (when that support is added to
3951 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003952 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003953 by Samba (not sure whether other servers allow
3954 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003955#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003956 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003957 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003958 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003959 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003960 SECMODE_PW_ENCRYPT ? true : false,
3961 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003962 else
3963#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003964 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003965 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003966
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003967 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003968 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003969 /* must align unicode strings */
3970 *bcc_ptr = 0; /* null byte password */
3971 bcc_ptr++;
3972 }
Steve Frencheeac8042006-01-13 21:34:58 -08003973 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
Steve French96daf2b2011-05-27 04:34:02 +00003975 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003976 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3978
3979 if (ses->capabilities & CAP_STATUS32) {
3980 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3981 }
3982 if (ses->capabilities & CAP_DFS) {
3983 smb_buffer->Flags2 |= SMBFLG2_DFS;
3984 }
3985 if (ses->capabilities & CAP_UNICODE) {
3986 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3987 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003988 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003989 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003990 (/* server len*/ + 256 /* share len */), nls_codepage);
3991 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 bcc_ptr += 2; /* skip trailing null */
3993 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 strcpy(bcc_ptr, tree);
3995 bcc_ptr += strlen(tree) + 1;
3996 }
3997 strcpy(bcc_ptr, "?????");
3998 bcc_ptr += strlen("?????");
3999 bcc_ptr += 1;
4000 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004001 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4002 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 pSMB->ByteCount = cpu_to_le16(count);
4004
Steve French133672e2007-11-13 22:41:37 +00004005 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004006 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 /* above now done in SendReceive */
4009 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004010 bool is_unicode;
4011
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004013 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 tcon->tid = smb_buffer_response->Tid;
4015 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004016 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004017 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004018 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4019 is_unicode = true;
4020 else
4021 is_unicode = false;
4022
Jeff Laytoncc20c032009-04-30 07:16:21 -04004023
Steve French50c2f752007-07-13 00:33:32 +00004024 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004025 if (length == 3) {
4026 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4027 (bcc_ptr[2] == 'C')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004028 cFYI(1, "IPC connection");
Steve French7f8ed422007-09-28 22:28:55 +00004029 tcon->ipc = 1;
4030 }
4031 } else if (length == 2) {
4032 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4033 /* the most common case */
Joe Perchesb6b38f72010-04-21 03:50:45 +00004034 cFYI(1, "disk share connection");
Steve French7f8ed422007-09-28 22:28:55 +00004035 }
4036 }
Steve French50c2f752007-07-13 00:33:32 +00004037 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004038 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004040
4041 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004042 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004043 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004044 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004045 nls_codepage);
4046
Joe Perchesb6b38f72010-04-21 03:50:45 +00004047 cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004048
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004049 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004050 (smb_buffer_response->WordCount == 7))
4051 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004052 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4053 else
4054 tcon->Flags = 0;
Joe Perchesb6b38f72010-04-21 03:50:45 +00004055 cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004057 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 ses->ipc_tid = smb_buffer_response->Tid;
4059 }
4060
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004061 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062 return rc;
4063}
4064
Al Viro2a9b9952011-06-17 09:27:16 -04004065void
4066cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067{
Jeff Laytonb647c352010-10-28 11:16:44 -04004068 struct rb_root *root = &cifs_sb->tlink_tree;
4069 struct rb_node *node;
4070 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
Jeff Layton2de970f2010-10-06 19:51:12 -04004072 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4073
Jeff Laytonb647c352010-10-28 11:16:44 -04004074 spin_lock(&cifs_sb->tlink_tree_lock);
4075 while ((node = rb_first(root))) {
4076 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4077 cifs_get_tlink(tlink);
4078 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4079 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004080
Jeff Laytonb647c352010-10-28 11:16:44 -04004081 spin_unlock(&cifs_sb->tlink_tree_lock);
4082 cifs_put_tlink(tlink);
4083 spin_lock(&cifs_sb->tlink_tree_lock);
4084 }
4085 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004086
Al Virodd854462011-06-17 08:24:42 -04004087 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004088 kfree(cifs_sb->mountdata);
4089 unload_nls(cifs_sb->local_nls);
4090 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00004091}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
Steve French96daf2b2011-05-27 04:34:02 +00004093int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094{
4095 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004096 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
Jeff Layton198b5682010-04-24 07:57:48 -04004098 /* only send once per connect */
4099 if (server->maxBuf != 0)
4100 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004102 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004103 rc = CIFSSMBNegotiate(xid, ses);
4104 if (rc == -EAGAIN) {
4105 /* retry only once on 1st time connection */
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004106 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004107 rc = CIFSSMBNegotiate(xid, ses);
4108 if (rc == -EAGAIN)
4109 rc = -EHOSTDOWN;
4110 }
4111 if (rc == 0) {
4112 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004113 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004114 server->tcpStatus = CifsGood;
4115 else
4116 rc = -EHOSTDOWN;
4117 spin_unlock(&GlobalMid_Lock);
4118
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 }
Steve French26b994f2008-08-06 05:11:33 +00004120
Jeff Layton198b5682010-04-24 07:57:48 -04004121 return rc;
4122}
Steve French26b994f2008-08-06 05:11:33 +00004123
Jeff Layton198b5682010-04-24 07:57:48 -04004124
Steve French96daf2b2011-05-27 04:34:02 +00004125int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
Jeff Layton198b5682010-04-24 07:57:48 -04004126 struct nls_table *nls_info)
4127{
4128 int rc = 0;
4129 struct TCP_Server_Info *server = ses->server;
4130
4131 ses->flags = 0;
4132 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004133 if (linuxExtEnabled == 0)
Jeff Layton198b5682010-04-24 07:57:48 -04004134 ses->capabilities &= (~CAP_UNIX);
Steve French20418ac2009-04-30 16:13:32 +00004135
Joe Perchesb6b38f72010-04-21 03:50:45 +00004136 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
Steve French96daf2b2011-05-27 04:34:02 +00004137 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004138
Jeff Layton198b5682010-04-24 07:57:48 -04004139 rc = CIFS_SessSetup(xid, ses, nls_info);
Steve French26b994f2008-08-06 05:11:33 +00004140 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004141 cERROR(1, "Send error in SessSetup = %d", rc);
Steve French26b994f2008-08-06 05:11:33 +00004142 } else {
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004143 mutex_lock(&ses->server->srv_mutex);
4144 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004145 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004146 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004147 server->sequence_number = 0x2;
4148 server->session_estab = true;
4149 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004150 }
4151 mutex_unlock(&server->srv_mutex);
4152
Joe Perchesb6b38f72010-04-21 03:50:45 +00004153 cFYI(1, "CIFS Session Established successfully");
Steve French20418ac2009-04-30 16:13:32 +00004154 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04004155 ses->status = CifsGood;
4156 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00004157 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00004158 }
4159
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004160 kfree(ses->auth_key.response);
4161 ses->auth_key.response = NULL;
4162 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05004163 kfree(ses->ntlmssp);
4164 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004165
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 return rc;
4167}
4168
Jeff Layton8a8798a2012-01-17 16:09:15 -05004169static int
4170cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4171{
4172 switch (ses->server->secType) {
4173 case Kerberos:
4174 vol->secFlg = CIFSSEC_MUST_KRB5;
4175 return 0;
4176 case NTLMv2:
4177 vol->secFlg = CIFSSEC_MUST_NTLMV2;
4178 break;
4179 case NTLM:
4180 vol->secFlg = CIFSSEC_MUST_NTLM;
4181 break;
4182 case RawNTLMSSP:
4183 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
4184 break;
4185 case LANMAN:
4186 vol->secFlg = CIFSSEC_MUST_LANMAN;
4187 break;
4188 }
4189
4190 return cifs_set_cifscreds(vol, ses);
4191}
4192
Steve French96daf2b2011-05-27 04:34:02 +00004193static struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004194cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
4195{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004196 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004197 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4198 struct cifs_ses *ses;
4199 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004200 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004201
4202 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004203 if (vol_info == NULL)
4204 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004205
Jeff Layton9d002df2010-10-06 19:51:11 -04004206 vol_info->local_nls = cifs_sb->local_nls;
4207 vol_info->linux_uid = fsuid;
4208 vol_info->cred_uid = fsuid;
4209 vol_info->UNC = master_tcon->treeName;
4210 vol_info->retry = master_tcon->retry;
4211 vol_info->nocase = master_tcon->nocase;
4212 vol_info->local_lease = master_tcon->local_lease;
4213 vol_info->no_linux_ext = !master_tcon->unix_ext;
4214
Jeff Layton8a8798a2012-01-17 16:09:15 -05004215 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4216 if (rc) {
4217 tcon = ERR_PTR(rc);
4218 goto out;
4219 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004220
4221 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304222 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004223 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304224 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004225
4226 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4227 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004228 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004229 cifs_put_tcp_session(master_tcon->ses->server);
4230 goto out;
4231 }
4232
4233 tcon = cifs_get_tcon(ses, vol_info);
4234 if (IS_ERR(tcon)) {
4235 cifs_put_smb_ses(ses);
4236 goto out;
4237 }
4238
4239 if (ses->capabilities & CAP_UNIX)
4240 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4241out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004242 kfree(vol_info->username);
4243 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004244 kfree(vol_info);
4245
4246 return tcon;
4247}
4248
Steve French96daf2b2011-05-27 04:34:02 +00004249struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004250cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4251{
4252 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4253}
4254
4255static int
4256cifs_sb_tcon_pending_wait(void *unused)
4257{
4258 schedule();
4259 return signal_pending(current) ? -ERESTARTSYS : 0;
4260}
4261
Jeff Laytonb647c352010-10-28 11:16:44 -04004262/* find and return a tlink with given uid */
4263static struct tcon_link *
4264tlink_rb_search(struct rb_root *root, uid_t uid)
4265{
4266 struct rb_node *node = root->rb_node;
4267 struct tcon_link *tlink;
4268
4269 while (node) {
4270 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4271
4272 if (tlink->tl_uid > uid)
4273 node = node->rb_left;
4274 else if (tlink->tl_uid < uid)
4275 node = node->rb_right;
4276 else
4277 return tlink;
4278 }
4279 return NULL;
4280}
4281
4282/* insert a tcon_link into the tree */
4283static void
4284tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4285{
4286 struct rb_node **new = &(root->rb_node), *parent = NULL;
4287 struct tcon_link *tlink;
4288
4289 while (*new) {
4290 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4291 parent = *new;
4292
4293 if (tlink->tl_uid > new_tlink->tl_uid)
4294 new = &((*new)->rb_left);
4295 else
4296 new = &((*new)->rb_right);
4297 }
4298
4299 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4300 rb_insert_color(&new_tlink->tl_rbnode, root);
4301}
4302
Jeff Layton9d002df2010-10-06 19:51:11 -04004303/*
4304 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4305 * current task.
4306 *
4307 * If the superblock doesn't refer to a multiuser mount, then just return
4308 * the master tcon for the mount.
4309 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304310 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004311 * exists, then check to see if it's pending construction. If it is then wait
4312 * for construction to complete. Once it's no longer pending, check to see if
4313 * it failed and either return an error or retry construction, depending on
4314 * the timeout.
4315 *
4316 * If one doesn't exist then insert a new tcon_link struct into the tree and
4317 * try to construct a new one.
4318 */
4319struct tcon_link *
4320cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4321{
4322 int ret;
Jeff Laytonb647c352010-10-28 11:16:44 -04004323 uid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004324 struct tcon_link *tlink, *newtlink;
4325
4326 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4327 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4328
4329 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004330 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004331 if (tlink)
4332 cifs_get_tlink(tlink);
4333 spin_unlock(&cifs_sb->tlink_tree_lock);
4334
4335 if (tlink == NULL) {
4336 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4337 if (newtlink == NULL)
4338 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004339 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004340 newtlink->tl_tcon = ERR_PTR(-EACCES);
4341 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4342 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4343 cifs_get_tlink(newtlink);
4344
Jeff Layton9d002df2010-10-06 19:51:11 -04004345 spin_lock(&cifs_sb->tlink_tree_lock);
4346 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004347 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004348 if (tlink) {
4349 cifs_get_tlink(tlink);
4350 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004351 kfree(newtlink);
4352 goto wait_for_construction;
4353 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004354 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004355 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4356 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004357 } else {
4358wait_for_construction:
4359 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4360 cifs_sb_tcon_pending_wait,
4361 TASK_INTERRUPTIBLE);
4362 if (ret) {
4363 cifs_put_tlink(tlink);
4364 return ERR_PTR(ret);
4365 }
4366
4367 /* if it's good, return it */
4368 if (!IS_ERR(tlink->tl_tcon))
4369 return tlink;
4370
4371 /* return error if we tried this already recently */
4372 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4373 cifs_put_tlink(tlink);
4374 return ERR_PTR(-EACCES);
4375 }
4376
4377 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4378 goto wait_for_construction;
4379 }
4380
4381 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4382 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4383 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4384
4385 if (IS_ERR(tlink->tl_tcon)) {
4386 cifs_put_tlink(tlink);
4387 return ERR_PTR(-EACCES);
4388 }
4389
4390 return tlink;
4391}
Jeff Layton2de970f2010-10-06 19:51:12 -04004392
4393/*
4394 * periodic workqueue job that scans tcon_tree for a superblock and closes
4395 * out tcons.
4396 */
4397static void
4398cifs_prune_tlinks(struct work_struct *work)
4399{
4400 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4401 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004402 struct rb_root *root = &cifs_sb->tlink_tree;
4403 struct rb_node *node = rb_first(root);
4404 struct rb_node *tmp;
4405 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004406
Jeff Laytonb647c352010-10-28 11:16:44 -04004407 /*
4408 * Because we drop the spinlock in the loop in order to put the tlink
4409 * it's not guarded against removal of links from the tree. The only
4410 * places that remove entries from the tree are this function and
4411 * umounts. Because this function is non-reentrant and is canceled
4412 * before umount can proceed, this is safe.
4413 */
4414 spin_lock(&cifs_sb->tlink_tree_lock);
4415 node = rb_first(root);
4416 while (node != NULL) {
4417 tmp = node;
4418 node = rb_next(tmp);
4419 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4420
4421 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4422 atomic_read(&tlink->tl_count) != 0 ||
4423 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4424 continue;
4425
4426 cifs_get_tlink(tlink);
4427 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4428 rb_erase(tmp, root);
4429
Jeff Layton2de970f2010-10-06 19:51:12 -04004430 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004431 cifs_put_tlink(tlink);
4432 spin_lock(&cifs_sb->tlink_tree_lock);
4433 }
4434 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004435
Jeff Laytonda472fc2012-03-23 14:40:53 -04004436 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004437 TLINK_IDLE_EXPIRE);
4438}