blob: 65ec6ef0995ed1c65a88c397cc967a09049c0865 [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
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400786static struct mid_q_entry *
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400787find_mid(struct TCP_Server_Info *server, char *buffer)
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400788{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400789 struct smb_hdr *buf = (struct smb_hdr *)buffer;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400790 struct mid_q_entry *mid;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400791
792 spin_lock(&GlobalMid_Lock);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400793 list_for_each_entry(mid, &server->pending_mid_q, qhead) {
794 if (mid->mid == buf->Mid &&
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400795 mid->mid_state == MID_REQUEST_SUBMITTED &&
796 le16_to_cpu(mid->command) == buf->Command) {
Jeff Laytonea1f4502011-10-19 15:29:05 -0400797 spin_unlock(&GlobalMid_Lock);
798 return mid;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400799 }
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400800 }
801 spin_unlock(&GlobalMid_Lock);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400802 return NULL;
803}
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400804
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400805void
806dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400807{
808#ifdef CONFIG_CIFS_STATS2
809 mid->when_received = jiffies;
810#endif
811 spin_lock(&GlobalMid_Lock);
812 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400813 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400814 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400815 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400816 list_del_init(&mid->qhead);
817 spin_unlock(&GlobalMid_Lock);
818}
819
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400820static void
821handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400822 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400823{
Jeff Laytonffc00e22011-10-19 15:29:13 -0400824 if (malformed == 0 && check2ndT2(buf) > 0) {
825 mid->multiRsp = true;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400826 if (mid->resp_buf) {
827 /* merge response - fix up 1st*/
Jeff Laytonffc00e22011-10-19 15:29:13 -0400828 malformed = coalesce_t2(buf, mid->resp_buf);
829 if (malformed > 0)
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400830 return;
Jeff Laytonffc00e22011-10-19 15:29:13 -0400831
Jeff Laytonea1f4502011-10-19 15:29:05 -0400832 /* All parts received or packet is malformed. */
833 mid->multiEnd = true;
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400834 return dequeue_mid(mid, malformed);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400835 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400836 if (!server->large_buf) {
Jeff Laytonea1f4502011-10-19 15:29:05 -0400837 /*FIXME: switch to already allocated largebuf?*/
838 cERROR(1, "1st trans2 resp needs bigbuf");
839 } else {
840 /* Have first buffer */
841 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400842 mid->large_buf = true;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400843 server->bigbuf = NULL;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400844 }
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400845 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400846 }
847 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400848 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400849 /* Was previous buf put in mpx struct for multi-rsp? */
850 if (!mid->multiRsp) {
851 /* smb buffer will be freed by user thread */
852 if (server->large_buf)
853 server->bigbuf = NULL;
854 else
855 server->smallbuf = NULL;
856 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400857 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400858}
859
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400860static void clean_demultiplex_info(struct TCP_Server_Info *server)
861{
862 int length;
863
864 /* take it off the list, if it's not already */
865 spin_lock(&cifs_tcp_ses_lock);
866 list_del_init(&server->tcp_ses_list);
867 spin_unlock(&cifs_tcp_ses_lock);
868
869 spin_lock(&GlobalMid_Lock);
870 server->tcpStatus = CifsExiting;
871 spin_unlock(&GlobalMid_Lock);
872 wake_up_all(&server->response_q);
873
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400874 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300875 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400876 if (server->credits <= 0)
877 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300878 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400879 /*
880 * Although there should not be any requests blocked on this queue it
881 * can not hurt to be paranoid and try to wake up requests that may
882 * haven been blocked when more than 50 at time were on the wire to the
883 * same server - they now will see the session is in exit state and get
884 * out of SendReceive.
885 */
886 wake_up_all(&server->request_q);
887 /* give those requests time to exit */
888 msleep(125);
889
890 if (server->ssocket) {
891 sock_release(server->ssocket);
892 server->ssocket = NULL;
893 }
894
895 if (!list_empty(&server->pending_mid_q)) {
896 struct list_head dispose_list;
897 struct mid_q_entry *mid_entry;
898 struct list_head *tmp, *tmp2;
899
900 INIT_LIST_HEAD(&dispose_list);
901 spin_lock(&GlobalMid_Lock);
902 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
903 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400904 cFYI(1, "Clearing mid 0x%llx", mid_entry->mid);
905 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400906 list_move(&mid_entry->qhead, &dispose_list);
907 }
908 spin_unlock(&GlobalMid_Lock);
909
910 /* now walk dispose list and issue callbacks */
911 list_for_each_safe(tmp, tmp2, &dispose_list) {
912 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400913 cFYI(1, "Callback mid 0x%llx", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400914 list_del_init(&mid_entry->qhead);
915 mid_entry->callback(mid_entry);
916 }
917 /* 1/8th of sec is more than enough time for them to exit */
918 msleep(125);
919 }
920
921 if (!list_empty(&server->pending_mid_q)) {
922 /*
923 * mpx threads have not exited yet give them at least the smb
924 * send timeout time for long ops.
925 *
926 * Due to delays on oplock break requests, we need to wait at
927 * least 45 seconds before giving up on a request getting a
928 * response and going ahead and killing cifsd.
929 */
930 cFYI(1, "Wait for exit from demultiplex thread");
931 msleep(46000);
932 /*
933 * If threads still have not exited they are probably never
934 * coming home not much else we can do but free the memory.
935 */
936 }
937
938 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400939 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400940 kfree(server);
941
942 length = atomic_dec_return(&tcpSesAllocCount);
943 if (length > 0)
944 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
945 GFP_KERNEL);
946}
947
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400948static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400949standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
950{
951 int length;
952 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400953 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400954
955 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400956 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Jeff Laytone9097ab2011-10-19 15:29:40 -0400957 cERROR(1, "SMB response too long (%u bytes)",
958 pdu_length);
959 cifs_reconnect(server);
960 wake_up(&server->response_q);
961 return -EAGAIN;
962 }
963
964 /* switch to large buffer if too big for a small one */
965 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
966 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400967 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400968 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400969 }
970
971 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400972 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
973 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400974 if (length < 0)
975 return length;
976 server->total_read += length;
977
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400978 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400979
980 /*
981 * We know that we received enough to get to the MID as we
982 * checked the pdu_length earlier. Now check to see
983 * if the rest of the header is OK. We borrow the length
984 * var for the rest of the loop to avoid a new stack var.
985 *
986 * 48 bytes is enough to display the header and a little bit
987 * into the payload for debugging purposes.
988 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400989 length = checkSMB(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400990 if (length != 0)
991 cifs_dump_mem("Bad SMB: ", buf,
992 min_t(unsigned int, server->total_read, 48));
993
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500994 if (!mid)
995 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400996
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400997 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500998 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400999}
1000
1001static int
Al Viro7c97c202011-06-21 08:51:28 -04001002cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003{
1004 int length;
Al Viro7c97c202011-06-21 08:51:28 -04001005 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001006 unsigned int pdu_length;
1007 char *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 struct task_struct *task_to_wake = NULL;
1009 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 current->flags |= PF_MEMALLOC;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001012 cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001013
1014 length = atomic_inc_return(&tcpSesAllocCount);
1015 if (length > 1)
Steve French26f57362007-08-30 22:09:15 +00001016 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
1017 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001019 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +00001020 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001021 if (try_to_freeze())
1022 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001023
Jeff Layton2a37ef92011-10-19 15:29:23 -04001024 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001025 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001026
Jeff Layton2a37ef92011-10-19 15:29:23 -04001027 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001028 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001029 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001030
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001031 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001032 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001033 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001034 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001035
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001036 /*
1037 * The right amount was read from socket - 4 bytes,
1038 * so we can now interpret the length field.
1039 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001040 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001041
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001042 cFYI(1, "RFC1002 header 0x%x", pdu_length);
1043 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001044 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001045
Jeff Layton89482a52011-10-19 15:28:57 -04001046 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001047 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Jeff Layton89482a52011-10-19 15:28:57 -04001048 cERROR(1, "SMB response too short (%u bytes)",
1049 pdu_length);
1050 cifs_reconnect(server);
1051 wake_up(&server->response_q);
1052 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001053 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001054
Jeff Layton89482a52011-10-19 15:28:57 -04001055 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001056 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001057 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -04001058 if (length < 0)
1059 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001060 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001061
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001062 mid_entry = find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001063
Jeff Layton44d22d82011-10-19 15:29:49 -04001064 if (!mid_entry || !mid_entry->receive)
1065 length = standard_receive3(server, mid_entry);
1066 else
1067 length = mid_entry->receive(server, mid_entry);
1068
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001069 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -07001070 continue;
1071
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001072 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001073 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001074
Steve Frenchfda35942011-01-20 18:06:34 +00001075 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -05001076 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -04001077 if (!mid_entry->multiRsp || mid_entry->multiEnd)
1078 mid_entry->callback(mid_entry);
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001079 } else if (!is_valid_oplock_break(buf, server)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001080 cERROR(1, "No task to wake, unknown frame received! "
Jeff Layton80975312011-01-11 07:24:02 -05001081 "NumMids %d", atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001082 cifs_dump_mem("Received Data is: ", buf,
1083 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +00001084#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001085 cifs_dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +00001086 cifs_dump_mids(server);
1087#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +00001088
Steve Frenche4eb2952005-04-28 22:41:09 -07001089 }
1090 } /* end while !EXITING */
1091
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001092 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001093 cifs_buf_release(server->bigbuf);
1094 if (server->smallbuf) /* no sense logging a debug message if NULL */
1095 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001097 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001098 clean_demultiplex_info(server);
Steve French50c2f752007-07-13 00:33:32 +00001099
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001100 /* if server->tsk was NULL then wait for a signal before exiting */
1101 if (!task_to_wake) {
1102 set_current_state(TASK_INTERRUPTIBLE);
1103 while (!signal_pending(current)) {
1104 schedule();
1105 set_current_state(TASK_INTERRUPTIBLE);
1106 }
1107 set_current_state(TASK_RUNNING);
1108 }
1109
Jeff Layton0468a2c2008-12-01 07:09:35 -05001110 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
Jeff Laytonc359cf32007-11-16 22:22:06 +00001113/* extract the host portion of the UNC string */
1114static char *
1115extract_hostname(const char *unc)
1116{
1117 const char *src;
1118 char *dst, *delim;
1119 unsigned int len;
1120
1121 /* skip double chars at beginning of string */
1122 /* BB: check validity of these bytes? */
1123 src = unc + 2;
1124
1125 /* delimiter between hostname and sharename is always '\\' now */
1126 delim = strchr(src, '\\');
1127 if (!delim)
1128 return ERR_PTR(-EINVAL);
1129
1130 len = delim - src;
1131 dst = kmalloc((len + 1), GFP_KERNEL);
1132 if (dst == NULL)
1133 return ERR_PTR(-ENOMEM);
1134
1135 memcpy(dst, src, len);
1136 dst[len] = '\0';
1137
1138 return dst;
1139}
1140
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001141static int get_option_ul(substring_t args[], unsigned long *option)
1142{
1143 int rc;
1144 char *string;
1145
1146 string = match_strdup(args);
1147 if (string == NULL)
1148 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001149 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001150 kfree(string);
1151
1152 return rc;
1153}
1154
1155
1156static int cifs_parse_security_flavors(char *value,
1157 struct smb_vol *vol)
1158{
1159
1160 substring_t args[MAX_OPT_ARGS];
1161
1162 switch (match_token(value, cifs_secflavor_tokens, args)) {
1163 case Opt_sec_krb5:
1164 vol->secFlg |= CIFSSEC_MAY_KRB5;
1165 break;
1166 case Opt_sec_krb5i:
1167 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
1168 break;
1169 case Opt_sec_krb5p:
1170 /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
1171 cERROR(1, "Krb5 cifs privacy not supported");
1172 break;
1173 case Opt_sec_ntlmssp:
1174 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1175 break;
1176 case Opt_sec_ntlmsspi:
1177 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
1178 break;
1179 case Opt_ntlm:
1180 /* ntlm is default so can be turned off too */
1181 vol->secFlg |= CIFSSEC_MAY_NTLM;
1182 break;
1183 case Opt_sec_ntlmi:
1184 vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
1185 break;
1186 case Opt_sec_nontlm:
1187 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1188 break;
1189 case Opt_sec_ntlmv2i:
1190 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
1191 break;
1192#ifdef CONFIG_CIFS_WEAK_PW_HASH
1193 case Opt_sec_lanman:
1194 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1195 break;
1196#endif
1197 case Opt_sec_none:
1198 vol->nullauth = 1;
1199 break;
1200 default:
1201 cERROR(1, "bad security option: %s", value);
1202 return 1;
1203 }
1204
1205 return 0;
1206}
1207
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001209cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1210{
1211 substring_t args[MAX_OPT_ARGS];
1212
1213 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1214 case Opt_cache_loose:
1215 vol->direct_io = false;
1216 vol->strict_io = false;
1217 break;
1218 case Opt_cache_strict:
1219 vol->direct_io = false;
1220 vol->strict_io = true;
1221 break;
1222 case Opt_cache_none:
1223 vol->direct_io = true;
1224 vol->strict_io = false;
1225 break;
1226 default:
1227 cERROR(1, "bad cache= option: %s", value);
1228 return 1;
1229 }
1230 return 0;
1231}
1232
1233static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001234cifs_parse_smb_version(char *value, struct smb_vol *vol)
1235{
1236 substring_t args[MAX_OPT_ARGS];
1237
1238 switch (match_token(value, cifs_smb_version_tokens, args)) {
1239 case Smb_1:
1240 vol->ops = &smb1_operations;
1241 vol->vals = &smb1_values;
1242 break;
1243 default:
1244 cERROR(1, "Unknown vers= option specified: %s", value);
1245 return 1;
1246 }
1247 return 0;
1248}
1249
1250static int
Sean Finneyb9468452011-04-11 13:19:32 +00001251cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001252 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001254 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001255 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 unsigned int temp_len, i, j;
1257 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001258 short int override_uid = -1;
1259 short int override_gid = -1;
1260 bool uid_specified = false;
1261 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001262 bool sloppy = false;
1263 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001264 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001265 char *string = NULL;
1266 char *tmp_end, *value;
1267 char delim;
Jeff Layton296838b2012-05-16 07:53:01 -04001268 bool cache_specified = false;
1269 static bool cache_warned = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001272 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001273 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Jeff Layton88463992010-11-22 15:31:03 -05001275 /*
1276 * does not have to be perfect mapping since field is
1277 * informational, only used for servers that do not support
1278 * port 445 and it can be overridden at mount time
1279 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001280 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1281 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001282 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1283
Jeff Layton1397f2e2011-01-07 11:30:28 -05001284 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001285 /* null target name indicates to use *SMBSERVR default called name
1286 if we end up sending RFC1001 session initialize */
1287 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001288 vol->cred_uid = current_uid();
1289 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001290 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001291
1292 /* default to only allowing write access to owner of the mount */
1293 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
1295 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001296 /* default is always to request posix paths. */
1297 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001298 /* default to using server inode numbers where available */
1299 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001300
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301301 vol->actimeo = CIFS_DEF_ACTIMEO;
1302
Jeff Layton23db65f2012-05-15 12:20:51 -04001303 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1304 vol->ops = &smb1_operations;
1305 vol->vals = &smb1_values;
1306
Sean Finneyb9468452011-04-11 13:19:32 +00001307 if (!mountdata)
1308 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Sean Finneyb9468452011-04-11 13:19:32 +00001310 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1311 if (!mountdata_copy)
1312 goto cifs_parse_mount_err;
1313
1314 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001315 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001316
Steve French50c2f752007-07-13 00:33:32 +00001317 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001318 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 separator[0] = options[4];
1320 options += 5;
1321 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001322 cFYI(1, "Null separator not allowed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 }
1324 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001325 vol->backupuid_specified = false; /* no backup intent for a user */
1326 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001327
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001329 substring_t args[MAX_OPT_ARGS];
1330 unsigned long option;
1331 int token;
1332
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if (!*data)
1334 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001336 token = match_token(data, cifs_mount_option_tokens, args);
1337
1338 switch (token) {
1339
1340 /* Ingnore the following */
1341 case Opt_ignore:
1342 break;
1343
1344 /* Boolean values */
1345 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001347 break;
1348 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001350 break;
1351 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001352 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001353 break;
1354 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001355 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001356 break;
1357 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001358 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001359 break;
1360 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001361 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362 break;
1363 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001365 break;
1366 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 break;
1369 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371 break;
1372 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001374 break;
1375 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001376 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001377 break;
1378 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001379 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
1381 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001382 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001385 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001388 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
1390 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001391 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 break;
1393 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001394 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001395 break;
1396 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001397 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001398 break;
1399 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001400 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001401 break;
1402 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001403 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001404 break;
1405 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001406 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001407 /*
1408 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001409 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001410 * local vfs will do advisory
1411 */
Steve French50c2f752007-07-13 00:33:32 +00001412 if (vol->file_mode ==
1413 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001414 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001417 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
1425 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001426 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 break;
1428 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001429 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001439 break;
1440 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
1443 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001444 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001447 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 break;
1452 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001454 break;
1455 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001456 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001457 break;
1458 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001459 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 break;
1461 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001462 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001463 break;
1464 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001466 break;
1467 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001469 break;
1470 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001471 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001472 break;
1473 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001474 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001475 break;
1476 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001477 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001478 * is a per tree connection (mount) not a per socket
1479 * or per-smb connection option in the protocol
1480 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1481 */
Steve French95b1cb92008-05-15 16:44:38 +00001482 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001483 break;
1484 case Opt_direct:
Jeff Layton296838b2012-05-16 07:53:01 -04001485 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001486 vol->direct_io = true;
1487 vol->strict_io = false;
Jeff Layton09983b22012-05-16 07:53:00 -04001488 cERROR(1, "The \"directio\" option will be removed in "
1489 "3.7. Please switch to the \"cache=none\" "
1490 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001491 break;
1492 case Opt_strictcache:
Jeff Layton296838b2012-05-16 07:53:01 -04001493 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001494 vol->direct_io = false;
1495 vol->strict_io = true;
Jeff Layton09983b22012-05-16 07:53:00 -04001496 cERROR(1, "The \"strictcache\" option will be removed "
1497 "in 3.7. Please switch to the \"cache=strict\" "
1498 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001499 break;
1500 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001501 printk(KERN_WARNING "CIFS: Mount option noac not "
1502 "supported. Instead set "
1503 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001504 break;
1505 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301506#ifndef CONFIG_CIFS_FSCACHE
Jeff Layton83fb0862011-06-08 07:35:24 -04001507 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301508 "kernel config option set");
Sean Finneyb9468452011-04-11 13:19:32 +00001509 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301510#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301511 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001512 break;
1513 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001514 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001515 break;
1516 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001517 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001518 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001519 case Opt_sloppy:
1520 sloppy = true;
1521 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001522
1523 /* Numeric Values */
1524 case Opt_backupuid:
1525 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001526 cERROR(1, "%s: Invalid backupuid value",
1527 __func__);
1528 goto cifs_parse_mount_err;
1529 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001530 vol->backupuid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001531 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001532 break;
1533 case Opt_backupgid:
1534 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001535 cERROR(1, "%s: Invalid backupgid value",
1536 __func__);
1537 goto cifs_parse_mount_err;
1538 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001539 vol->backupgid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001540 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001541 break;
1542 case Opt_uid:
1543 if (get_option_ul(args, &option)) {
1544 cERROR(1, "%s: Invalid uid value",
1545 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001546 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001548 vol->linux_uid = option;
1549 uid_specified = true;
1550 break;
1551 case Opt_cruid:
1552 if (get_option_ul(args, &option)) {
1553 cERROR(1, "%s: Invalid cruid value",
1554 __func__);
1555 goto cifs_parse_mount_err;
1556 }
1557 vol->cred_uid = option;
1558 break;
1559 case Opt_gid:
1560 if (get_option_ul(args, &option)) {
1561 cERROR(1, "%s: Invalid gid value",
1562 __func__);
1563 goto cifs_parse_mount_err;
1564 }
1565 vol->linux_gid = option;
1566 gid_specified = true;
1567 break;
1568 case Opt_file_mode:
1569 if (get_option_ul(args, &option)) {
1570 cERROR(1, "%s: Invalid file_mode value",
1571 __func__);
1572 goto cifs_parse_mount_err;
1573 }
1574 vol->file_mode = option;
1575 break;
1576 case Opt_dirmode:
1577 if (get_option_ul(args, &option)) {
1578 cERROR(1, "%s: Invalid dir_mode value",
1579 __func__);
1580 goto cifs_parse_mount_err;
1581 }
1582 vol->dir_mode = option;
1583 break;
1584 case Opt_port:
1585 if (get_option_ul(args, &option)) {
1586 cERROR(1, "%s: Invalid port value",
1587 __func__);
1588 goto cifs_parse_mount_err;
1589 }
1590 vol->port = option;
1591 break;
1592 case Opt_rsize:
1593 if (get_option_ul(args, &option)) {
1594 cERROR(1, "%s: Invalid rsize value",
1595 __func__);
1596 goto cifs_parse_mount_err;
1597 }
1598 vol->rsize = option;
1599 break;
1600 case Opt_wsize:
1601 if (get_option_ul(args, &option)) {
1602 cERROR(1, "%s: Invalid wsize value",
1603 __func__);
1604 goto cifs_parse_mount_err;
1605 }
1606 vol->wsize = option;
1607 break;
1608 case Opt_actimeo:
1609 if (get_option_ul(args, &option)) {
1610 cERROR(1, "%s: Invalid actimeo value",
1611 __func__);
1612 goto cifs_parse_mount_err;
1613 }
1614 vol->actimeo = HZ * option;
1615 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1616 cERROR(1, "CIFS: attribute cache"
1617 "timeout too large");
1618 goto cifs_parse_mount_err;
1619 }
1620 break;
1621
1622 /* String Arguments */
1623
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001624 case Opt_blank_user:
1625 /* null user, ie. anonymous authentication */
1626 vol->nullauth = 1;
1627 vol->username = NULL;
1628 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001629 case Opt_user:
1630 string = match_strdup(args);
1631 if (string == NULL)
1632 goto out_nomem;
1633
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001634 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001635 MAX_USERNAME_SIZE) {
1636 printk(KERN_WARNING "CIFS: username too long\n");
1637 goto cifs_parse_mount_err;
1638 }
1639 vol->username = kstrdup(string, GFP_KERNEL);
1640 if (!vol->username) {
1641 printk(KERN_WARNING "CIFS: no memory "
1642 "for username\n");
1643 goto cifs_parse_mount_err;
1644 }
1645 break;
1646 case Opt_blank_pass:
1647 vol->password = NULL;
1648 break;
1649 case Opt_pass:
1650 /* passwords have to be handled differently
1651 * to allow the character used for deliminator
1652 * to be passed within them
1653 */
1654
1655 /* Obtain the value string */
1656 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001657 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001658
1659 /* Set tmp_end to end of the string */
1660 tmp_end = (char *) value + strlen(value);
1661
1662 /* Check if following character is the deliminator
1663 * If yes, we have encountered a double deliminator
1664 * reset the NULL character to the deliminator
1665 */
1666 if (tmp_end < end && tmp_end[1] == delim)
1667 tmp_end[0] = delim;
1668
1669 /* Keep iterating until we get to a single deliminator
1670 * OR the end
1671 */
1672 while ((tmp_end = strchr(tmp_end, delim)) != NULL &&
1673 (tmp_end[1] == delim)) {
1674 tmp_end = (char *) &tmp_end[2];
1675 }
1676
1677 /* Reset var options to point to next element */
1678 if (tmp_end) {
1679 tmp_end[0] = '\0';
1680 options = (char *) &tmp_end[1];
1681 } else
1682 /* Reached the end of the mount option string */
1683 options = end;
1684
1685 /* Now build new password string */
1686 temp_len = strlen(value);
1687 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1688 if (vol->password == NULL) {
1689 printk(KERN_WARNING "CIFS: no memory "
1690 "for password\n");
1691 goto cifs_parse_mount_err;
1692 }
1693
1694 for (i = 0, j = 0; i < temp_len; i++, j++) {
1695 vol->password[j] = value[i];
1696 if ((value[i] == delim) &&
1697 value[i+1] == delim)
1698 /* skip the second deliminator */
1699 i++;
1700 }
1701 vol->password[j] = '\0';
1702 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001703 case Opt_blank_ip:
1704 vol->UNCip = NULL;
1705 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001706 case Opt_ip:
1707 string = match_strdup(args);
1708 if (string == NULL)
1709 goto out_nomem;
1710
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001711 if (strnlen(string, INET6_ADDRSTRLEN) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001712 INET6_ADDRSTRLEN) {
1713 printk(KERN_WARNING "CIFS: ip address "
1714 "too long\n");
1715 goto cifs_parse_mount_err;
1716 }
1717 vol->UNCip = kstrdup(string, GFP_KERNEL);
1718 if (!vol->UNCip) {
1719 printk(KERN_WARNING "CIFS: no memory "
1720 "for UNC IP\n");
1721 goto cifs_parse_mount_err;
1722 }
1723 break;
1724 case Opt_unc:
1725 string = match_strdup(args);
1726 if (string == NULL)
1727 goto out_nomem;
1728
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001729 temp_len = strnlen(string, 300);
1730 if (temp_len == 300) {
1731 printk(KERN_WARNING "CIFS: UNC name too long\n");
1732 goto cifs_parse_mount_err;
1733 }
1734
Sachin Prabhue4b41fb2012-04-04 01:58:56 +01001735 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1736 if (vol->UNC == NULL) {
1737 printk(KERN_WARNING "CIFS: no memory for UNC\n");
1738 goto cifs_parse_mount_err;
1739 }
1740 strcpy(vol->UNC, string);
1741
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001742 if (strncmp(string, "//", 2) == 0) {
1743 vol->UNC[0] = '\\';
1744 vol->UNC[1] = '\\';
1745 } else if (strncmp(string, "\\\\", 2) != 0) {
1746 printk(KERN_WARNING "CIFS: UNC Path does not "
1747 "begin with // or \\\\\n");
1748 goto cifs_parse_mount_err;
1749 }
1750
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001751 break;
1752 case Opt_domain:
1753 string = match_strdup(args);
1754 if (string == NULL)
1755 goto out_nomem;
1756
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001757 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001758 printk(KERN_WARNING "CIFS: domain name too"
1759 " long\n");
1760 goto cifs_parse_mount_err;
1761 }
1762
1763 vol->domainname = kstrdup(string, GFP_KERNEL);
1764 if (!vol->domainname) {
1765 printk(KERN_WARNING "CIFS: no memory "
1766 "for domainname\n");
1767 goto cifs_parse_mount_err;
1768 }
1769 cFYI(1, "Domain name set");
1770 break;
1771 case Opt_srcaddr:
1772 string = match_strdup(args);
1773 if (string == NULL)
1774 goto out_nomem;
1775
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001776 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001777 (struct sockaddr *)&vol->srcaddr,
1778 string, strlen(string))) {
1779 printk(KERN_WARNING "CIFS: Could not parse"
1780 " srcaddr: %s\n", string);
1781 goto cifs_parse_mount_err;
1782 }
1783 break;
1784 case Opt_prefixpath:
1785 string = match_strdup(args);
1786 if (string == NULL)
1787 goto out_nomem;
1788
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001789 temp_len = strnlen(string, 1024);
1790 if (string[0] != '/')
1791 temp_len++; /* missing leading slash */
1792 if (temp_len > 1024) {
1793 printk(KERN_WARNING "CIFS: prefix too long\n");
1794 goto cifs_parse_mount_err;
1795 }
1796
1797 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1798 if (vol->prepath == NULL) {
1799 printk(KERN_WARNING "CIFS: no memory "
1800 "for path prefix\n");
1801 goto cifs_parse_mount_err;
1802 }
1803
1804 if (string[0] != '/') {
1805 vol->prepath[0] = '/';
1806 strcpy(vol->prepath+1, string);
1807 } else
1808 strcpy(vol->prepath, string);
1809
1810 break;
1811 case Opt_iocharset:
1812 string = match_strdup(args);
1813 if (string == NULL)
1814 goto out_nomem;
1815
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001816 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001817 printk(KERN_WARNING "CIFS: iocharset name "
1818 "too long.\n");
1819 goto cifs_parse_mount_err;
1820 }
1821
1822 if (strnicmp(string, "default", 7) != 0) {
1823 vol->iocharset = kstrdup(string,
1824 GFP_KERNEL);
1825 if (!vol->iocharset) {
1826 printk(KERN_WARNING "CIFS: no memory"
1827 "for charset\n");
1828 goto cifs_parse_mount_err;
1829 }
1830 }
1831 /* if iocharset not set then load_nls_default
1832 * is used by caller
1833 */
1834 cFYI(1, "iocharset set to %s", string);
1835 break;
1836 case Opt_sockopt:
1837 string = match_strdup(args);
1838 if (string == NULL)
1839 goto out_nomem;
1840
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001841 if (strnicmp(string, "TCP_NODELAY", 11) == 0)
1842 vol->sockopt_tcp_nodelay = 1;
1843 break;
1844 case Opt_netbiosname:
1845 string = match_strdup(args);
1846 if (string == NULL)
1847 goto out_nomem;
1848
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001849 memset(vol->source_rfc1001_name, 0x20,
1850 RFC1001_NAME_LEN);
1851 /*
1852 * FIXME: are there cases in which a comma can
1853 * be valid in workstation netbios name (and
1854 * need special handling)?
1855 */
1856 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1857 /* don't ucase netbiosname for user */
1858 if (string[i] == 0)
1859 break;
1860 vol->source_rfc1001_name[i] = string[i];
1861 }
1862 /* The string has 16th byte zero still from
1863 * set at top of the function
1864 */
1865 if (i == RFC1001_NAME_LEN && string[i] != 0)
1866 printk(KERN_WARNING "CIFS: netbiosname"
1867 " longer than 15 truncated.\n");
1868
1869 break;
1870 case Opt_servern:
1871 /* servernetbiosname specified override *SMBSERVER */
1872 string = match_strdup(args);
1873 if (string == NULL)
1874 goto out_nomem;
1875
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001876 /* last byte, type, is 0x20 for servr type */
1877 memset(vol->target_rfc1001_name, 0x20,
1878 RFC1001_NAME_LEN_WITH_NULL);
1879
1880 /* BB are there cases in which a comma can be
1881 valid in this workstation netbios name
1882 (and need special handling)? */
1883
1884 /* user or mount helper must uppercase the
1885 netbios name */
1886 for (i = 0; i < 15; i++) {
1887 if (string[i] == 0)
1888 break;
1889 vol->target_rfc1001_name[i] = string[i];
1890 }
1891 /* The string has 16th byte zero still from
1892 set at top of the function */
1893 if (i == RFC1001_NAME_LEN && string[i] != 0)
1894 printk(KERN_WARNING "CIFS: server net"
1895 "biosname longer than 15 truncated.\n");
1896 break;
1897 case Opt_ver:
1898 string = match_strdup(args);
1899 if (string == NULL)
1900 goto out_nomem;
1901
Jeff Layton5249af32012-05-15 12:04:03 -04001902 if (strnicmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001903 /* This is the default */
1904 break;
1905 }
1906 /* For all other value, error */
1907 printk(KERN_WARNING "CIFS: Invalid version"
1908 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001909 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001910 case Opt_vers:
1911 string = match_strdup(args);
1912 if (string == NULL)
1913 goto out_nomem;
1914
1915 if (cifs_parse_smb_version(string, vol) != 0)
1916 goto cifs_parse_mount_err;
1917 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001918 case Opt_sec:
1919 string = match_strdup(args);
1920 if (string == NULL)
1921 goto out_nomem;
1922
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001923 if (cifs_parse_security_flavors(string, vol) != 0)
1924 goto cifs_parse_mount_err;
1925 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001926 case Opt_cache:
Jeff Layton296838b2012-05-16 07:53:01 -04001927 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001928 string = match_strdup(args);
1929 if (string == NULL)
1930 goto out_nomem;
1931
1932 if (cifs_parse_cache_flavor(string, vol) != 0)
1933 goto cifs_parse_mount_err;
1934 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001935 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001936 /*
1937 * An option we don't recognize. Save it off for later
1938 * if we haven't already found one
1939 */
1940 if (!invalid)
1941 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001942 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001944 /* Free up any allocated string */
1945 kfree(string);
1946 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001948
Jeff Laytond8162552012-03-23 14:40:56 -04001949 if (!sloppy && invalid) {
1950 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1951 goto cifs_parse_mount_err;
1952 }
1953
Jeff Layton8a8798a2012-01-17 16:09:15 -05001954#ifndef CONFIG_KEYS
1955 /* Muliuser mounts require CONFIG_KEYS support */
1956 if (vol->multiuser) {
1957 cERROR(1, "Multiuser mounts require kernels with "
1958 "CONFIG_KEYS enabled.");
Sean Finneyb9468452011-04-11 13:19:32 +00001959 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001960 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001961#endif
Jeff Layton0eb8a132010-10-06 19:51:12 -04001962
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001963 if (vol->UNCip == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 vol->UNCip = &vol->UNC[2];
1965
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001966 if (uid_specified)
1967 vol->override_uid = override_uid;
1968 else if (override_uid == 1)
1969 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1970 "specified with no uid= option.\n");
1971
1972 if (gid_specified)
1973 vol->override_gid = override_gid;
1974 else if (override_gid == 1)
1975 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1976 "specified with no gid= option.\n");
1977
Jeff Layton296838b2012-05-16 07:53:01 -04001978 /* FIXME: remove this block in 3.7 */
1979 if (!cache_specified && !cache_warned) {
1980 cache_warned = true;
1981 printk(KERN_NOTICE "CIFS: no cache= option specified, using "
1982 "\"cache=loose\". This default will change "
1983 "to \"cache=strict\" in 3.7.\n");
1984 }
1985
Sean Finneyb9468452011-04-11 13:19:32 +00001986 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001988
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001989out_nomem:
1990 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001991cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001992 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001993 kfree(mountdata_copy);
1994 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995}
1996
Ben Greear3eb9a882010-09-01 17:06:02 -07001997/** Returns true if srcaddr isn't specified and rhs isn't
1998 * specified, or if srcaddr is specified and
1999 * matches the IP address of the rhs argument.
2000 */
Jeff Layton45151482010-07-06 20:43:02 -04002001static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002002srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2003{
2004 switch (srcaddr->sa_family) {
2005 case AF_UNSPEC:
2006 return (rhs->sa_family == AF_UNSPEC);
2007 case AF_INET: {
2008 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2009 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2010 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2011 }
2012 case AF_INET6: {
2013 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
2014 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
2015 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2016 }
2017 default:
2018 WARN_ON(1);
2019 return false; /* don't expect to be here */
2020 }
2021}
2022
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002023/*
2024 * If no port is specified in addr structure, we try to match with 445 port
2025 * and if it fails - with 139 ports. It should be called only if address
2026 * families of server and addr are equal.
2027 */
2028static bool
2029match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2030{
Steve French6da97912011-03-13 18:55:55 +00002031 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002032
2033 switch (addr->sa_family) {
2034 case AF_INET:
2035 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2036 port = ((struct sockaddr_in *) addr)->sin_port;
2037 break;
2038 case AF_INET6:
2039 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2040 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2041 break;
2042 default:
2043 WARN_ON(1);
2044 return false;
2045 }
2046
2047 if (!port) {
2048 port = htons(CIFS_PORT);
2049 if (port == *sport)
2050 return true;
2051
2052 port = htons(RFC1001_PORT);
2053 }
2054
2055 return port == *sport;
2056}
Ben Greear3eb9a882010-09-01 17:06:02 -07002057
2058static bool
2059match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2060 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061{
Jeff Layton45151482010-07-06 20:43:02 -04002062 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002063 case AF_INET: {
2064 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2065 struct sockaddr_in *srv_addr4 =
2066 (struct sockaddr_in *)&server->dstaddr;
2067
2068 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002069 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002070 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002071 }
2072 case AF_INET6: {
2073 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2074 struct sockaddr_in6 *srv_addr6 =
2075 (struct sockaddr_in6 *)&server->dstaddr;
2076
Jeff Layton45151482010-07-06 20:43:02 -04002077 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002078 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002079 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002080 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002081 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002082 break;
2083 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002084 default:
2085 WARN_ON(1);
2086 return false; /* don't expect to be here */
2087 }
Jeff Layton45151482010-07-06 20:43:02 -04002088
Ben Greear3eb9a882010-09-01 17:06:02 -07002089 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2090 return false;
2091
Jeff Layton45151482010-07-06 20:43:02 -04002092 return true;
2093}
2094
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002095static bool
2096match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2097{
2098 unsigned int secFlags;
2099
2100 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
2101 secFlags = vol->secFlg;
2102 else
2103 secFlags = global_secflags | vol->secFlg;
2104
2105 switch (server->secType) {
2106 case LANMAN:
2107 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
2108 return false;
2109 break;
2110 case NTLMv2:
2111 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
2112 return false;
2113 break;
2114 case NTLM:
2115 if (!(secFlags & CIFSSEC_MAY_NTLM))
2116 return false;
2117 break;
2118 case Kerberos:
2119 if (!(secFlags & CIFSSEC_MAY_KRB5))
2120 return false;
2121 break;
2122 case RawNTLMSSP:
2123 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2124 return false;
2125 break;
2126 default:
2127 /* shouldn't happen */
2128 return false;
2129 }
2130
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002131 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002132 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002133 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002134 return false;
2135 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002136 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002137 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2138 return false;
2139
2140 return true;
2141}
2142
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002143static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
2144 struct smb_vol *vol)
2145{
Jeff Layton23db65f2012-05-15 12:20:51 -04002146 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2147 return 0;
2148
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002149 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2150 return 0;
2151
2152 if (!match_address(server, addr,
2153 (struct sockaddr *)&vol->srcaddr))
2154 return 0;
2155
2156 if (!match_port(server, addr))
2157 return 0;
2158
2159 if (!match_security(server, vol))
2160 return 0;
2161
2162 return 1;
2163}
2164
Jeff Layton45151482010-07-06 20:43:02 -04002165static struct TCP_Server_Info *
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002166cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002167{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002168 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302170 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002171 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002172 if (!match_server(server, addr, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002173 continue;
2174
Jeff Laytone7ddee92008-11-14 13:44:38 -05002175 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302176 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002177 cFYI(1, "Existing tcp session with server found");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002178 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302180 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 return NULL;
2182}
2183
Jeff Layton14fbf502008-11-14 13:53:46 -05002184static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002185cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002187 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302189 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002190 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302191 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002192 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002194
Rob Landleyf1d0c992011-01-22 15:44:05 -06002195 put_net(cifs_net_ns(server));
2196
Jeff Laytone7ddee92008-11-14 13:44:38 -05002197 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302198 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002199
Jeff Laytonc74093b2011-01-11 07:24:23 -05002200 cancel_delayed_work_sync(&server->echo);
2201
Jeff Laytone7ddee92008-11-14 13:44:38 -05002202 spin_lock(&GlobalMid_Lock);
2203 server->tcpStatus = CifsExiting;
2204 spin_unlock(&GlobalMid_Lock);
2205
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002206 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302207 cifs_fscache_release_client_cookie(server);
2208
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002209 kfree(server->session_key.response);
2210 server->session_key.response = NULL;
2211 server->session_key.len = 0;
2212
Jeff Laytone7ddee92008-11-14 13:44:38 -05002213 task = xchg(&server->tsk, NULL);
2214 if (task)
2215 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216}
2217
Jeff Layton63c038c2008-12-01 18:41:46 -05002218static struct TCP_Server_Info *
2219cifs_get_tcp_session(struct smb_vol *volume_info)
2220{
2221 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002222 struct sockaddr_storage addr;
Jeff Layton63c038c2008-12-01 18:41:46 -05002223 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2224 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2225 int rc;
2226
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002227 memset(&addr, 0, sizeof(struct sockaddr_storage));
Jeff Layton63c038c2008-12-01 18:41:46 -05002228
Joe Perchesb6b38f72010-04-21 03:50:45 +00002229 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002230
Jeff Layton63c038c2008-12-01 18:41:46 -05002231 if (volume_info->UNCip && volume_info->UNC) {
Jeff Layton50d97162010-07-06 20:43:01 -04002232 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2233 volume_info->UNCip,
David Howells67b76262010-07-22 18:33:01 +01002234 strlen(volume_info->UNCip),
Jeff Layton50d97162010-07-06 20:43:01 -04002235 volume_info->port);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002236 if (!rc) {
Jeff Layton63c038c2008-12-01 18:41:46 -05002237 /* we failed translating address */
2238 rc = -EINVAL;
2239 goto out_err;
2240 }
Jeff Layton63c038c2008-12-01 18:41:46 -05002241 } else if (volume_info->UNCip) {
2242 /* BB using ip addr as tcp_ses name to connect to the
2243 DFS root below */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002244 cERROR(1, "Connecting to DFS root not implemented yet");
Jeff Layton63c038c2008-12-01 18:41:46 -05002245 rc = -EINVAL;
2246 goto out_err;
2247 } else /* which tcp_sess DFS root would we conect to */ {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002248 cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
2249 "unc=//192.168.1.100/public) specified");
Jeff Layton63c038c2008-12-01 18:41:46 -05002250 rc = -EINVAL;
2251 goto out_err;
2252 }
2253
2254 /* see if we already have a matching tcp_ses */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002255 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002256 if (tcp_ses)
2257 return tcp_ses;
2258
2259 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2260 if (!tcp_ses) {
2261 rc = -ENOMEM;
2262 goto out_err;
2263 }
2264
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002265 rc = cifs_crypto_shash_allocate(tcp_ses);
2266 if (rc) {
2267 cERROR(1, "could not setup hash structures rc %d", rc);
2268 goto out_err;
2269 }
2270
Jeff Layton23db65f2012-05-15 12:20:51 -04002271 tcp_ses->ops = volume_info->ops;
2272 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002273 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002274 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2275 if (IS_ERR(tcp_ses->hostname)) {
2276 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002277 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002278 }
2279
2280 tcp_ses->noblocksnd = volume_info->noblocksnd;
2281 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002282 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002283 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002284 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002285 init_waitqueue_head(&tcp_ses->response_q);
2286 init_waitqueue_head(&tcp_ses->request_q);
2287 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2288 mutex_init(&tcp_ses->srv_mutex);
2289 memcpy(tcp_ses->workstation_RFC1001_name,
2290 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2291 memcpy(tcp_ses->server_RFC1001_name,
2292 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002293 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002294 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002295 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002296 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002297 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2298 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002299 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton63c038c2008-12-01 18:41:46 -05002300
2301 /*
2302 * at this point we are the only ones with the pointer
2303 * to the struct since the kernel thread not created yet
2304 * no need to spinlock this init of tcpStatus or srv_count
2305 */
2306 tcp_ses->tcpStatus = CifsNew;
Ben Greear3eb9a882010-09-01 17:06:02 -07002307 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2308 sizeof(tcp_ses->srcaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002309 ++tcp_ses->srv_count;
2310
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002311 if (addr.ss_family == AF_INET6) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002312 cFYI(1, "attempting ipv6 connect");
Jeff Layton63c038c2008-12-01 18:41:46 -05002313 /* BB should we allow ipv6 on port 139? */
2314 /* other OS never observed in Wild doing 139 with v6 */
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002315 memcpy(&tcp_ses->dstaddr, sin_server6,
2316 sizeof(struct sockaddr_in6));
2317 } else
2318 memcpy(&tcp_ses->dstaddr, sin_server,
2319 sizeof(struct sockaddr_in));
2320
2321 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002322 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002323 cERROR(1, "Error connecting to socket. Aborting operation");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002324 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002325 }
2326
2327 /*
2328 * since we're in a cifs function already, we know that
2329 * this will succeed. No need for try_module_get().
2330 */
2331 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002332 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002333 tcp_ses, "cifsd");
2334 if (IS_ERR(tcp_ses->tsk)) {
2335 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002336 cERROR(1, "error %d create cifsd thread", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002337 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002338 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002339 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002340 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002341
2342 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302343 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002344 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302345 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002346
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302347 cifs_fscache_get_client_cookie(tcp_ses);
2348
Jeff Laytonc74093b2011-01-11 07:24:23 -05002349 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002350 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002351
Jeff Layton63c038c2008-12-01 18:41:46 -05002352 return tcp_ses;
2353
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002354out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002355 cifs_crypto_shash_release(tcp_ses);
2356
Rob Landleyf1d0c992011-01-22 15:44:05 -06002357 put_net(cifs_net_ns(tcp_ses));
2358
Jeff Layton63c038c2008-12-01 18:41:46 -05002359out_err:
2360 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002361 if (!IS_ERR(tcp_ses->hostname))
2362 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002363 if (tcp_ses->ssocket)
2364 sock_release(tcp_ses->ssocket);
2365 kfree(tcp_ses);
2366 }
2367 return ERR_PTR(rc);
2368}
2369
Steve French96daf2b2011-05-27 04:34:02 +00002370static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002371{
2372 switch (ses->server->secType) {
2373 case Kerberos:
2374 if (vol->cred_uid != ses->cred_uid)
2375 return 0;
2376 break;
2377 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002378 /* NULL username means anonymous session */
2379 if (ses->user_name == NULL) {
2380 if (!vol->nullauth)
2381 return 0;
2382 break;
2383 }
2384
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002385 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002386 if (strncmp(ses->user_name,
2387 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002388 MAX_USERNAME_SIZE))
2389 return 0;
2390 if (strlen(vol->username) != 0 &&
2391 ses->password != NULL &&
2392 strncmp(ses->password,
2393 vol->password ? vol->password : "",
2394 MAX_PASSWORD_SIZE))
2395 return 0;
2396 }
2397 return 1;
2398}
2399
Steve French96daf2b2011-05-27 04:34:02 +00002400static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002401cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402{
Steve French96daf2b2011-05-27 04:34:02 +00002403 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302405 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002406 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002407 if (!match_session(ses, vol))
2408 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002409 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302410 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002411 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302413 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 return NULL;
2415}
2416
Jeff Layton14fbf502008-11-14 13:53:46 -05002417static void
Steve French96daf2b2011-05-27 04:34:02 +00002418cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002419{
2420 int xid;
2421 struct TCP_Server_Info *server = ses->server;
2422
Jeff Layton36988c72010-04-24 07:57:43 -04002423 cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302424 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002425 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302426 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002427 return;
2428 }
2429
2430 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302431 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002432
2433 if (ses->status == CifsGood) {
2434 xid = GetXid();
2435 CIFSSMBLogoff(xid, ses);
2436 _FreeXid(xid);
2437 }
2438 sesInfoFree(ses);
2439 cifs_put_tcp_session(server);
2440}
2441
Jeff Layton8a8798a2012-01-17 16:09:15 -05002442#ifdef CONFIG_KEYS
2443
2444/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2445#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2446
2447/* Populate username and pw fields from keyring if possible */
2448static int
2449cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2450{
2451 int rc = 0;
2452 char *desc, *delim, *payload;
2453 ssize_t len;
2454 struct key *key;
2455 struct TCP_Server_Info *server = ses->server;
2456 struct sockaddr_in *sa;
2457 struct sockaddr_in6 *sa6;
2458 struct user_key_payload *upayload;
2459
2460 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2461 if (!desc)
2462 return -ENOMEM;
2463
2464 /* try to find an address key first */
2465 switch (server->dstaddr.ss_family) {
2466 case AF_INET:
2467 sa = (struct sockaddr_in *)&server->dstaddr;
2468 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2469 break;
2470 case AF_INET6:
2471 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2472 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2473 break;
2474 default:
2475 cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
2476 rc = -EINVAL;
2477 goto out_err;
2478 }
2479
2480 cFYI(1, "%s: desc=%s", __func__, desc);
2481 key = request_key(&key_type_logon, desc, "");
2482 if (IS_ERR(key)) {
2483 if (!ses->domainName) {
2484 cFYI(1, "domainName is NULL");
2485 rc = PTR_ERR(key);
2486 goto out_err;
2487 }
2488
2489 /* didn't work, try to find a domain key */
2490 sprintf(desc, "cifs:d:%s", ses->domainName);
2491 cFYI(1, "%s: desc=%s", __func__, desc);
2492 key = request_key(&key_type_logon, desc, "");
2493 if (IS_ERR(key)) {
2494 rc = PTR_ERR(key);
2495 goto out_err;
2496 }
2497 }
2498
2499 down_read(&key->sem);
2500 upayload = key->payload.data;
2501 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002502 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002503 goto out_key_put;
2504 }
2505
2506 /* find first : in payload */
2507 payload = (char *)upayload->data;
2508 delim = strnchr(payload, upayload->datalen, ':');
2509 cFYI(1, "payload=%s", payload);
2510 if (!delim) {
2511 cFYI(1, "Unable to find ':' in payload (datalen=%d)",
2512 upayload->datalen);
2513 rc = -EINVAL;
2514 goto out_key_put;
2515 }
2516
2517 len = delim - payload;
2518 if (len > MAX_USERNAME_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002519 cFYI(1, "Bad value from username search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002520 rc = -EINVAL;
2521 goto out_key_put;
2522 }
2523
2524 vol->username = kstrndup(payload, len, GFP_KERNEL);
2525 if (!vol->username) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002526 cFYI(1, "Unable to allocate %zd bytes for username", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002527 rc = -ENOMEM;
2528 goto out_key_put;
2529 }
2530 cFYI(1, "%s: username=%s", __func__, vol->username);
2531
2532 len = key->datalen - (len + 1);
2533 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002534 cFYI(1, "Bad len for password search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002535 rc = -EINVAL;
2536 kfree(vol->username);
2537 vol->username = NULL;
2538 goto out_key_put;
2539 }
2540
2541 ++delim;
2542 vol->password = kstrndup(delim, len, GFP_KERNEL);
2543 if (!vol->password) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002544 cFYI(1, "Unable to allocate %zd bytes for password", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002545 rc = -ENOMEM;
2546 kfree(vol->username);
2547 vol->username = NULL;
2548 goto out_key_put;
2549 }
2550
2551out_key_put:
2552 up_read(&key->sem);
2553 key_put(key);
2554out_err:
2555 kfree(desc);
2556 cFYI(1, "%s: returning %d", __func__, rc);
2557 return rc;
2558}
2559#else /* ! CONFIG_KEYS */
2560static inline int
2561cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2562 struct cifs_ses *ses __attribute__((unused)))
2563{
2564 return -ENOSYS;
2565}
2566#endif /* CONFIG_KEYS */
2567
Steve Frenchd9b94202011-04-12 01:24:57 +00002568static bool warned_on_ntlm; /* globals init to false automatically */
2569
Steve French96daf2b2011-05-27 04:34:02 +00002570static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002571cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2572{
2573 int rc = -ENOMEM, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002574 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002575 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2576 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002577
2578 xid = GetXid();
2579
Jeff Layton4ff67b72010-07-06 20:43:02 -04002580 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002581 if (ses) {
2582 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
2583
Jeff Layton36988c72010-04-24 07:57:43 -04002584 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002585 rc = cifs_negotiate_protocol(xid, ses);
2586 if (rc) {
2587 mutex_unlock(&ses->session_mutex);
2588 /* problem -- put our ses reference */
2589 cifs_put_smb_ses(ses);
2590 FreeXid(xid);
2591 return ERR_PTR(rc);
2592 }
Jeff Layton36988c72010-04-24 07:57:43 -04002593 if (ses->need_reconnect) {
2594 cFYI(1, "Session needs reconnect");
2595 rc = cifs_setup_session(xid, ses,
2596 volume_info->local_nls);
2597 if (rc) {
2598 mutex_unlock(&ses->session_mutex);
2599 /* problem -- put our reference */
2600 cifs_put_smb_ses(ses);
2601 FreeXid(xid);
2602 return ERR_PTR(rc);
2603 }
2604 }
2605 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002606
2607 /* existing SMB ses has a server reference already */
2608 cifs_put_tcp_session(server);
Jeff Layton36988c72010-04-24 07:57:43 -04002609 FreeXid(xid);
2610 return ses;
2611 }
2612
2613 cFYI(1, "Existing smb sess not found");
2614 ses = sesInfoAlloc();
2615 if (ses == NULL)
2616 goto get_ses_fail;
2617
2618 /* new SMB session uses our server ref */
2619 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002620 if (server->dstaddr.ss_family == AF_INET6)
2621 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002622 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002623 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002624
Steve French8727c8a2011-02-25 01:11:56 -06002625 if (volume_info->username) {
2626 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2627 if (!ses->user_name)
2628 goto get_ses_fail;
2629 }
Jeff Layton36988c72010-04-24 07:57:43 -04002630
2631 /* volume_info->password freed at unmount */
2632 if (volume_info->password) {
2633 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2634 if (!ses->password)
2635 goto get_ses_fail;
2636 }
2637 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002638 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2639 if (!ses->domainName)
2640 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002641 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002642 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002643 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002644
2645 /* ntlmv2 is much stronger than ntlm security, and has been broadly
2646 supported for many years, time to update default security mechanism */
2647 if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
2648 warned_on_ntlm = true;
2649 cERROR(1, "default security mechanism requested. The default "
2650 "security mechanism will be upgraded from ntlm to "
Steve French225de112012-01-03 23:08:24 -06002651 "ntlmv2 in kernel release 3.3");
Steve Frenchd9b94202011-04-12 01:24:57 +00002652 }
Jeff Layton36988c72010-04-24 07:57:43 -04002653 ses->overrideSecFlg = volume_info->secFlg;
2654
2655 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002656 rc = cifs_negotiate_protocol(xid, ses);
2657 if (!rc)
2658 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002659 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002660 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002661 goto get_ses_fail;
2662
2663 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302664 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002665 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302666 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002667
2668 FreeXid(xid);
2669 return ses;
2670
2671get_ses_fail:
2672 sesInfoFree(ses);
2673 FreeXid(xid);
2674 return ERR_PTR(rc);
2675}
2676
Steve French96daf2b2011-05-27 04:34:02 +00002677static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002678{
2679 if (tcon->tidStatus == CifsExiting)
2680 return 0;
2681 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2682 return 0;
2683 return 1;
2684}
2685
Steve French96daf2b2011-05-27 04:34:02 +00002686static struct cifs_tcon *
2687cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688{
2689 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002690 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302692 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002693 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002694 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002695 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002696 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002697 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302698 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 return tcon;
2700 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302701 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return NULL;
2703}
2704
Jeff Laytonf1987b42008-11-15 11:12:47 -05002705static void
Steve French96daf2b2011-05-27 04:34:02 +00002706cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002707{
2708 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002709 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002710
Jeff Laytond00c28d2010-04-24 07:57:44 -04002711 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302712 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002713 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302714 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002715 return;
2716 }
2717
2718 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302719 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002720
2721 xid = GetXid();
2722 CIFSSMBTDis(xid, tcon);
2723 _FreeXid(xid);
2724
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302725 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002726 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002727 cifs_put_smb_ses(ses);
2728}
2729
Steve French96daf2b2011-05-27 04:34:02 +00002730static struct cifs_tcon *
2731cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002732{
2733 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002734 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002735
2736 tcon = cifs_find_tcon(ses, volume_info->UNC);
2737 if (tcon) {
2738 cFYI(1, "Found match on UNC path");
2739 /* existing tcon already has a reference */
2740 cifs_put_smb_ses(ses);
2741 if (tcon->seal != volume_info->seal)
2742 cERROR(1, "transport encryption setting "
2743 "conflicts with existing tid");
2744 return tcon;
2745 }
2746
2747 tcon = tconInfoAlloc();
2748 if (tcon == NULL) {
2749 rc = -ENOMEM;
2750 goto out_fail;
2751 }
2752
2753 tcon->ses = ses;
2754 if (volume_info->password) {
2755 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2756 if (!tcon->password) {
2757 rc = -ENOMEM;
2758 goto out_fail;
2759 }
2760 }
2761
2762 if (strchr(volume_info->UNC + 3, '\\') == NULL
2763 && strchr(volume_info->UNC + 3, '/') == NULL) {
2764 cERROR(1, "Missing share name");
2765 rc = -ENODEV;
2766 goto out_fail;
2767 }
2768
2769 /* BB Do we need to wrap session_mutex around
2770 * this TCon call and Unix SetFS as
2771 * we do on SessSetup and reconnect? */
2772 xid = GetXid();
2773 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
2774 FreeXid(xid);
2775 cFYI(1, "CIFS Tcon rc = %d", rc);
2776 if (rc)
2777 goto out_fail;
2778
2779 if (volume_info->nodfs) {
2780 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2781 cFYI(1, "DFS disabled (%d)", tcon->Flags);
2782 }
2783 tcon->seal = volume_info->seal;
2784 /* we can have only one retry value for a connection
2785 to a share so for resources mounted more than once
2786 to the same server share the last value passed in
2787 for the retry flag is used */
2788 tcon->retry = volume_info->retry;
2789 tcon->nocase = volume_info->nocase;
2790 tcon->local_lease = volume_info->local_lease;
2791
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302792 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002793 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302794 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002795
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302796 cifs_fscache_get_super_cookie(tcon);
2797
Jeff Laytond00c28d2010-04-24 07:57:44 -04002798 return tcon;
2799
2800out_fail:
2801 tconInfoFree(tcon);
2802 return ERR_PTR(rc);
2803}
2804
Jeff Layton9d002df2010-10-06 19:51:11 -04002805void
2806cifs_put_tlink(struct tcon_link *tlink)
2807{
2808 if (!tlink || IS_ERR(tlink))
2809 return;
2810
2811 if (!atomic_dec_and_test(&tlink->tl_count) ||
2812 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2813 tlink->tl_time = jiffies;
2814 return;
2815 }
2816
2817 if (!IS_ERR(tlink_tcon(tlink)))
2818 cifs_put_tcon(tlink_tcon(tlink));
2819 kfree(tlink);
2820 return;
2821}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002822
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002823static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002824cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2825{
2826 return cifs_sb->master_tlink;
2827}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002828
2829static int
2830compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2831{
2832 struct cifs_sb_info *old = CIFS_SB(sb);
2833 struct cifs_sb_info *new = mnt_data->cifs_sb;
2834
2835 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2836 return 0;
2837
2838 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2839 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2840 return 0;
2841
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002842 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002843 * We want to share sb only if we don't specify an r/wsize or
2844 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002845 */
2846 if (new->wsize && new->wsize < old->wsize)
2847 return 0;
2848
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002849 if (new->rsize && new->rsize < old->rsize)
2850 return 0;
2851
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002852 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2853 return 0;
2854
2855 if (old->mnt_file_mode != new->mnt_file_mode ||
2856 old->mnt_dir_mode != new->mnt_dir_mode)
2857 return 0;
2858
2859 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2860 return 0;
2861
2862 if (old->actimeo != new->actimeo)
2863 return 0;
2864
2865 return 1;
2866}
2867
2868int
2869cifs_match_super(struct super_block *sb, void *data)
2870{
2871 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2872 struct smb_vol *volume_info;
2873 struct cifs_sb_info *cifs_sb;
2874 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002875 struct cifs_ses *ses;
2876 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002877 struct tcon_link *tlink;
2878 struct sockaddr_storage addr;
2879 int rc = 0;
2880
2881 memset(&addr, 0, sizeof(struct sockaddr_storage));
2882
2883 spin_lock(&cifs_tcp_ses_lock);
2884 cifs_sb = CIFS_SB(sb);
2885 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2886 if (IS_ERR(tlink)) {
2887 spin_unlock(&cifs_tcp_ses_lock);
2888 return rc;
2889 }
2890 tcon = tlink_tcon(tlink);
2891 ses = tcon->ses;
2892 tcp_srv = ses->server;
2893
2894 volume_info = mnt_data->vol;
2895
2896 if (!volume_info->UNCip || !volume_info->UNC)
2897 goto out;
2898
2899 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2900 volume_info->UNCip,
2901 strlen(volume_info->UNCip),
2902 volume_info->port);
2903 if (!rc)
2904 goto out;
2905
2906 if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
2907 !match_session(ses, volume_info) ||
2908 !match_tcon(tcon, volume_info->UNC)) {
2909 rc = 0;
2910 goto out;
2911 }
2912
2913 rc = compare_mount_options(sb, mnt_data);
2914out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002915 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002916 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002917 return rc;
2918}
2919
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920int
Steve French96daf2b2011-05-27 04:34:02 +00002921get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
Steve French50c2f752007-07-13 00:33:32 +00002922 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
Steve French366781c2008-01-25 10:12:41 +00002923 struct dfs_info3_param **preferrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924{
2925 char *temp_unc;
2926 int rc = 0;
2927
2928 *pnum_referrals = 0;
Steve French366781c2008-01-25 10:12:41 +00002929 *preferrals = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931 if (pSesInfo->ipc_tid == 0) {
2932 temp_unc = kmalloc(2 /* for slashes */ +
Steve French50c2f752007-07-13 00:33:32 +00002933 strnlen(pSesInfo->serverName,
2934 SERVER_NAME_LEN_WITH_NULL * 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 + 1 + 4 /* slash IPC$ */ + 2,
2936 GFP_KERNEL);
2937 if (temp_unc == NULL)
2938 return -ENOMEM;
2939 temp_unc[0] = '\\';
2940 temp_unc[1] = '\\';
2941 strcpy(temp_unc + 2, pSesInfo->serverName);
2942 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
2943 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002944 cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 kfree(temp_unc);
2946 }
2947 if (rc == 0)
Steve Frenchc2cf07d2008-05-15 06:20:02 +00002948 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
Steve French737b7582005-04-28 22:41:06 -07002949 pnum_referrals, nls_codepage, remap);
Steve French366781c2008-01-25 10:12:41 +00002950 /* BB map targetUNCs to dfs_info3 structures, here or
2951 in CIFSGetDFSRefer BB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952
2953 return rc;
2954}
2955
Jeff Layton09e50d52008-07-23 10:11:19 -04002956#ifdef CONFIG_DEBUG_LOCK_ALLOC
2957static struct lock_class_key cifs_key[2];
2958static struct lock_class_key cifs_slock_key[2];
2959
2960static inline void
2961cifs_reclassify_socket4(struct socket *sock)
2962{
2963 struct sock *sk = sock->sk;
2964 BUG_ON(sock_owned_by_user(sk));
2965 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2966 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2967}
2968
2969static inline void
2970cifs_reclassify_socket6(struct socket *sock)
2971{
2972 struct sock *sk = sock->sk;
2973 BUG_ON(sock_owned_by_user(sk));
2974 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2975 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2976}
2977#else
2978static inline void
2979cifs_reclassify_socket4(struct socket *sock)
2980{
2981}
2982
2983static inline void
2984cifs_reclassify_socket6(struct socket *sock)
2985{
2986}
2987#endif
2988
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002990static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991{
Steve French50c2f752007-07-13 00:33:32 +00002992 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993
Steve French50c2f752007-07-13 00:33:32 +00002994 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 /* mask a nibble at a time and encode */
2996 target[j] = 'A' + (0x0F & (source[i] >> 4));
2997 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002998 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 }
3000
3001}
3002
Ben Greear3eb9a882010-09-01 17:06:02 -07003003static int
3004bind_socket(struct TCP_Server_Info *server)
3005{
3006 int rc = 0;
3007 if (server->srcaddr.ss_family != AF_UNSPEC) {
3008 /* Bind to the specified local IP address */
3009 struct socket *socket = server->ssocket;
3010 rc = socket->ops->bind(socket,
3011 (struct sockaddr *) &server->srcaddr,
3012 sizeof(server->srcaddr));
3013 if (rc < 0) {
3014 struct sockaddr_in *saddr4;
3015 struct sockaddr_in6 *saddr6;
3016 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3017 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3018 if (saddr6->sin6_family == AF_INET6)
3019 cERROR(1, "cifs: "
3020 "Failed to bind to: %pI6c, error: %d\n",
3021 &saddr6->sin6_addr, rc);
3022 else
3023 cERROR(1, "cifs: "
3024 "Failed to bind to: %pI4, error: %d\n",
3025 &saddr4->sin_addr.s_addr, rc);
3026 }
3027 }
3028 return rc;
3029}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
3031static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003032ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033{
3034 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003035 /*
3036 * some servers require RFC1001 sessinit before sending
3037 * negprot - BB check reconnection in case where second
3038 * sessinit is sent but no second negprot
3039 */
3040 struct rfc1002_session_packet *ses_init_buf;
3041 struct smb_hdr *smb_buf;
3042 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3043 GFP_KERNEL);
3044 if (ses_init_buf) {
3045 ses_init_buf->trailer.session_req.called_len = 32;
3046
3047 if (server->server_RFC1001_name &&
3048 server->server_RFC1001_name[0] != 0)
3049 rfc1002mangle(ses_init_buf->trailer.
3050 session_req.called_name,
3051 server->server_RFC1001_name,
3052 RFC1001_NAME_LEN_WITH_NULL);
3053 else
3054 rfc1002mangle(ses_init_buf->trailer.
3055 session_req.called_name,
3056 DEFAULT_CIFS_CALLED_NAME,
3057 RFC1001_NAME_LEN_WITH_NULL);
3058
3059 ses_init_buf->trailer.session_req.calling_len = 32;
3060
3061 /*
3062 * calling name ends in null (byte 16) from old smb
3063 * convention.
3064 */
3065 if (server->workstation_RFC1001_name &&
3066 server->workstation_RFC1001_name[0] != 0)
3067 rfc1002mangle(ses_init_buf->trailer.
3068 session_req.calling_name,
3069 server->workstation_RFC1001_name,
3070 RFC1001_NAME_LEN_WITH_NULL);
3071 else
3072 rfc1002mangle(ses_init_buf->trailer.
3073 session_req.calling_name,
3074 "LINUX_CIFS_CLNT",
3075 RFC1001_NAME_LEN_WITH_NULL);
3076
3077 ses_init_buf->trailer.session_req.scope1 = 0;
3078 ses_init_buf->trailer.session_req.scope2 = 0;
3079 smb_buf = (struct smb_hdr *)ses_init_buf;
3080
3081 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003082 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003083 rc = smb_send(server, smb_buf, 0x44);
3084 kfree(ses_init_buf);
3085 /*
3086 * RFC1001 layer in at least one server
3087 * requires very short break before negprot
3088 * presumably because not expecting negprot
3089 * to follow so fast. This is a simple
3090 * solution that works without
3091 * complicating the code and causes no
3092 * significant slowing down on mount
3093 * for everyone else
3094 */
3095 usleep_range(1000, 2000);
3096 }
3097 /*
3098 * else the negprot may still work without this
3099 * even though malloc failed
3100 */
3101
3102 return rc;
3103}
3104
3105static int
3106generic_ip_connect(struct TCP_Server_Info *server)
3107{
3108 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003109 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003110 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003111 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003112 struct sockaddr *saddr;
3113
3114 saddr = (struct sockaddr *) &server->dstaddr;
3115
3116 if (server->dstaddr.ss_family == AF_INET6) {
3117 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3118 slen = sizeof(struct sockaddr_in6);
3119 sfamily = AF_INET6;
3120 } else {
3121 sport = ((struct sockaddr_in *) saddr)->sin_port;
3122 slen = sizeof(struct sockaddr_in);
3123 sfamily = AF_INET;
3124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003126 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003127 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3128 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003130 cERROR(1, "Error %d creating socket", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003131 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003134
3135 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003136 cFYI(1, "Socket created");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003137 server->ssocket = socket;
3138 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003139 if (sfamily == AF_INET6)
3140 cifs_reclassify_socket6(socket);
3141 else
3142 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 }
3144
Ben Greear3eb9a882010-09-01 17:06:02 -07003145 rc = bind_socket(server);
3146 if (rc < 0)
3147 return rc;
3148
Jeff Laytond5c56052008-12-01 18:42:33 -05003149 /*
3150 * Eventually check for other socket options to change from
3151 * the default. sock_setsockopt not used because it expects
3152 * user space buffer
3153 */
3154 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003155 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003156
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003157 /* make the bufsizes depend on wsize/rsize and max requests */
3158 if (server->noautotune) {
3159 if (socket->sk->sk_sndbuf < (200 * 1024))
3160 socket->sk->sk_sndbuf = 200 * 1024;
3161 if (socket->sk->sk_rcvbuf < (140 * 1024))
3162 socket->sk->sk_rcvbuf = 140 * 1024;
3163 }
3164
Steve French6a5fa2362010-01-01 01:28:43 +00003165 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003166 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003167 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3168 (char *)&val, sizeof(val));
3169 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003170 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003171 }
3172
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003173 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
3174 socket->sk->sk_sndbuf,
3175 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3176
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003177 rc = socket->ops->connect(socket, saddr, slen, 0);
3178 if (rc < 0) {
3179 cFYI(1, "Error %d connecting to server", rc);
3180 sock_release(socket);
3181 server->ssocket = NULL;
3182 return rc;
3183 }
3184
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003185 if (sport == htons(RFC1001_PORT))
3186 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003187
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188 return rc;
3189}
3190
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003191static int
3192ip_connect(struct TCP_Server_Info *server)
3193{
Steve French6da97912011-03-13 18:55:55 +00003194 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003195 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3196 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3197
3198 if (server->dstaddr.ss_family == AF_INET6)
3199 sport = &addr6->sin6_port;
3200 else
3201 sport = &addr->sin_port;
3202
3203 if (*sport == 0) {
3204 int rc;
3205
3206 /* try with 445 port at first */
3207 *sport = htons(CIFS_PORT);
3208
3209 rc = generic_ip_connect(server);
3210 if (rc >= 0)
3211 return rc;
3212
3213 /* if it failed, try with 139 port */
3214 *sport = htons(RFC1001_PORT);
3215 }
3216
3217 return generic_ip_connect(server);
3218}
3219
Steve French96daf2b2011-05-27 04:34:02 +00003220void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003221 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003222{
3223 /* if we are reconnecting then should we check to see if
3224 * any requested capabilities changed locally e.g. via
3225 * remount but we can not do much about it here
3226 * if they have (even if we could detect it by the following)
3227 * Perhaps we could add a backpointer to array of sb from tcon
3228 * or if we change to make all sb to same share the same
3229 * sb as NFS - then we only have one backpointer to sb.
3230 * What if we wanted to mount the server share twice once with
3231 * and once without posixacls or posix paths? */
3232 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003233
Steve Frenchc18c8422007-07-18 23:21:09 +00003234 if (vol_info && vol_info->no_linux_ext) {
3235 tcon->fsUnixInfo.Capability = 0;
3236 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003237 cFYI(1, "Linux protocol extensions disabled");
Steve Frenchc18c8422007-07-18 23:21:09 +00003238 return;
3239 } else if (vol_info)
3240 tcon->unix_ext = 1; /* Unix Extensions supported */
3241
3242 if (tcon->unix_ext == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003243 cFYI(1, "Unix extensions disabled so not set on reconnect");
Steve Frenchc18c8422007-07-18 23:21:09 +00003244 return;
3245 }
Steve French50c2f752007-07-13 00:33:32 +00003246
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003247 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003248 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French6848b732011-05-26 18:38:54 +00003249 cFYI(1, "unix caps which server supports %lld", cap);
Steve French8af18972007-02-14 04:42:51 +00003250 /* check for reconnect case in which we do not
3251 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003252 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003253 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003254 originally at mount time */
3255 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3256 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003257 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3258 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003259 cERROR(1, "POSIXPATH support change");
Steve French8af18972007-02-14 04:42:51 +00003260 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003261 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003262 cERROR(1, "possible reconnect error");
3263 cERROR(1, "server disabled POSIX path support");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003264 }
Steve French8af18972007-02-14 04:42:51 +00003265 }
Steve French50c2f752007-07-13 00:33:32 +00003266
Steve French6848b732011-05-26 18:38:54 +00003267 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3268 cERROR(1, "per-share encryption not supported yet");
3269
Steve French8af18972007-02-14 04:42:51 +00003270 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003271 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003272 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003273 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003274 cFYI(1, "negotiated posix acl support");
Al Viro2c6292a2011-06-17 09:05:48 -04003275 if (cifs_sb)
3276 cifs_sb->mnt_cifs_flags |=
3277 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003278 }
3279
Steve French75865f8c2007-06-24 18:30:48 +00003280 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003281 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003282 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003283 cFYI(1, "negotiate posix pathnames");
Al Viro2c6292a2011-06-17 09:05:48 -04003284 if (cifs_sb)
3285 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003286 CIFS_MOUNT_POSIX_PATHS;
3287 }
Steve French50c2f752007-07-13 00:33:32 +00003288
Joe Perchesb6b38f72010-04-21 03:50:45 +00003289 cFYI(1, "Negotiate caps 0x%x", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003290#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003291 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003292 cFYI(1, "FCNTL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003293 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003294 cFYI(1, "EXTATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003295 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003296 cFYI(1, "POSIX path cap");
Steve French75865f8c2007-06-24 18:30:48 +00003297 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003298 cFYI(1, "XATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003299 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003300 cFYI(1, "POSIX ACL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003301 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003302 cFYI(1, "very large read cap");
Steve French75865f8c2007-06-24 18:30:48 +00003303 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003304 cFYI(1, "very large write cap");
Steve French6848b732011-05-26 18:38:54 +00003305 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3306 cFYI(1, "transport encryption cap");
3307 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3308 cFYI(1, "mandatory transport encryption cap");
Steve French8af18972007-02-14 04:42:51 +00003309#endif /* CIFS_DEBUG2 */
3310 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003311 if (vol_info == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003312 cFYI(1, "resetting capabilities failed");
Steve French442aa312007-09-24 20:25:46 +00003313 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003314 cERROR(1, "Negotiating Unix capabilities "
Steve French5a44b312007-09-20 15:16:24 +00003315 "with the server failed. Consider "
3316 "mounting with the Unix Extensions\n"
3317 "disabled, if problems are found, "
3318 "by specifying the nounix mount "
Joe Perchesb6b38f72010-04-21 03:50:45 +00003319 "option.");
Steve French5a44b312007-09-20 15:16:24 +00003320
Steve French8af18972007-02-14 04:42:51 +00003321 }
3322 }
3323}
3324
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003325void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3326 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003327{
Jeff Layton2de970f2010-10-06 19:51:12 -04003328 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3329
Al Viro2ced6f62011-06-17 09:20:04 -04003330 spin_lock_init(&cifs_sb->tlink_tree_lock);
3331 cifs_sb->tlink_tree = RB_ROOT;
3332
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003333 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003334 * Temporarily set r/wsize for matching superblock. If we end up using
3335 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003336 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003337 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003338 cifs_sb->wsize = pvolume_info->wsize;
3339
Steve French3b795212008-11-13 19:45:32 +00003340 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3341 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3342 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3343 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Al Viro5206efd2011-07-26 03:22:14 -04003344 cFYI(1, "file mode: 0x%hx dir mode: 0x%hx",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003345 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003346
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303347 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003348 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303349
Steve French3b795212008-11-13 19:45:32 +00003350 if (pvolume_info->noperm)
3351 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3352 if (pvolume_info->setuids)
3353 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3354 if (pvolume_info->server_ino)
3355 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3356 if (pvolume_info->remap)
3357 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3358 if (pvolume_info->no_xattr)
3359 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3360 if (pvolume_info->sfu_emul)
3361 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3362 if (pvolume_info->nobrl)
3363 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003364 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003365 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003366 if (pvolume_info->mand_lock)
3367 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003368 if (pvolume_info->rwpidforward)
3369 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003370 if (pvolume_info->cifs_acl)
3371 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003372 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003373 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003374 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3375 }
3376 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003377 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003378 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3379 }
Steve French3b795212008-11-13 19:45:32 +00003380 if (pvolume_info->override_uid)
3381 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3382 if (pvolume_info->override_gid)
3383 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3384 if (pvolume_info->dynperm)
3385 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303386 if (pvolume_info->fsc)
3387 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003388 if (pvolume_info->multiuser)
3389 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3390 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003391 if (pvolume_info->strict_io)
3392 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003393 if (pvolume_info->direct_io) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003394 cFYI(1, "mounting share using direct i/o");
Steve French3b795212008-11-13 19:45:32 +00003395 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3396 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003397 if (pvolume_info->mfsymlinks) {
3398 if (pvolume_info->sfu_emul) {
3399 cERROR(1, "mount option mfsymlinks ignored if sfu "
3400 "mount option is used");
3401 } else {
3402 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3403 }
3404 }
Steve French3b795212008-11-13 19:45:32 +00003405
3406 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesb6b38f72010-04-21 03:50:45 +00003407 cERROR(1, "mount option dynperm ignored if cifsacl "
3408 "mount option supported");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003409}
3410
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003411/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003412 * When the server supports very large reads and writes via POSIX extensions,
3413 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
3414 * including the RFC1001 length.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003415 *
3416 * Note that this might make for "interesting" allocation problems during
Jeff Layton1190f6a2011-06-22 17:33:57 -04003417 * writeback however as we have to allocate an array of pointers for the
3418 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003419 *
3420 * For reads, there is a similar problem as we need to allocate an array
3421 * of kvecs to handle the receive, though that should only need to be done
3422 * once.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003423 */
Jeff Layton1190f6a2011-06-22 17:33:57 -04003424#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003425#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003426
3427/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003428 * When the server doesn't allow large posix writes, only allow a rsize/wsize
3429 * of 2^17-1 minus the size of the call header. That allows for a read or
3430 * write up to the maximum size described by RFC1002.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003431 */
Pavel Shilovsky94443f42011-10-07 18:57:45 +04003432#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003433#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003434
3435/*
3436 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
3437 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
3438 * a single wsize request with a single call.
3439 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003440#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
3441
3442/*
Jeff Laytonce91acb2012-01-17 16:08:51 -05003443 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
3444 * those values when posix extensions aren't in force. In actuality here, we
3445 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
3446 * to be ok with the extra byte even though Windows doesn't send writes that
3447 * are that large.
3448 *
3449 * Citation:
3450 *
3451 * 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 -04003452 */
3453#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
Jeff Laytonce91acb2012-01-17 16:08:51 -05003454#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003455
3456static unsigned int
Steve French96daf2b2011-05-27 04:34:02 +00003457cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003458{
3459 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3460 struct TCP_Server_Info *server = tcon->ses->server;
Jeff Laytonce91acb2012-01-17 16:08:51 -05003461 unsigned int wsize;
3462
3463 /* start with specified wsize, or default */
3464 if (pvolume_info->wsize)
3465 wsize = pvolume_info->wsize;
3466 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3467 wsize = CIFS_DEFAULT_IOSIZE;
3468 else
3469 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003470
3471 /* can server support 24-bit write sizes? (via UNIX extensions) */
3472 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
Jeff Layton1190f6a2011-06-22 17:33:57 -04003473 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003474
Jeff Layton1190f6a2011-06-22 17:33:57 -04003475 /*
3476 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
3477 * Limit it to max buffer offered by the server, minus the size of the
3478 * WRITEX header, not including the 4 byte RFC1001 length.
3479 */
3480 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
3481 (!(server->capabilities & CAP_UNIX) &&
3482 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
3483 wsize = min_t(unsigned int, wsize,
3484 server->maxBuf - sizeof(WRITE_REQ) + 4);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003485
3486 /* hard limit of CIFS_MAX_WSIZE */
3487 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3488
3489 return wsize;
3490}
3491
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003492static unsigned int
3493cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3494{
3495 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3496 struct TCP_Server_Info *server = tcon->ses->server;
3497 unsigned int rsize, defsize;
3498
3499 /*
3500 * Set default value...
3501 *
3502 * HACK alert! Ancient servers have very small buffers. Even though
3503 * MS-CIFS indicates that servers are only limited by the client's
3504 * bufsize for reads, testing against win98se shows that it throws
3505 * INVALID_PARAMETER errors if you try to request too large a read.
3506 *
3507 * If the server advertises a MaxBufferSize of less than one page,
3508 * assume that it also can't satisfy reads larger than that either.
3509 *
3510 * FIXME: Is there a better heuristic for this?
3511 */
3512 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
3513 defsize = CIFS_DEFAULT_IOSIZE;
3514 else if (server->capabilities & CAP_LARGE_READ_X)
3515 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
3516 else if (server->maxBuf >= PAGE_CACHE_SIZE)
3517 defsize = CIFSMaxBufSize;
3518 else
3519 defsize = server->maxBuf - sizeof(READ_RSP);
3520
3521 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
3522
3523 /*
3524 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
3525 * the client's MaxBufferSize.
3526 */
3527 if (!(server->capabilities & CAP_LARGE_READ_X))
3528 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3529
3530 /* hard limit of CIFS_MAX_RSIZE */
3531 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3532
3533 return rsize;
3534}
3535
Igor Mammedove4cce942009-02-10 14:10:26 +03003536static int
Steve French96daf2b2011-05-27 04:34:02 +00003537is_path_accessible(int xid, struct cifs_tcon *tcon,
Igor Mammedove4cce942009-02-10 14:10:26 +03003538 struct cifs_sb_info *cifs_sb, const char *full_path)
3539{
3540 int rc;
Igor Mammedove4cce942009-02-10 14:10:26 +03003541 FILE_ALL_INFO *pfile_info;
3542
Igor Mammedove4cce942009-02-10 14:10:26 +03003543 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
3544 if (pfile_info == NULL)
3545 return -ENOMEM;
3546
3547 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
3548 0 /* not legacy */, cifs_sb->local_nls,
3549 cifs_sb->mnt_cifs_flags &
3550 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton221d1d72011-05-17 06:40:30 -04003551
3552 if (rc == -EOPNOTSUPP || rc == -EINVAL)
3553 rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
3554 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
3555 CIFS_MOUNT_MAP_SPECIAL_CHR);
Igor Mammedove4cce942009-02-10 14:10:26 +03003556 kfree(pfile_info);
3557 return rc;
3558}
3559
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003560static void
3561cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003562{
Sean Finneyb9468452011-04-11 13:19:32 +00003563 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003564 kzfree(volume_info->password);
Steve French13589c42011-08-18 04:41:55 +00003565 if (volume_info->UNCip != volume_info->UNC + 2)
3566 kfree(volume_info->UNCip);
Jesper Juhl95c75452011-08-27 18:58:34 +02003567 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003568 kfree(volume_info->domainname);
3569 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003570 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003571}
3572
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003573void
3574cifs_cleanup_volume_info(struct smb_vol *volume_info)
3575{
3576 if (!volume_info)
3577 return;
3578 cleanup_volume_info_contents(volume_info);
3579 kfree(volume_info);
3580}
3581
3582
Steve French2d6d5892009-04-09 00:36:44 +00003583#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003584/* build_path_to_root returns full path to root when
3585 * we do not have an exiting connection (tcon) */
3586static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003587build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003588 const struct cifs_sb_info *cifs_sb)
3589{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003590 char *full_path, *pos;
3591 unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
3592 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003593
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003594 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003595 if (full_path == NULL)
3596 return ERR_PTR(-ENOMEM);
3597
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003598 strncpy(full_path, vol->UNC, unc_len);
3599 pos = full_path + unc_len;
3600
3601 if (pplen) {
3602 strncpy(pos, vol->prepath, pplen);
3603 pos += pplen;
3604 }
3605
3606 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003607 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003608 cFYI(1, "%s: full_path=%s", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003609 return full_path;
3610}
Sean Finneydd613942011-04-11 13:19:30 +00003611
3612/*
3613 * Perform a dfs referral query for a share and (optionally) prefix
3614 *
Sean Finney046462a2011-04-11 13:19:33 +00003615 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3616 * to a string containing updated options for the submount. Otherwise it
3617 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003618 *
3619 * Returns the rc from get_dfs_path to the caller, which can be used to
3620 * determine whether there were referrals.
3621 */
3622static int
Steve French96daf2b2011-05-27 04:34:02 +00003623expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
Sean Finneydd613942011-04-11 13:19:30 +00003624 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003625 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003626{
3627 int rc;
3628 unsigned int num_referrals = 0;
3629 struct dfs_info3_param *referrals = NULL;
3630 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3631
3632 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3633 if (IS_ERR(full_path))
3634 return PTR_ERR(full_path);
3635
3636 /* For DFS paths, skip the first '\' of the UNC */
3637 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3638
3639 rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
3640 &num_referrals, &referrals,
3641 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3642
3643 if (!rc && num_referrals > 0) {
3644 char *fake_devname = NULL;
3645
3646 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3647 full_path + 1, referrals,
3648 &fake_devname);
3649
3650 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003651
Sean Finneydd613942011-04-11 13:19:30 +00003652 if (IS_ERR(mdata)) {
3653 rc = PTR_ERR(mdata);
3654 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003655 } else {
3656 cleanup_volume_info_contents(volume_info);
3657 memset(volume_info, '\0', sizeof(*volume_info));
3658 rc = cifs_setup_volume_info(volume_info, mdata,
3659 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003660 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003661 kfree(fake_devname);
3662 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003663 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003664 }
3665 kfree(full_path);
3666 return rc;
3667}
Steve French2d6d5892009-04-09 00:36:44 +00003668#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003669
Jeff Layton04db79b2011-07-06 08:10:38 -04003670static int
3671cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3672 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003674 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003675
Jeff Layton04db79b2011-07-06 08:10:38 -04003676 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3677 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
Jeff Layton23db65f2012-05-15 12:20:51 -04003679
Jeff Layton7586b762008-12-01 18:41:49 -05003680 if (volume_info->nullauth) {
Jeff Layton04febab2012-01-17 16:09:15 -05003681 cFYI(1, "Anonymous login");
3682 kfree(volume_info->username);
3683 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003684 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 /* BB fixme parse for domain name here */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003686 cFYI(1, "Username: %s", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 } else {
Steve Frenchbf820672005-12-01 22:32:42 -08003688 cifserror("No username specified");
Steve French50c2f752007-07-13 00:33:32 +00003689 /* In userspace mount helper we can get user name from alternate
3690 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003691 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 }
3693
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003695 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003696 /* load_nls_default cannot return null */
3697 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003699 volume_info->local_nls = load_nls(volume_info->iocharset);
3700 if (volume_info->local_nls == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003701 cERROR(1, "CIFS mount error: iocharset %s not found",
3702 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003703 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 }
3705 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003706
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003707 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003708}
3709
3710struct smb_vol *
3711cifs_get_volume_info(char *mount_data, const char *devname)
3712{
3713 int rc;
3714 struct smb_vol *volume_info;
3715
3716 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
3717 if (!volume_info)
3718 return ERR_PTR(-ENOMEM);
3719
3720 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3721 if (rc) {
3722 cifs_cleanup_volume_info(volume_info);
3723 volume_info = ERR_PTR(rc);
3724 }
3725
3726 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003727}
3728
3729int
Al Viro2c6292a2011-06-17 09:05:48 -04003730cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003731{
Jeff Layton1daaae82012-03-21 06:30:40 -04003732 int rc;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003733 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003734 struct cifs_ses *pSesInfo;
3735 struct cifs_tcon *tcon;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003736 struct TCP_Server_Info *srvTcp;
3737 char *full_path;
3738 struct tcon_link *tlink;
3739#ifdef CONFIG_CIFS_DFS_UPCALL
3740 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003741#endif
Al Virodd854462011-06-17 08:24:42 -04003742
3743 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3744 if (rc)
3745 return rc;
3746
Jeff Layton20547492011-07-09 12:21:07 -04003747#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003748try_mount_again:
3749 /* cleanup activities if we're chasing a referral */
3750 if (referral_walks_count) {
3751 if (tcon)
3752 cifs_put_tcon(tcon);
3753 else if (pSesInfo)
3754 cifs_put_smb_ses(pSesInfo);
3755
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003756 FreeXid(xid);
3757 }
3758#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003759 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003760 tcon = NULL;
3761 pSesInfo = NULL;
3762 srvTcp = NULL;
3763 full_path = NULL;
3764 tlink = NULL;
3765
3766 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767
Jeff Layton63c038c2008-12-01 18:41:46 -05003768 /* get a reference to a tcp session */
Jeff Layton7586b762008-12-01 18:41:49 -05003769 srvTcp = cifs_get_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05003770 if (IS_ERR(srvTcp)) {
3771 rc = PTR_ERR(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003772 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003773 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 }
3775
Jeff Layton36988c72010-04-24 07:57:43 -04003776 /* get a reference to a SMB session */
3777 pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
3778 if (IS_ERR(pSesInfo)) {
3779 rc = PTR_ERR(pSesInfo);
3780 pSesInfo = NULL;
3781 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 }
Steve French50c2f752007-07-13 00:33:32 +00003783
Jeff Laytond00c28d2010-04-24 07:57:44 -04003784 /* search for existing tcon to this server share */
3785 tcon = cifs_get_tcon(pSesInfo, volume_info);
3786 if (IS_ERR(tcon)) {
3787 rc = PTR_ERR(tcon);
3788 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003789 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003790 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003791
Steve French6848b732011-05-26 18:38:54 +00003792 /* tell server which Unix caps we support */
3793 if (tcon->ses->capabilities & CAP_UNIX) {
3794 /* reset of caps checks mount to see if unix extensions
3795 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003796 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003797 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3798 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3799 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3800 rc = -EACCES;
3801 goto mount_fail_check;
3802 }
3803 } else
3804 tcon->unix_ext = 0; /* server does not support them */
3805
Steve Frenchd82c2df2008-11-15 00:07:26 +00003806 /* do not care if following two calls succeed - informational */
3807 if (!tcon->ipc) {
3808 CIFSSMBQFSDeviceInfo(xid, tcon);
3809 CIFSSMBQFSAttributeInfo(xid, tcon);
3810 }
3811
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003812 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003813 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003814
Jeff Layton66bfaad2011-10-19 15:30:35 -04003815 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003816 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003817
Igor Mammedove4cce942009-02-10 14:10:26 +03003818remote_path_check:
3819#ifdef CONFIG_CIFS_DFS_UPCALL
3820 /*
3821 * Perform an unconditional check for whether there are DFS
3822 * referrals for this path without prefix, to provide support
3823 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003824 * with PATH_NOT_COVERED to requests that include the prefix.
3825 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003826 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003827 if (referral_walks_count == 0) {
3828 int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
3829 cifs_sb, false);
3830 if (!refrc) {
3831 referral_walks_count++;
3832 goto try_mount_again;
3833 }
3834 }
3835#endif
3836
Steve Frenchf87d39d2011-05-27 03:50:55 +00003837 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 if (!rc && tcon) {
3839 /* build_path_to_root works only when we have a valid tcon */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003840 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Steve French7c7b25b2006-06-01 19:20:10 +00003841 if (full_path == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842 rc = -ENOMEM;
3843 goto mount_fail_check;
3844 }
3845 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
3846 if (rc != 0 && rc != -EREMOTE) {
3847 kfree(full_path);
3848 goto mount_fail_check;
3849 }
3850 kfree(full_path);
3851 }
3852
3853 /* get referral if needed */
3854 if (rc == -EREMOTE) {
3855#ifdef CONFIG_CIFS_DFS_UPCALL
3856 if (referral_walks_count > MAX_NESTED_LINKS) {
3857 /*
Steve Frencheeac8042006-01-13 21:34:58 -08003858 * BB: when we implement proper loop detection,
Steve French4523cc32007-04-30 20:13:06 +00003859 * we will remove this check. But now we need it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 * to prevent an indefinite loop if 'DFS tree' is
3861 * misconfigured (i.e. has loops).
3862 */
3863 rc = -ELOOP;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003864 goto mount_fail_check;
3865 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003866
Sean Finneydd613942011-04-11 13:19:30 +00003867 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003868 true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003869
Sean Finneydd613942011-04-11 13:19:30 +00003870 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003871 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003872 goto try_mount_again;
3873 }
Sean Finneydd613942011-04-11 13:19:30 +00003874 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003875#else /* No DFS support, return error on mount */
3876 rc = -EOPNOTSUPP;
3877#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003878 }
3879
Jeff Layton9d002df2010-10-06 19:51:11 -04003880 if (rc)
3881 goto mount_fail_check;
3882
3883 /* now, hang the tcon off of the superblock */
3884 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3885 if (tlink == NULL) {
3886 rc = -ENOMEM;
3887 goto mount_fail_check;
3888 }
3889
Jeff Laytonb647c352010-10-28 11:16:44 -04003890 tlink->tl_uid = pSesInfo->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003891 tlink->tl_tcon = tcon;
3892 tlink->tl_time = jiffies;
3893 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3894 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3895
Jeff Layton413e6612010-10-28 13:33:38 -04003896 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003897 spin_lock(&cifs_sb->tlink_tree_lock);
3898 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3899 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003900
Jeff Laytonda472fc2012-03-23 14:40:53 -04003901 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003902 TLINK_IDLE_EXPIRE);
3903
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003904mount_fail_check:
3905 /* on error free sesinfo and tcon struct if needed */
3906 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003907 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003908 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003909 if (tcon)
3910 cifs_put_tcon(tcon);
3911 else if (pSesInfo)
3912 cifs_put_smb_ses(pSesInfo);
3913 else
3914 cifs_put_tcp_session(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003915 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003916 }
3917
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 FreeXid(xid);
3920 return rc;
3921}
3922
Jeff Layton8d1bca32011-06-11 21:17:10 -04003923/*
3924 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3925 * pointer may be NULL.
3926 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927int
Steve French96daf2b2011-05-27 04:34:02 +00003928CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3929 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 const struct nls_table *nls_codepage)
3931{
3932 struct smb_hdr *smb_buffer;
3933 struct smb_hdr *smb_buffer_response;
3934 TCONX_REQ *pSMB;
3935 TCONX_RSP *pSMBr;
3936 unsigned char *bcc_ptr;
3937 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003938 int length;
3939 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
3941 if (ses == NULL)
3942 return -EIO;
3943
3944 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003945 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003947
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 smb_buffer_response = smb_buffer;
3949
3950 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3951 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003952
3953 smb_buffer->Mid = GetNextMid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 smb_buffer->Uid = ses->Suid;
3955 pSMB = (TCONX_REQ *) smb_buffer;
3956 pSMBr = (TCONX_RSP *) smb_buffer_response;
3957
3958 pSMB->AndXCommand = 0xFF;
3959 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003961 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003962 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003963 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003964 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003965 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003966 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003967 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003968 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3969 specified as required (when that support is added to
3970 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003971 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003972 by Samba (not sure whether other servers allow
3973 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003974#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003975 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003976 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003977 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003978 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003979 SECMODE_PW_ENCRYPT ? true : false,
3980 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003981 else
3982#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003983 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003984 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003985
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003986 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003987 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003988 /* must align unicode strings */
3989 *bcc_ptr = 0; /* null byte password */
3990 bcc_ptr++;
3991 }
Steve Frencheeac8042006-01-13 21:34:58 -08003992 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Steve French96daf2b2011-05-27 04:34:02 +00003994 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003995 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3997
3998 if (ses->capabilities & CAP_STATUS32) {
3999 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4000 }
4001 if (ses->capabilities & CAP_DFS) {
4002 smb_buffer->Flags2 |= SMBFLG2_DFS;
4003 }
4004 if (ses->capabilities & CAP_UNICODE) {
4005 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4006 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004007 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004008 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004009 (/* server len*/ + 256 /* share len */), nls_codepage);
4010 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 bcc_ptr += 2; /* skip trailing null */
4012 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 strcpy(bcc_ptr, tree);
4014 bcc_ptr += strlen(tree) + 1;
4015 }
4016 strcpy(bcc_ptr, "?????");
4017 bcc_ptr += strlen("?????");
4018 bcc_ptr += 1;
4019 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004020 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4021 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 pSMB->ByteCount = cpu_to_le16(count);
4023
Steve French133672e2007-11-13 22:41:37 +00004024 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004025 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 /* above now done in SendReceive */
4028 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004029 bool is_unicode;
4030
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004032 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 tcon->tid = smb_buffer_response->Tid;
4034 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004035 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004036 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004037 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4038 is_unicode = true;
4039 else
4040 is_unicode = false;
4041
Jeff Laytoncc20c032009-04-30 07:16:21 -04004042
Steve French50c2f752007-07-13 00:33:32 +00004043 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004044 if (length == 3) {
4045 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4046 (bcc_ptr[2] == 'C')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004047 cFYI(1, "IPC connection");
Steve French7f8ed422007-09-28 22:28:55 +00004048 tcon->ipc = 1;
4049 }
4050 } else if (length == 2) {
4051 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4052 /* the most common case */
Joe Perchesb6b38f72010-04-21 03:50:45 +00004053 cFYI(1, "disk share connection");
Steve French7f8ed422007-09-28 22:28:55 +00004054 }
4055 }
Steve French50c2f752007-07-13 00:33:32 +00004056 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004057 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004059
4060 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004061 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004062 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004063 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004064 nls_codepage);
4065
Joe Perchesb6b38f72010-04-21 03:50:45 +00004066 cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004067
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004068 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004069 (smb_buffer_response->WordCount == 7))
4070 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004071 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4072 else
4073 tcon->Flags = 0;
Joe Perchesb6b38f72010-04-21 03:50:45 +00004074 cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004076 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 ses->ipc_tid = smb_buffer_response->Tid;
4078 }
4079
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004080 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 return rc;
4082}
4083
Al Viro2a9b9952011-06-17 09:27:16 -04004084void
4085cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086{
Jeff Laytonb647c352010-10-28 11:16:44 -04004087 struct rb_root *root = &cifs_sb->tlink_tree;
4088 struct rb_node *node;
4089 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
Jeff Layton2de970f2010-10-06 19:51:12 -04004091 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4092
Jeff Laytonb647c352010-10-28 11:16:44 -04004093 spin_lock(&cifs_sb->tlink_tree_lock);
4094 while ((node = rb_first(root))) {
4095 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4096 cifs_get_tlink(tlink);
4097 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4098 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004099
Jeff Laytonb647c352010-10-28 11:16:44 -04004100 spin_unlock(&cifs_sb->tlink_tree_lock);
4101 cifs_put_tlink(tlink);
4102 spin_lock(&cifs_sb->tlink_tree_lock);
4103 }
4104 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004105
Al Virodd854462011-06-17 08:24:42 -04004106 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004107 kfree(cifs_sb->mountdata);
4108 unload_nls(cifs_sb->local_nls);
4109 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00004110}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111
Steve French96daf2b2011-05-27 04:34:02 +00004112int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113{
4114 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004115 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116
Jeff Layton198b5682010-04-24 07:57:48 -04004117 /* only send once per connect */
4118 if (server->maxBuf != 0)
4119 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004121 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004122 rc = CIFSSMBNegotiate(xid, ses);
4123 if (rc == -EAGAIN) {
4124 /* retry only once on 1st time connection */
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004125 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004126 rc = CIFSSMBNegotiate(xid, ses);
4127 if (rc == -EAGAIN)
4128 rc = -EHOSTDOWN;
4129 }
4130 if (rc == 0) {
4131 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004132 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004133 server->tcpStatus = CifsGood;
4134 else
4135 rc = -EHOSTDOWN;
4136 spin_unlock(&GlobalMid_Lock);
4137
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 }
Steve French26b994f2008-08-06 05:11:33 +00004139
Jeff Layton198b5682010-04-24 07:57:48 -04004140 return rc;
4141}
Steve French26b994f2008-08-06 05:11:33 +00004142
Jeff Layton198b5682010-04-24 07:57:48 -04004143
Steve French96daf2b2011-05-27 04:34:02 +00004144int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
Jeff Layton198b5682010-04-24 07:57:48 -04004145 struct nls_table *nls_info)
4146{
4147 int rc = 0;
4148 struct TCP_Server_Info *server = ses->server;
4149
4150 ses->flags = 0;
4151 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004152 if (linuxExtEnabled == 0)
Jeff Layton198b5682010-04-24 07:57:48 -04004153 ses->capabilities &= (~CAP_UNIX);
Steve French20418ac2009-04-30 16:13:32 +00004154
Joe Perchesb6b38f72010-04-21 03:50:45 +00004155 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
Steve French96daf2b2011-05-27 04:34:02 +00004156 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004157
Jeff Layton198b5682010-04-24 07:57:48 -04004158 rc = CIFS_SessSetup(xid, ses, nls_info);
Steve French26b994f2008-08-06 05:11:33 +00004159 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004160 cERROR(1, "Send error in SessSetup = %d", rc);
Steve French26b994f2008-08-06 05:11:33 +00004161 } else {
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004162 mutex_lock(&ses->server->srv_mutex);
4163 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004164 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004165 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004166 server->sequence_number = 0x2;
4167 server->session_estab = true;
4168 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004169 }
4170 mutex_unlock(&server->srv_mutex);
4171
Joe Perchesb6b38f72010-04-21 03:50:45 +00004172 cFYI(1, "CIFS Session Established successfully");
Steve French20418ac2009-04-30 16:13:32 +00004173 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04004174 ses->status = CifsGood;
4175 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00004176 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00004177 }
4178
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004179 kfree(ses->auth_key.response);
4180 ses->auth_key.response = NULL;
4181 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05004182 kfree(ses->ntlmssp);
4183 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004184
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 return rc;
4186}
4187
Jeff Layton8a8798a2012-01-17 16:09:15 -05004188static int
4189cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4190{
4191 switch (ses->server->secType) {
4192 case Kerberos:
4193 vol->secFlg = CIFSSEC_MUST_KRB5;
4194 return 0;
4195 case NTLMv2:
4196 vol->secFlg = CIFSSEC_MUST_NTLMV2;
4197 break;
4198 case NTLM:
4199 vol->secFlg = CIFSSEC_MUST_NTLM;
4200 break;
4201 case RawNTLMSSP:
4202 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
4203 break;
4204 case LANMAN:
4205 vol->secFlg = CIFSSEC_MUST_LANMAN;
4206 break;
4207 }
4208
4209 return cifs_set_cifscreds(vol, ses);
4210}
4211
Steve French96daf2b2011-05-27 04:34:02 +00004212static struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004213cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
4214{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004215 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004216 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4217 struct cifs_ses *ses;
4218 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004219 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004220
4221 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004222 if (vol_info == NULL)
4223 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004224
Jeff Layton9d002df2010-10-06 19:51:11 -04004225 vol_info->local_nls = cifs_sb->local_nls;
4226 vol_info->linux_uid = fsuid;
4227 vol_info->cred_uid = fsuid;
4228 vol_info->UNC = master_tcon->treeName;
4229 vol_info->retry = master_tcon->retry;
4230 vol_info->nocase = master_tcon->nocase;
4231 vol_info->local_lease = master_tcon->local_lease;
4232 vol_info->no_linux_ext = !master_tcon->unix_ext;
4233
Jeff Layton8a8798a2012-01-17 16:09:15 -05004234 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4235 if (rc) {
4236 tcon = ERR_PTR(rc);
4237 goto out;
4238 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004239
4240 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304241 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004242 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304243 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004244
4245 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4246 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004247 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004248 cifs_put_tcp_session(master_tcon->ses->server);
4249 goto out;
4250 }
4251
4252 tcon = cifs_get_tcon(ses, vol_info);
4253 if (IS_ERR(tcon)) {
4254 cifs_put_smb_ses(ses);
4255 goto out;
4256 }
4257
4258 if (ses->capabilities & CAP_UNIX)
4259 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4260out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004261 kfree(vol_info->username);
4262 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004263 kfree(vol_info);
4264
4265 return tcon;
4266}
4267
Steve French96daf2b2011-05-27 04:34:02 +00004268struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004269cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4270{
4271 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4272}
4273
4274static int
4275cifs_sb_tcon_pending_wait(void *unused)
4276{
4277 schedule();
4278 return signal_pending(current) ? -ERESTARTSYS : 0;
4279}
4280
Jeff Laytonb647c352010-10-28 11:16:44 -04004281/* find and return a tlink with given uid */
4282static struct tcon_link *
4283tlink_rb_search(struct rb_root *root, uid_t uid)
4284{
4285 struct rb_node *node = root->rb_node;
4286 struct tcon_link *tlink;
4287
4288 while (node) {
4289 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4290
4291 if (tlink->tl_uid > uid)
4292 node = node->rb_left;
4293 else if (tlink->tl_uid < uid)
4294 node = node->rb_right;
4295 else
4296 return tlink;
4297 }
4298 return NULL;
4299}
4300
4301/* insert a tcon_link into the tree */
4302static void
4303tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4304{
4305 struct rb_node **new = &(root->rb_node), *parent = NULL;
4306 struct tcon_link *tlink;
4307
4308 while (*new) {
4309 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4310 parent = *new;
4311
4312 if (tlink->tl_uid > new_tlink->tl_uid)
4313 new = &((*new)->rb_left);
4314 else
4315 new = &((*new)->rb_right);
4316 }
4317
4318 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4319 rb_insert_color(&new_tlink->tl_rbnode, root);
4320}
4321
Jeff Layton9d002df2010-10-06 19:51:11 -04004322/*
4323 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4324 * current task.
4325 *
4326 * If the superblock doesn't refer to a multiuser mount, then just return
4327 * the master tcon for the mount.
4328 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304329 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004330 * exists, then check to see if it's pending construction. If it is then wait
4331 * for construction to complete. Once it's no longer pending, check to see if
4332 * it failed and either return an error or retry construction, depending on
4333 * the timeout.
4334 *
4335 * If one doesn't exist then insert a new tcon_link struct into the tree and
4336 * try to construct a new one.
4337 */
4338struct tcon_link *
4339cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4340{
4341 int ret;
Jeff Laytonb647c352010-10-28 11:16:44 -04004342 uid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004343 struct tcon_link *tlink, *newtlink;
4344
4345 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4346 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4347
4348 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004349 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004350 if (tlink)
4351 cifs_get_tlink(tlink);
4352 spin_unlock(&cifs_sb->tlink_tree_lock);
4353
4354 if (tlink == NULL) {
4355 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4356 if (newtlink == NULL)
4357 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004358 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004359 newtlink->tl_tcon = ERR_PTR(-EACCES);
4360 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4361 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4362 cifs_get_tlink(newtlink);
4363
Jeff Layton9d002df2010-10-06 19:51:11 -04004364 spin_lock(&cifs_sb->tlink_tree_lock);
4365 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004366 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004367 if (tlink) {
4368 cifs_get_tlink(tlink);
4369 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004370 kfree(newtlink);
4371 goto wait_for_construction;
4372 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004373 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004374 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4375 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004376 } else {
4377wait_for_construction:
4378 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4379 cifs_sb_tcon_pending_wait,
4380 TASK_INTERRUPTIBLE);
4381 if (ret) {
4382 cifs_put_tlink(tlink);
4383 return ERR_PTR(ret);
4384 }
4385
4386 /* if it's good, return it */
4387 if (!IS_ERR(tlink->tl_tcon))
4388 return tlink;
4389
4390 /* return error if we tried this already recently */
4391 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4392 cifs_put_tlink(tlink);
4393 return ERR_PTR(-EACCES);
4394 }
4395
4396 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4397 goto wait_for_construction;
4398 }
4399
4400 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4401 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4402 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4403
4404 if (IS_ERR(tlink->tl_tcon)) {
4405 cifs_put_tlink(tlink);
4406 return ERR_PTR(-EACCES);
4407 }
4408
4409 return tlink;
4410}
Jeff Layton2de970f2010-10-06 19:51:12 -04004411
4412/*
4413 * periodic workqueue job that scans tcon_tree for a superblock and closes
4414 * out tcons.
4415 */
4416static void
4417cifs_prune_tlinks(struct work_struct *work)
4418{
4419 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4420 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004421 struct rb_root *root = &cifs_sb->tlink_tree;
4422 struct rb_node *node = rb_first(root);
4423 struct rb_node *tmp;
4424 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004425
Jeff Laytonb647c352010-10-28 11:16:44 -04004426 /*
4427 * Because we drop the spinlock in the loop in order to put the tlink
4428 * it's not guarded against removal of links from the tree. The only
4429 * places that remove entries from the tree are this function and
4430 * umounts. Because this function is non-reentrant and is canceled
4431 * before umount can proceed, this is safe.
4432 */
4433 spin_lock(&cifs_sb->tlink_tree_lock);
4434 node = rb_first(root);
4435 while (node != NULL) {
4436 tmp = node;
4437 node = rb_next(tmp);
4438 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4439
4440 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4441 atomic_read(&tlink->tl_count) != 0 ||
4442 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4443 continue;
4444
4445 cifs_get_tlink(tlink);
4446 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4447 rb_erase(tmp, root);
4448
Jeff Layton2de970f2010-10-06 19:51:12 -04004449 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004450 cifs_put_tlink(tlink);
4451 spin_lock(&cifs_sb->tlink_tree_lock);
4452 }
4453 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004454
Jeff Laytonda472fc2012-03-23 14:40:53 -04004455 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004456 TLINK_IDLE_EXPIRE);
4457}