blob: 5ac20fc2c31268722457c96491705b423d996996 [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 Shilovskyd4e48542012-03-23 14:28:02 -0400571 memset(server->bigbuf, 0, header_size());
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 Shilovskyd4e48542012-03-23 14:28:02 -0400585 memset(server->smallbuf, 0, header_size());
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 Shilovskyd4e48542012-03-23 14:28:02 -0400956 if (pdu_length > CIFSMaxBufSize + max_header_size() - 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 Shilovskyd4e48542012-03-23 14:28:02 -0400972 length = cifs_read_from_socket(server, buf + header_size() - 1,
973 pdu_length - header_size() + 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 Shilovskyd4e48542012-03-23 14:28:02 -04001047 if (pdu_length < header_size() - 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 Shilovskyd4e48542012-03-23 14:28:02 -04001057 header_size() - 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 Shilovskyd4e48542012-03-23 14:28:02 -04001082 cifs_dump_mem("Received Data is: ", buf, header_size());
Steve French39798772006-05-31 22:40:51 +00001083#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001084 cifs_dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +00001085 cifs_dump_mids(server);
1086#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +00001087
Steve Frenche4eb2952005-04-28 22:41:09 -07001088 }
1089 } /* end while !EXITING */
1090
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001091 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001092 cifs_buf_release(server->bigbuf);
1093 if (server->smallbuf) /* no sense logging a debug message if NULL */
1094 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001096 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001097 clean_demultiplex_info(server);
Steve French50c2f752007-07-13 00:33:32 +00001098
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001099 /* if server->tsk was NULL then wait for a signal before exiting */
1100 if (!task_to_wake) {
1101 set_current_state(TASK_INTERRUPTIBLE);
1102 while (!signal_pending(current)) {
1103 schedule();
1104 set_current_state(TASK_INTERRUPTIBLE);
1105 }
1106 set_current_state(TASK_RUNNING);
1107 }
1108
Jeff Layton0468a2c2008-12-01 07:09:35 -05001109 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110}
1111
Jeff Laytonc359cf32007-11-16 22:22:06 +00001112/* extract the host portion of the UNC string */
1113static char *
1114extract_hostname(const char *unc)
1115{
1116 const char *src;
1117 char *dst, *delim;
1118 unsigned int len;
1119
1120 /* skip double chars at beginning of string */
1121 /* BB: check validity of these bytes? */
1122 src = unc + 2;
1123
1124 /* delimiter between hostname and sharename is always '\\' now */
1125 delim = strchr(src, '\\');
1126 if (!delim)
1127 return ERR_PTR(-EINVAL);
1128
1129 len = delim - src;
1130 dst = kmalloc((len + 1), GFP_KERNEL);
1131 if (dst == NULL)
1132 return ERR_PTR(-ENOMEM);
1133
1134 memcpy(dst, src, len);
1135 dst[len] = '\0';
1136
1137 return dst;
1138}
1139
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001140static int get_option_ul(substring_t args[], unsigned long *option)
1141{
1142 int rc;
1143 char *string;
1144
1145 string = match_strdup(args);
1146 if (string == NULL)
1147 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001148 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001149 kfree(string);
1150
1151 return rc;
1152}
1153
1154
1155static int cifs_parse_security_flavors(char *value,
1156 struct smb_vol *vol)
1157{
1158
1159 substring_t args[MAX_OPT_ARGS];
1160
1161 switch (match_token(value, cifs_secflavor_tokens, args)) {
1162 case Opt_sec_krb5:
1163 vol->secFlg |= CIFSSEC_MAY_KRB5;
1164 break;
1165 case Opt_sec_krb5i:
1166 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
1167 break;
1168 case Opt_sec_krb5p:
1169 /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
1170 cERROR(1, "Krb5 cifs privacy not supported");
1171 break;
1172 case Opt_sec_ntlmssp:
1173 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1174 break;
1175 case Opt_sec_ntlmsspi:
1176 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
1177 break;
1178 case Opt_ntlm:
1179 /* ntlm is default so can be turned off too */
1180 vol->secFlg |= CIFSSEC_MAY_NTLM;
1181 break;
1182 case Opt_sec_ntlmi:
1183 vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
1184 break;
1185 case Opt_sec_nontlm:
1186 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1187 break;
1188 case Opt_sec_ntlmv2i:
1189 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
1190 break;
1191#ifdef CONFIG_CIFS_WEAK_PW_HASH
1192 case Opt_sec_lanman:
1193 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1194 break;
1195#endif
1196 case Opt_sec_none:
1197 vol->nullauth = 1;
1198 break;
1199 default:
1200 cERROR(1, "bad security option: %s", value);
1201 return 1;
1202 }
1203
1204 return 0;
1205}
1206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001208cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1209{
1210 substring_t args[MAX_OPT_ARGS];
1211
1212 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1213 case Opt_cache_loose:
1214 vol->direct_io = false;
1215 vol->strict_io = false;
1216 break;
1217 case Opt_cache_strict:
1218 vol->direct_io = false;
1219 vol->strict_io = true;
1220 break;
1221 case Opt_cache_none:
1222 vol->direct_io = true;
1223 vol->strict_io = false;
1224 break;
1225 default:
1226 cERROR(1, "bad cache= option: %s", value);
1227 return 1;
1228 }
1229 return 0;
1230}
1231
1232static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001233cifs_parse_smb_version(char *value, struct smb_vol *vol)
1234{
1235 substring_t args[MAX_OPT_ARGS];
1236
1237 switch (match_token(value, cifs_smb_version_tokens, args)) {
1238 case Smb_1:
1239 vol->ops = &smb1_operations;
1240 vol->vals = &smb1_values;
1241 break;
1242 default:
1243 cERROR(1, "Unknown vers= option specified: %s", value);
1244 return 1;
1245 }
1246 return 0;
1247}
1248
1249static int
Sean Finneyb9468452011-04-11 13:19:32 +00001250cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001251 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001253 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001254 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 unsigned int temp_len, i, j;
1256 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001257 short int override_uid = -1;
1258 short int override_gid = -1;
1259 bool uid_specified = false;
1260 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001261 bool sloppy = false;
1262 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001263 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001264 char *string = NULL;
1265 char *tmp_end, *value;
1266 char delim;
Jeff Layton296838b2012-05-16 07:53:01 -04001267 bool cache_specified = false;
1268 static bool cache_warned = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
1270 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001271 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001272 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Jeff Layton88463992010-11-22 15:31:03 -05001274 /*
1275 * does not have to be perfect mapping since field is
1276 * informational, only used for servers that do not support
1277 * port 445 and it can be overridden at mount time
1278 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001279 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1280 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001281 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1282
Jeff Layton1397f2e2011-01-07 11:30:28 -05001283 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001284 /* null target name indicates to use *SMBSERVR default called name
1285 if we end up sending RFC1001 session initialize */
1286 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001287 vol->cred_uid = current_uid();
1288 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001289 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001290
1291 /* default to only allowing write access to owner of the mount */
1292 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001295 /* default is always to request posix paths. */
1296 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001297 /* default to using server inode numbers where available */
1298 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001299
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301300 vol->actimeo = CIFS_DEF_ACTIMEO;
1301
Jeff Layton23db65f2012-05-15 12:20:51 -04001302 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1303 vol->ops = &smb1_operations;
1304 vol->vals = &smb1_values;
1305
Sean Finneyb9468452011-04-11 13:19:32 +00001306 if (!mountdata)
1307 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Sean Finneyb9468452011-04-11 13:19:32 +00001309 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1310 if (!mountdata_copy)
1311 goto cifs_parse_mount_err;
1312
1313 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001314 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001315
Steve French50c2f752007-07-13 00:33:32 +00001316 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001317 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 separator[0] = options[4];
1319 options += 5;
1320 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001321 cFYI(1, "Null separator not allowed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 }
1323 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001324 vol->backupuid_specified = false; /* no backup intent for a user */
1325 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001326
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001328 substring_t args[MAX_OPT_ARGS];
1329 unsigned long option;
1330 int token;
1331
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 if (!*data)
1333 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001335 token = match_token(data, cifs_mount_option_tokens, args);
1336
1337 switch (token) {
1338
1339 /* Ingnore the following */
1340 case Opt_ignore:
1341 break;
1342
1343 /* Boolean values */
1344 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001346 break;
1347 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001349 break;
1350 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001351 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001352 break;
1353 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001354 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001355 break;
1356 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001357 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001358 break;
1359 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001360 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001361 break;
1362 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001364 break;
1365 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001367 break;
1368 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001370 break;
1371 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001373 break;
1374 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001375 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001376 break;
1377 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001378 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001379 break;
1380 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001381 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001382 break;
1383 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001384 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001385 break;
1386 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001387 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001388 break;
1389 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001390 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001391 break;
1392 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001393 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001394 break;
1395 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001396 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001397 break;
1398 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001399 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001400 break;
1401 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001402 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001403 break;
1404 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001405 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001406 /*
1407 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001408 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001409 * local vfs will do advisory
1410 */
Steve French50c2f752007-07-13 00:33:32 +00001411 if (vol->file_mode ==
1412 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001413 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001414 break;
1415 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001416 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001417 break;
1418 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001420 break;
1421 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001423 break;
1424 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001425 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001426 break;
1427 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001428 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001429 break;
1430 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001432 break;
1433 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001435 break;
1436 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001438 break;
1439 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001441 break;
1442 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001443 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001444 break;
1445 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001446 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001447 break;
1448 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001450 break;
1451 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001453 break;
1454 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001455 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001456 break;
1457 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001458 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001459 break;
1460 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001461 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001462 break;
1463 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001465 break;
1466 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001468 break;
1469 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001470 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001471 break;
1472 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001473 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001474 break;
1475 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001476 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001477 * is a per tree connection (mount) not a per socket
1478 * or per-smb connection option in the protocol
1479 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1480 */
Steve French95b1cb92008-05-15 16:44:38 +00001481 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001482 break;
1483 case Opt_direct:
Jeff Layton296838b2012-05-16 07:53:01 -04001484 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001485 vol->direct_io = true;
1486 vol->strict_io = false;
Jeff Layton09983b22012-05-16 07:53:00 -04001487 cERROR(1, "The \"directio\" option will be removed in "
1488 "3.7. Please switch to the \"cache=none\" "
1489 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001490 break;
1491 case Opt_strictcache:
Jeff Layton296838b2012-05-16 07:53:01 -04001492 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001493 vol->direct_io = false;
1494 vol->strict_io = true;
Jeff Layton09983b22012-05-16 07:53:00 -04001495 cERROR(1, "The \"strictcache\" option will be removed "
1496 "in 3.7. Please switch to the \"cache=strict\" "
1497 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001498 break;
1499 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001500 printk(KERN_WARNING "CIFS: Mount option noac not "
1501 "supported. Instead set "
1502 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001503 break;
1504 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301505#ifndef CONFIG_CIFS_FSCACHE
Jeff Layton83fb0862011-06-08 07:35:24 -04001506 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301507 "kernel config option set");
Sean Finneyb9468452011-04-11 13:19:32 +00001508 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301509#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301510 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001511 break;
1512 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001513 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001514 break;
1515 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001516 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001517 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001518 case Opt_sloppy:
1519 sloppy = true;
1520 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001521
1522 /* Numeric Values */
1523 case Opt_backupuid:
1524 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001525 cERROR(1, "%s: Invalid backupuid value",
1526 __func__);
1527 goto cifs_parse_mount_err;
1528 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001529 vol->backupuid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001530 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001531 break;
1532 case Opt_backupgid:
1533 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001534 cERROR(1, "%s: Invalid backupgid value",
1535 __func__);
1536 goto cifs_parse_mount_err;
1537 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001538 vol->backupgid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001539 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001540 break;
1541 case Opt_uid:
1542 if (get_option_ul(args, &option)) {
1543 cERROR(1, "%s: Invalid uid value",
1544 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001545 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001547 vol->linux_uid = option;
1548 uid_specified = true;
1549 break;
1550 case Opt_cruid:
1551 if (get_option_ul(args, &option)) {
1552 cERROR(1, "%s: Invalid cruid value",
1553 __func__);
1554 goto cifs_parse_mount_err;
1555 }
1556 vol->cred_uid = option;
1557 break;
1558 case Opt_gid:
1559 if (get_option_ul(args, &option)) {
1560 cERROR(1, "%s: Invalid gid value",
1561 __func__);
1562 goto cifs_parse_mount_err;
1563 }
1564 vol->linux_gid = option;
1565 gid_specified = true;
1566 break;
1567 case Opt_file_mode:
1568 if (get_option_ul(args, &option)) {
1569 cERROR(1, "%s: Invalid file_mode value",
1570 __func__);
1571 goto cifs_parse_mount_err;
1572 }
1573 vol->file_mode = option;
1574 break;
1575 case Opt_dirmode:
1576 if (get_option_ul(args, &option)) {
1577 cERROR(1, "%s: Invalid dir_mode value",
1578 __func__);
1579 goto cifs_parse_mount_err;
1580 }
1581 vol->dir_mode = option;
1582 break;
1583 case Opt_port:
1584 if (get_option_ul(args, &option)) {
1585 cERROR(1, "%s: Invalid port value",
1586 __func__);
1587 goto cifs_parse_mount_err;
1588 }
1589 vol->port = option;
1590 break;
1591 case Opt_rsize:
1592 if (get_option_ul(args, &option)) {
1593 cERROR(1, "%s: Invalid rsize value",
1594 __func__);
1595 goto cifs_parse_mount_err;
1596 }
1597 vol->rsize = option;
1598 break;
1599 case Opt_wsize:
1600 if (get_option_ul(args, &option)) {
1601 cERROR(1, "%s: Invalid wsize value",
1602 __func__);
1603 goto cifs_parse_mount_err;
1604 }
1605 vol->wsize = option;
1606 break;
1607 case Opt_actimeo:
1608 if (get_option_ul(args, &option)) {
1609 cERROR(1, "%s: Invalid actimeo value",
1610 __func__);
1611 goto cifs_parse_mount_err;
1612 }
1613 vol->actimeo = HZ * option;
1614 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1615 cERROR(1, "CIFS: attribute cache"
1616 "timeout too large");
1617 goto cifs_parse_mount_err;
1618 }
1619 break;
1620
1621 /* String Arguments */
1622
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001623 case Opt_blank_user:
1624 /* null user, ie. anonymous authentication */
1625 vol->nullauth = 1;
1626 vol->username = NULL;
1627 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001628 case Opt_user:
1629 string = match_strdup(args);
1630 if (string == NULL)
1631 goto out_nomem;
1632
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001633 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001634 MAX_USERNAME_SIZE) {
1635 printk(KERN_WARNING "CIFS: username too long\n");
1636 goto cifs_parse_mount_err;
1637 }
1638 vol->username = kstrdup(string, GFP_KERNEL);
1639 if (!vol->username) {
1640 printk(KERN_WARNING "CIFS: no memory "
1641 "for username\n");
1642 goto cifs_parse_mount_err;
1643 }
1644 break;
1645 case Opt_blank_pass:
1646 vol->password = NULL;
1647 break;
1648 case Opt_pass:
1649 /* passwords have to be handled differently
1650 * to allow the character used for deliminator
1651 * to be passed within them
1652 */
1653
1654 /* Obtain the value string */
1655 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001656 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001657
1658 /* Set tmp_end to end of the string */
1659 tmp_end = (char *) value + strlen(value);
1660
1661 /* Check if following character is the deliminator
1662 * If yes, we have encountered a double deliminator
1663 * reset the NULL character to the deliminator
1664 */
1665 if (tmp_end < end && tmp_end[1] == delim)
1666 tmp_end[0] = delim;
1667
1668 /* Keep iterating until we get to a single deliminator
1669 * OR the end
1670 */
1671 while ((tmp_end = strchr(tmp_end, delim)) != NULL &&
1672 (tmp_end[1] == delim)) {
1673 tmp_end = (char *) &tmp_end[2];
1674 }
1675
1676 /* Reset var options to point to next element */
1677 if (tmp_end) {
1678 tmp_end[0] = '\0';
1679 options = (char *) &tmp_end[1];
1680 } else
1681 /* Reached the end of the mount option string */
1682 options = end;
1683
1684 /* Now build new password string */
1685 temp_len = strlen(value);
1686 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1687 if (vol->password == NULL) {
1688 printk(KERN_WARNING "CIFS: no memory "
1689 "for password\n");
1690 goto cifs_parse_mount_err;
1691 }
1692
1693 for (i = 0, j = 0; i < temp_len; i++, j++) {
1694 vol->password[j] = value[i];
1695 if ((value[i] == delim) &&
1696 value[i+1] == delim)
1697 /* skip the second deliminator */
1698 i++;
1699 }
1700 vol->password[j] = '\0';
1701 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001702 case Opt_blank_ip:
1703 vol->UNCip = NULL;
1704 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001705 case Opt_ip:
1706 string = match_strdup(args);
1707 if (string == NULL)
1708 goto out_nomem;
1709
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001710 if (strnlen(string, INET6_ADDRSTRLEN) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001711 INET6_ADDRSTRLEN) {
1712 printk(KERN_WARNING "CIFS: ip address "
1713 "too long\n");
1714 goto cifs_parse_mount_err;
1715 }
1716 vol->UNCip = kstrdup(string, GFP_KERNEL);
1717 if (!vol->UNCip) {
1718 printk(KERN_WARNING "CIFS: no memory "
1719 "for UNC IP\n");
1720 goto cifs_parse_mount_err;
1721 }
1722 break;
1723 case Opt_unc:
1724 string = match_strdup(args);
1725 if (string == NULL)
1726 goto out_nomem;
1727
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001728 temp_len = strnlen(string, 300);
1729 if (temp_len == 300) {
1730 printk(KERN_WARNING "CIFS: UNC name too long\n");
1731 goto cifs_parse_mount_err;
1732 }
1733
Sachin Prabhue4b41fb2012-04-04 01:58:56 +01001734 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1735 if (vol->UNC == NULL) {
1736 printk(KERN_WARNING "CIFS: no memory for UNC\n");
1737 goto cifs_parse_mount_err;
1738 }
1739 strcpy(vol->UNC, string);
1740
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001741 if (strncmp(string, "//", 2) == 0) {
1742 vol->UNC[0] = '\\';
1743 vol->UNC[1] = '\\';
1744 } else if (strncmp(string, "\\\\", 2) != 0) {
1745 printk(KERN_WARNING "CIFS: UNC Path does not "
1746 "begin with // or \\\\\n");
1747 goto cifs_parse_mount_err;
1748 }
1749
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001750 break;
1751 case Opt_domain:
1752 string = match_strdup(args);
1753 if (string == NULL)
1754 goto out_nomem;
1755
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001756 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001757 printk(KERN_WARNING "CIFS: domain name too"
1758 " long\n");
1759 goto cifs_parse_mount_err;
1760 }
1761
1762 vol->domainname = kstrdup(string, GFP_KERNEL);
1763 if (!vol->domainname) {
1764 printk(KERN_WARNING "CIFS: no memory "
1765 "for domainname\n");
1766 goto cifs_parse_mount_err;
1767 }
1768 cFYI(1, "Domain name set");
1769 break;
1770 case Opt_srcaddr:
1771 string = match_strdup(args);
1772 if (string == NULL)
1773 goto out_nomem;
1774
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001775 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 (struct sockaddr *)&vol->srcaddr,
1777 string, strlen(string))) {
1778 printk(KERN_WARNING "CIFS: Could not parse"
1779 " srcaddr: %s\n", string);
1780 goto cifs_parse_mount_err;
1781 }
1782 break;
1783 case Opt_prefixpath:
1784 string = match_strdup(args);
1785 if (string == NULL)
1786 goto out_nomem;
1787
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001788 temp_len = strnlen(string, 1024);
1789 if (string[0] != '/')
1790 temp_len++; /* missing leading slash */
1791 if (temp_len > 1024) {
1792 printk(KERN_WARNING "CIFS: prefix too long\n");
1793 goto cifs_parse_mount_err;
1794 }
1795
1796 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1797 if (vol->prepath == NULL) {
1798 printk(KERN_WARNING "CIFS: no memory "
1799 "for path prefix\n");
1800 goto cifs_parse_mount_err;
1801 }
1802
1803 if (string[0] != '/') {
1804 vol->prepath[0] = '/';
1805 strcpy(vol->prepath+1, string);
1806 } else
1807 strcpy(vol->prepath, string);
1808
1809 break;
1810 case Opt_iocharset:
1811 string = match_strdup(args);
1812 if (string == NULL)
1813 goto out_nomem;
1814
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001815 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 printk(KERN_WARNING "CIFS: iocharset name "
1817 "too long.\n");
1818 goto cifs_parse_mount_err;
1819 }
1820
1821 if (strnicmp(string, "default", 7) != 0) {
1822 vol->iocharset = kstrdup(string,
1823 GFP_KERNEL);
1824 if (!vol->iocharset) {
1825 printk(KERN_WARNING "CIFS: no memory"
1826 "for charset\n");
1827 goto cifs_parse_mount_err;
1828 }
1829 }
1830 /* if iocharset not set then load_nls_default
1831 * is used by caller
1832 */
1833 cFYI(1, "iocharset set to %s", string);
1834 break;
1835 case Opt_sockopt:
1836 string = match_strdup(args);
1837 if (string == NULL)
1838 goto out_nomem;
1839
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001840 if (strnicmp(string, "TCP_NODELAY", 11) == 0)
1841 vol->sockopt_tcp_nodelay = 1;
1842 break;
1843 case Opt_netbiosname:
1844 string = match_strdup(args);
1845 if (string == NULL)
1846 goto out_nomem;
1847
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001848 memset(vol->source_rfc1001_name, 0x20,
1849 RFC1001_NAME_LEN);
1850 /*
1851 * FIXME: are there cases in which a comma can
1852 * be valid in workstation netbios name (and
1853 * need special handling)?
1854 */
1855 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1856 /* don't ucase netbiosname for user */
1857 if (string[i] == 0)
1858 break;
1859 vol->source_rfc1001_name[i] = string[i];
1860 }
1861 /* The string has 16th byte zero still from
1862 * set at top of the function
1863 */
1864 if (i == RFC1001_NAME_LEN && string[i] != 0)
1865 printk(KERN_WARNING "CIFS: netbiosname"
1866 " longer than 15 truncated.\n");
1867
1868 break;
1869 case Opt_servern:
1870 /* servernetbiosname specified override *SMBSERVER */
1871 string = match_strdup(args);
1872 if (string == NULL)
1873 goto out_nomem;
1874
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001875 /* last byte, type, is 0x20 for servr type */
1876 memset(vol->target_rfc1001_name, 0x20,
1877 RFC1001_NAME_LEN_WITH_NULL);
1878
1879 /* BB are there cases in which a comma can be
1880 valid in this workstation netbios name
1881 (and need special handling)? */
1882
1883 /* user or mount helper must uppercase the
1884 netbios name */
1885 for (i = 0; i < 15; i++) {
1886 if (string[i] == 0)
1887 break;
1888 vol->target_rfc1001_name[i] = string[i];
1889 }
1890 /* The string has 16th byte zero still from
1891 set at top of the function */
1892 if (i == RFC1001_NAME_LEN && string[i] != 0)
1893 printk(KERN_WARNING "CIFS: server net"
1894 "biosname longer than 15 truncated.\n");
1895 break;
1896 case Opt_ver:
1897 string = match_strdup(args);
1898 if (string == NULL)
1899 goto out_nomem;
1900
Jeff Layton5249af32012-05-15 12:04:03 -04001901 if (strnicmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001902 /* This is the default */
1903 break;
1904 }
1905 /* For all other value, error */
1906 printk(KERN_WARNING "CIFS: Invalid version"
1907 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001908 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001909 case Opt_vers:
1910 string = match_strdup(args);
1911 if (string == NULL)
1912 goto out_nomem;
1913
1914 if (cifs_parse_smb_version(string, vol) != 0)
1915 goto cifs_parse_mount_err;
1916 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001917 case Opt_sec:
1918 string = match_strdup(args);
1919 if (string == NULL)
1920 goto out_nomem;
1921
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001922 if (cifs_parse_security_flavors(string, vol) != 0)
1923 goto cifs_parse_mount_err;
1924 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001925 case Opt_cache:
Jeff Layton296838b2012-05-16 07:53:01 -04001926 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001927 string = match_strdup(args);
1928 if (string == NULL)
1929 goto out_nomem;
1930
1931 if (cifs_parse_cache_flavor(string, vol) != 0)
1932 goto cifs_parse_mount_err;
1933 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001934 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001935 /*
1936 * An option we don't recognize. Save it off for later
1937 * if we haven't already found one
1938 */
1939 if (!invalid)
1940 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001941 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001943 /* Free up any allocated string */
1944 kfree(string);
1945 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001947
Jeff Laytond8162552012-03-23 14:40:56 -04001948 if (!sloppy && invalid) {
1949 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1950 goto cifs_parse_mount_err;
1951 }
1952
Jeff Layton8a8798a2012-01-17 16:09:15 -05001953#ifndef CONFIG_KEYS
1954 /* Muliuser mounts require CONFIG_KEYS support */
1955 if (vol->multiuser) {
1956 cERROR(1, "Multiuser mounts require kernels with "
1957 "CONFIG_KEYS enabled.");
Sean Finneyb9468452011-04-11 13:19:32 +00001958 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001959 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001960#endif
Jeff Layton0eb8a132010-10-06 19:51:12 -04001961
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001962 if (vol->UNCip == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 vol->UNCip = &vol->UNC[2];
1964
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001965 if (uid_specified)
1966 vol->override_uid = override_uid;
1967 else if (override_uid == 1)
1968 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1969 "specified with no uid= option.\n");
1970
1971 if (gid_specified)
1972 vol->override_gid = override_gid;
1973 else if (override_gid == 1)
1974 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1975 "specified with no gid= option.\n");
1976
Jeff Layton296838b2012-05-16 07:53:01 -04001977 /* FIXME: remove this block in 3.7 */
1978 if (!cache_specified && !cache_warned) {
1979 cache_warned = true;
1980 printk(KERN_NOTICE "CIFS: no cache= option specified, using "
1981 "\"cache=loose\". This default will change "
1982 "to \"cache=strict\" in 3.7.\n");
1983 }
1984
Sean Finneyb9468452011-04-11 13:19:32 +00001985 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001987
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001988out_nomem:
1989 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001990cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001991 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001992 kfree(mountdata_copy);
1993 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994}
1995
Ben Greear3eb9a882010-09-01 17:06:02 -07001996/** Returns true if srcaddr isn't specified and rhs isn't
1997 * specified, or if srcaddr is specified and
1998 * matches the IP address of the rhs argument.
1999 */
Jeff Layton45151482010-07-06 20:43:02 -04002000static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002001srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2002{
2003 switch (srcaddr->sa_family) {
2004 case AF_UNSPEC:
2005 return (rhs->sa_family == AF_UNSPEC);
2006 case AF_INET: {
2007 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2008 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2009 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2010 }
2011 case AF_INET6: {
2012 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
2013 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
2014 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2015 }
2016 default:
2017 WARN_ON(1);
2018 return false; /* don't expect to be here */
2019 }
2020}
2021
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002022/*
2023 * If no port is specified in addr structure, we try to match with 445 port
2024 * and if it fails - with 139 ports. It should be called only if address
2025 * families of server and addr are equal.
2026 */
2027static bool
2028match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2029{
Steve French6da97912011-03-13 18:55:55 +00002030 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002031
2032 switch (addr->sa_family) {
2033 case AF_INET:
2034 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2035 port = ((struct sockaddr_in *) addr)->sin_port;
2036 break;
2037 case AF_INET6:
2038 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2039 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2040 break;
2041 default:
2042 WARN_ON(1);
2043 return false;
2044 }
2045
2046 if (!port) {
2047 port = htons(CIFS_PORT);
2048 if (port == *sport)
2049 return true;
2050
2051 port = htons(RFC1001_PORT);
2052 }
2053
2054 return port == *sport;
2055}
Ben Greear3eb9a882010-09-01 17:06:02 -07002056
2057static bool
2058match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2059 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060{
Jeff Layton45151482010-07-06 20:43:02 -04002061 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002062 case AF_INET: {
2063 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2064 struct sockaddr_in *srv_addr4 =
2065 (struct sockaddr_in *)&server->dstaddr;
2066
2067 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002068 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002069 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002070 }
2071 case AF_INET6: {
2072 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2073 struct sockaddr_in6 *srv_addr6 =
2074 (struct sockaddr_in6 *)&server->dstaddr;
2075
Jeff Layton45151482010-07-06 20:43:02 -04002076 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002077 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002078 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002079 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002080 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002081 break;
2082 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002083 default:
2084 WARN_ON(1);
2085 return false; /* don't expect to be here */
2086 }
Jeff Layton45151482010-07-06 20:43:02 -04002087
Ben Greear3eb9a882010-09-01 17:06:02 -07002088 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2089 return false;
2090
Jeff Layton45151482010-07-06 20:43:02 -04002091 return true;
2092}
2093
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002094static bool
2095match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2096{
2097 unsigned int secFlags;
2098
2099 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
2100 secFlags = vol->secFlg;
2101 else
2102 secFlags = global_secflags | vol->secFlg;
2103
2104 switch (server->secType) {
2105 case LANMAN:
2106 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
2107 return false;
2108 break;
2109 case NTLMv2:
2110 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
2111 return false;
2112 break;
2113 case NTLM:
2114 if (!(secFlags & CIFSSEC_MAY_NTLM))
2115 return false;
2116 break;
2117 case Kerberos:
2118 if (!(secFlags & CIFSSEC_MAY_KRB5))
2119 return false;
2120 break;
2121 case RawNTLMSSP:
2122 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2123 return false;
2124 break;
2125 default:
2126 /* shouldn't happen */
2127 return false;
2128 }
2129
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002130 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002131 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002132 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002133 return false;
2134 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002135 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002136 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2137 return false;
2138
2139 return true;
2140}
2141
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002142static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
2143 struct smb_vol *vol)
2144{
Jeff Layton23db65f2012-05-15 12:20:51 -04002145 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2146 return 0;
2147
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002148 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2149 return 0;
2150
2151 if (!match_address(server, addr,
2152 (struct sockaddr *)&vol->srcaddr))
2153 return 0;
2154
2155 if (!match_port(server, addr))
2156 return 0;
2157
2158 if (!match_security(server, vol))
2159 return 0;
2160
2161 return 1;
2162}
2163
Jeff Layton45151482010-07-06 20:43:02 -04002164static struct TCP_Server_Info *
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002165cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002166{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002167 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302169 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002170 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002171 if (!match_server(server, addr, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002172 continue;
2173
Jeff Laytone7ddee92008-11-14 13:44:38 -05002174 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302175 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002176 cFYI(1, "Existing tcp session with server found");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002177 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302179 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 return NULL;
2181}
2182
Jeff Layton14fbf502008-11-14 13:53:46 -05002183static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002184cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002186 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302188 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002189 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302190 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002191 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002193
Rob Landleyf1d0c992011-01-22 15:44:05 -06002194 put_net(cifs_net_ns(server));
2195
Jeff Laytone7ddee92008-11-14 13:44:38 -05002196 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302197 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002198
Jeff Laytonc74093b2011-01-11 07:24:23 -05002199 cancel_delayed_work_sync(&server->echo);
2200
Jeff Laytone7ddee92008-11-14 13:44:38 -05002201 spin_lock(&GlobalMid_Lock);
2202 server->tcpStatus = CifsExiting;
2203 spin_unlock(&GlobalMid_Lock);
2204
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002205 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302206 cifs_fscache_release_client_cookie(server);
2207
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002208 kfree(server->session_key.response);
2209 server->session_key.response = NULL;
2210 server->session_key.len = 0;
2211
Jeff Laytone7ddee92008-11-14 13:44:38 -05002212 task = xchg(&server->tsk, NULL);
2213 if (task)
2214 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215}
2216
Jeff Layton63c038c2008-12-01 18:41:46 -05002217static struct TCP_Server_Info *
2218cifs_get_tcp_session(struct smb_vol *volume_info)
2219{
2220 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002221 struct sockaddr_storage addr;
Jeff Layton63c038c2008-12-01 18:41:46 -05002222 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2223 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2224 int rc;
2225
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002226 memset(&addr, 0, sizeof(struct sockaddr_storage));
Jeff Layton63c038c2008-12-01 18:41:46 -05002227
Joe Perchesb6b38f72010-04-21 03:50:45 +00002228 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002229
Jeff Layton63c038c2008-12-01 18:41:46 -05002230 if (volume_info->UNCip && volume_info->UNC) {
Jeff Layton50d97162010-07-06 20:43:01 -04002231 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2232 volume_info->UNCip,
David Howells67b76262010-07-22 18:33:01 +01002233 strlen(volume_info->UNCip),
Jeff Layton50d97162010-07-06 20:43:01 -04002234 volume_info->port);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002235 if (!rc) {
Jeff Layton63c038c2008-12-01 18:41:46 -05002236 /* we failed translating address */
2237 rc = -EINVAL;
2238 goto out_err;
2239 }
Jeff Layton63c038c2008-12-01 18:41:46 -05002240 } else if (volume_info->UNCip) {
2241 /* BB using ip addr as tcp_ses name to connect to the
2242 DFS root below */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002243 cERROR(1, "Connecting to DFS root not implemented yet");
Jeff Layton63c038c2008-12-01 18:41:46 -05002244 rc = -EINVAL;
2245 goto out_err;
2246 } else /* which tcp_sess DFS root would we conect to */ {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002247 cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
2248 "unc=//192.168.1.100/public) specified");
Jeff Layton63c038c2008-12-01 18:41:46 -05002249 rc = -EINVAL;
2250 goto out_err;
2251 }
2252
2253 /* see if we already have a matching tcp_ses */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002254 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002255 if (tcp_ses)
2256 return tcp_ses;
2257
2258 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2259 if (!tcp_ses) {
2260 rc = -ENOMEM;
2261 goto out_err;
2262 }
2263
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002264 rc = cifs_crypto_shash_allocate(tcp_ses);
2265 if (rc) {
2266 cERROR(1, "could not setup hash structures rc %d", rc);
2267 goto out_err;
2268 }
2269
Jeff Layton23db65f2012-05-15 12:20:51 -04002270 tcp_ses->ops = volume_info->ops;
2271 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002272 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002273 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2274 if (IS_ERR(tcp_ses->hostname)) {
2275 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002276 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002277 }
2278
2279 tcp_ses->noblocksnd = volume_info->noblocksnd;
2280 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002281 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002282 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002283 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002284 init_waitqueue_head(&tcp_ses->response_q);
2285 init_waitqueue_head(&tcp_ses->request_q);
2286 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2287 mutex_init(&tcp_ses->srv_mutex);
2288 memcpy(tcp_ses->workstation_RFC1001_name,
2289 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2290 memcpy(tcp_ses->server_RFC1001_name,
2291 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002292 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002293 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002294 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002295 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002296 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2297 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002298 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton63c038c2008-12-01 18:41:46 -05002299
2300 /*
2301 * at this point we are the only ones with the pointer
2302 * to the struct since the kernel thread not created yet
2303 * no need to spinlock this init of tcpStatus or srv_count
2304 */
2305 tcp_ses->tcpStatus = CifsNew;
Ben Greear3eb9a882010-09-01 17:06:02 -07002306 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2307 sizeof(tcp_ses->srcaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002308 ++tcp_ses->srv_count;
2309
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002310 if (addr.ss_family == AF_INET6) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002311 cFYI(1, "attempting ipv6 connect");
Jeff Layton63c038c2008-12-01 18:41:46 -05002312 /* BB should we allow ipv6 on port 139? */
2313 /* other OS never observed in Wild doing 139 with v6 */
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002314 memcpy(&tcp_ses->dstaddr, sin_server6,
2315 sizeof(struct sockaddr_in6));
2316 } else
2317 memcpy(&tcp_ses->dstaddr, sin_server,
2318 sizeof(struct sockaddr_in));
2319
2320 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002321 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002322 cERROR(1, "Error connecting to socket. Aborting operation");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002323 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002324 }
2325
2326 /*
2327 * since we're in a cifs function already, we know that
2328 * this will succeed. No need for try_module_get().
2329 */
2330 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002331 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002332 tcp_ses, "cifsd");
2333 if (IS_ERR(tcp_ses->tsk)) {
2334 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002335 cERROR(1, "error %d create cifsd thread", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002336 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002337 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002338 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002339 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002340
2341 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302342 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002343 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302344 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002345
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302346 cifs_fscache_get_client_cookie(tcp_ses);
2347
Jeff Laytonc74093b2011-01-11 07:24:23 -05002348 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002349 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002350
Jeff Layton63c038c2008-12-01 18:41:46 -05002351 return tcp_ses;
2352
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002353out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002354 cifs_crypto_shash_release(tcp_ses);
2355
Rob Landleyf1d0c992011-01-22 15:44:05 -06002356 put_net(cifs_net_ns(tcp_ses));
2357
Jeff Layton63c038c2008-12-01 18:41:46 -05002358out_err:
2359 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002360 if (!IS_ERR(tcp_ses->hostname))
2361 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002362 if (tcp_ses->ssocket)
2363 sock_release(tcp_ses->ssocket);
2364 kfree(tcp_ses);
2365 }
2366 return ERR_PTR(rc);
2367}
2368
Steve French96daf2b2011-05-27 04:34:02 +00002369static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002370{
2371 switch (ses->server->secType) {
2372 case Kerberos:
2373 if (vol->cred_uid != ses->cred_uid)
2374 return 0;
2375 break;
2376 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002377 /* NULL username means anonymous session */
2378 if (ses->user_name == NULL) {
2379 if (!vol->nullauth)
2380 return 0;
2381 break;
2382 }
2383
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002384 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002385 if (strncmp(ses->user_name,
2386 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002387 MAX_USERNAME_SIZE))
2388 return 0;
2389 if (strlen(vol->username) != 0 &&
2390 ses->password != NULL &&
2391 strncmp(ses->password,
2392 vol->password ? vol->password : "",
2393 MAX_PASSWORD_SIZE))
2394 return 0;
2395 }
2396 return 1;
2397}
2398
Steve French96daf2b2011-05-27 04:34:02 +00002399static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002400cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401{
Steve French96daf2b2011-05-27 04:34:02 +00002402 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302404 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002405 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002406 if (!match_session(ses, vol))
2407 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002408 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302409 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002410 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302412 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 return NULL;
2414}
2415
Jeff Layton14fbf502008-11-14 13:53:46 -05002416static void
Steve French96daf2b2011-05-27 04:34:02 +00002417cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002418{
2419 int xid;
2420 struct TCP_Server_Info *server = ses->server;
2421
Jeff Layton36988c72010-04-24 07:57:43 -04002422 cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302423 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002424 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302425 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002426 return;
2427 }
2428
2429 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302430 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002431
2432 if (ses->status == CifsGood) {
2433 xid = GetXid();
2434 CIFSSMBLogoff(xid, ses);
2435 _FreeXid(xid);
2436 }
2437 sesInfoFree(ses);
2438 cifs_put_tcp_session(server);
2439}
2440
Jeff Layton8a8798a2012-01-17 16:09:15 -05002441#ifdef CONFIG_KEYS
2442
2443/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2444#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2445
2446/* Populate username and pw fields from keyring if possible */
2447static int
2448cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2449{
2450 int rc = 0;
2451 char *desc, *delim, *payload;
2452 ssize_t len;
2453 struct key *key;
2454 struct TCP_Server_Info *server = ses->server;
2455 struct sockaddr_in *sa;
2456 struct sockaddr_in6 *sa6;
2457 struct user_key_payload *upayload;
2458
2459 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2460 if (!desc)
2461 return -ENOMEM;
2462
2463 /* try to find an address key first */
2464 switch (server->dstaddr.ss_family) {
2465 case AF_INET:
2466 sa = (struct sockaddr_in *)&server->dstaddr;
2467 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2468 break;
2469 case AF_INET6:
2470 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2471 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2472 break;
2473 default:
2474 cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
2475 rc = -EINVAL;
2476 goto out_err;
2477 }
2478
2479 cFYI(1, "%s: desc=%s", __func__, desc);
2480 key = request_key(&key_type_logon, desc, "");
2481 if (IS_ERR(key)) {
2482 if (!ses->domainName) {
2483 cFYI(1, "domainName is NULL");
2484 rc = PTR_ERR(key);
2485 goto out_err;
2486 }
2487
2488 /* didn't work, try to find a domain key */
2489 sprintf(desc, "cifs:d:%s", ses->domainName);
2490 cFYI(1, "%s: desc=%s", __func__, desc);
2491 key = request_key(&key_type_logon, desc, "");
2492 if (IS_ERR(key)) {
2493 rc = PTR_ERR(key);
2494 goto out_err;
2495 }
2496 }
2497
2498 down_read(&key->sem);
2499 upayload = key->payload.data;
2500 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002501 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002502 goto out_key_put;
2503 }
2504
2505 /* find first : in payload */
2506 payload = (char *)upayload->data;
2507 delim = strnchr(payload, upayload->datalen, ':');
2508 cFYI(1, "payload=%s", payload);
2509 if (!delim) {
2510 cFYI(1, "Unable to find ':' in payload (datalen=%d)",
2511 upayload->datalen);
2512 rc = -EINVAL;
2513 goto out_key_put;
2514 }
2515
2516 len = delim - payload;
2517 if (len > MAX_USERNAME_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002518 cFYI(1, "Bad value from username search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002519 rc = -EINVAL;
2520 goto out_key_put;
2521 }
2522
2523 vol->username = kstrndup(payload, len, GFP_KERNEL);
2524 if (!vol->username) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002525 cFYI(1, "Unable to allocate %zd bytes for username", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002526 rc = -ENOMEM;
2527 goto out_key_put;
2528 }
2529 cFYI(1, "%s: username=%s", __func__, vol->username);
2530
2531 len = key->datalen - (len + 1);
2532 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002533 cFYI(1, "Bad len for password search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002534 rc = -EINVAL;
2535 kfree(vol->username);
2536 vol->username = NULL;
2537 goto out_key_put;
2538 }
2539
2540 ++delim;
2541 vol->password = kstrndup(delim, len, GFP_KERNEL);
2542 if (!vol->password) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002543 cFYI(1, "Unable to allocate %zd bytes for password", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002544 rc = -ENOMEM;
2545 kfree(vol->username);
2546 vol->username = NULL;
2547 goto out_key_put;
2548 }
2549
2550out_key_put:
2551 up_read(&key->sem);
2552 key_put(key);
2553out_err:
2554 kfree(desc);
2555 cFYI(1, "%s: returning %d", __func__, rc);
2556 return rc;
2557}
2558#else /* ! CONFIG_KEYS */
2559static inline int
2560cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2561 struct cifs_ses *ses __attribute__((unused)))
2562{
2563 return -ENOSYS;
2564}
2565#endif /* CONFIG_KEYS */
2566
Steve Frenchd9b94202011-04-12 01:24:57 +00002567static bool warned_on_ntlm; /* globals init to false automatically */
2568
Steve French96daf2b2011-05-27 04:34:02 +00002569static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002570cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2571{
2572 int rc = -ENOMEM, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002573 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002574 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2575 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002576
2577 xid = GetXid();
2578
Jeff Layton4ff67b72010-07-06 20:43:02 -04002579 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002580 if (ses) {
2581 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
2582
Jeff Layton36988c72010-04-24 07:57:43 -04002583 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002584 rc = cifs_negotiate_protocol(xid, ses);
2585 if (rc) {
2586 mutex_unlock(&ses->session_mutex);
2587 /* problem -- put our ses reference */
2588 cifs_put_smb_ses(ses);
2589 FreeXid(xid);
2590 return ERR_PTR(rc);
2591 }
Jeff Layton36988c72010-04-24 07:57:43 -04002592 if (ses->need_reconnect) {
2593 cFYI(1, "Session needs reconnect");
2594 rc = cifs_setup_session(xid, ses,
2595 volume_info->local_nls);
2596 if (rc) {
2597 mutex_unlock(&ses->session_mutex);
2598 /* problem -- put our reference */
2599 cifs_put_smb_ses(ses);
2600 FreeXid(xid);
2601 return ERR_PTR(rc);
2602 }
2603 }
2604 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002605
2606 /* existing SMB ses has a server reference already */
2607 cifs_put_tcp_session(server);
Jeff Layton36988c72010-04-24 07:57:43 -04002608 FreeXid(xid);
2609 return ses;
2610 }
2611
2612 cFYI(1, "Existing smb sess not found");
2613 ses = sesInfoAlloc();
2614 if (ses == NULL)
2615 goto get_ses_fail;
2616
2617 /* new SMB session uses our server ref */
2618 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002619 if (server->dstaddr.ss_family == AF_INET6)
2620 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002621 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002622 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002623
Steve French8727c8a2011-02-25 01:11:56 -06002624 if (volume_info->username) {
2625 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2626 if (!ses->user_name)
2627 goto get_ses_fail;
2628 }
Jeff Layton36988c72010-04-24 07:57:43 -04002629
2630 /* volume_info->password freed at unmount */
2631 if (volume_info->password) {
2632 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2633 if (!ses->password)
2634 goto get_ses_fail;
2635 }
2636 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002637 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2638 if (!ses->domainName)
2639 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002640 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002641 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002642 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002643
2644 /* ntlmv2 is much stronger than ntlm security, and has been broadly
2645 supported for many years, time to update default security mechanism */
2646 if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
2647 warned_on_ntlm = true;
2648 cERROR(1, "default security mechanism requested. The default "
2649 "security mechanism will be upgraded from ntlm to "
Steve French225de112012-01-03 23:08:24 -06002650 "ntlmv2 in kernel release 3.3");
Steve Frenchd9b94202011-04-12 01:24:57 +00002651 }
Jeff Layton36988c72010-04-24 07:57:43 -04002652 ses->overrideSecFlg = volume_info->secFlg;
2653
2654 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002655 rc = cifs_negotiate_protocol(xid, ses);
2656 if (!rc)
2657 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002658 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002659 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002660 goto get_ses_fail;
2661
2662 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302663 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002664 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302665 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002666
2667 FreeXid(xid);
2668 return ses;
2669
2670get_ses_fail:
2671 sesInfoFree(ses);
2672 FreeXid(xid);
2673 return ERR_PTR(rc);
2674}
2675
Steve French96daf2b2011-05-27 04:34:02 +00002676static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002677{
2678 if (tcon->tidStatus == CifsExiting)
2679 return 0;
2680 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2681 return 0;
2682 return 1;
2683}
2684
Steve French96daf2b2011-05-27 04:34:02 +00002685static struct cifs_tcon *
2686cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687{
2688 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002689 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302691 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002692 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002693 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002694 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002695 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002696 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302697 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 return tcon;
2699 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302700 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 return NULL;
2702}
2703
Jeff Laytonf1987b42008-11-15 11:12:47 -05002704static void
Steve French96daf2b2011-05-27 04:34:02 +00002705cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002706{
2707 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002708 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002709
Jeff Laytond00c28d2010-04-24 07:57:44 -04002710 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302711 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002712 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302713 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002714 return;
2715 }
2716
2717 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302718 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002719
2720 xid = GetXid();
2721 CIFSSMBTDis(xid, tcon);
2722 _FreeXid(xid);
2723
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302724 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002725 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002726 cifs_put_smb_ses(ses);
2727}
2728
Steve French96daf2b2011-05-27 04:34:02 +00002729static struct cifs_tcon *
2730cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002731{
2732 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002733 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002734
2735 tcon = cifs_find_tcon(ses, volume_info->UNC);
2736 if (tcon) {
2737 cFYI(1, "Found match on UNC path");
2738 /* existing tcon already has a reference */
2739 cifs_put_smb_ses(ses);
2740 if (tcon->seal != volume_info->seal)
2741 cERROR(1, "transport encryption setting "
2742 "conflicts with existing tid");
2743 return tcon;
2744 }
2745
2746 tcon = tconInfoAlloc();
2747 if (tcon == NULL) {
2748 rc = -ENOMEM;
2749 goto out_fail;
2750 }
2751
2752 tcon->ses = ses;
2753 if (volume_info->password) {
2754 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2755 if (!tcon->password) {
2756 rc = -ENOMEM;
2757 goto out_fail;
2758 }
2759 }
2760
2761 if (strchr(volume_info->UNC + 3, '\\') == NULL
2762 && strchr(volume_info->UNC + 3, '/') == NULL) {
2763 cERROR(1, "Missing share name");
2764 rc = -ENODEV;
2765 goto out_fail;
2766 }
2767
2768 /* BB Do we need to wrap session_mutex around
2769 * this TCon call and Unix SetFS as
2770 * we do on SessSetup and reconnect? */
2771 xid = GetXid();
2772 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
2773 FreeXid(xid);
2774 cFYI(1, "CIFS Tcon rc = %d", rc);
2775 if (rc)
2776 goto out_fail;
2777
2778 if (volume_info->nodfs) {
2779 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2780 cFYI(1, "DFS disabled (%d)", tcon->Flags);
2781 }
2782 tcon->seal = volume_info->seal;
2783 /* we can have only one retry value for a connection
2784 to a share so for resources mounted more than once
2785 to the same server share the last value passed in
2786 for the retry flag is used */
2787 tcon->retry = volume_info->retry;
2788 tcon->nocase = volume_info->nocase;
2789 tcon->local_lease = volume_info->local_lease;
2790
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302791 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002792 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302793 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002794
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302795 cifs_fscache_get_super_cookie(tcon);
2796
Jeff Laytond00c28d2010-04-24 07:57:44 -04002797 return tcon;
2798
2799out_fail:
2800 tconInfoFree(tcon);
2801 return ERR_PTR(rc);
2802}
2803
Jeff Layton9d002df2010-10-06 19:51:11 -04002804void
2805cifs_put_tlink(struct tcon_link *tlink)
2806{
2807 if (!tlink || IS_ERR(tlink))
2808 return;
2809
2810 if (!atomic_dec_and_test(&tlink->tl_count) ||
2811 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2812 tlink->tl_time = jiffies;
2813 return;
2814 }
2815
2816 if (!IS_ERR(tlink_tcon(tlink)))
2817 cifs_put_tcon(tlink_tcon(tlink));
2818 kfree(tlink);
2819 return;
2820}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002821
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002822static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002823cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2824{
2825 return cifs_sb->master_tlink;
2826}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002827
2828static int
2829compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2830{
2831 struct cifs_sb_info *old = CIFS_SB(sb);
2832 struct cifs_sb_info *new = mnt_data->cifs_sb;
2833
2834 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2835 return 0;
2836
2837 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2838 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2839 return 0;
2840
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002841 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002842 * We want to share sb only if we don't specify an r/wsize or
2843 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002844 */
2845 if (new->wsize && new->wsize < old->wsize)
2846 return 0;
2847
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002848 if (new->rsize && new->rsize < old->rsize)
2849 return 0;
2850
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002851 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2852 return 0;
2853
2854 if (old->mnt_file_mode != new->mnt_file_mode ||
2855 old->mnt_dir_mode != new->mnt_dir_mode)
2856 return 0;
2857
2858 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2859 return 0;
2860
2861 if (old->actimeo != new->actimeo)
2862 return 0;
2863
2864 return 1;
2865}
2866
2867int
2868cifs_match_super(struct super_block *sb, void *data)
2869{
2870 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2871 struct smb_vol *volume_info;
2872 struct cifs_sb_info *cifs_sb;
2873 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002874 struct cifs_ses *ses;
2875 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002876 struct tcon_link *tlink;
2877 struct sockaddr_storage addr;
2878 int rc = 0;
2879
2880 memset(&addr, 0, sizeof(struct sockaddr_storage));
2881
2882 spin_lock(&cifs_tcp_ses_lock);
2883 cifs_sb = CIFS_SB(sb);
2884 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2885 if (IS_ERR(tlink)) {
2886 spin_unlock(&cifs_tcp_ses_lock);
2887 return rc;
2888 }
2889 tcon = tlink_tcon(tlink);
2890 ses = tcon->ses;
2891 tcp_srv = ses->server;
2892
2893 volume_info = mnt_data->vol;
2894
2895 if (!volume_info->UNCip || !volume_info->UNC)
2896 goto out;
2897
2898 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2899 volume_info->UNCip,
2900 strlen(volume_info->UNCip),
2901 volume_info->port);
2902 if (!rc)
2903 goto out;
2904
2905 if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
2906 !match_session(ses, volume_info) ||
2907 !match_tcon(tcon, volume_info->UNC)) {
2908 rc = 0;
2909 goto out;
2910 }
2911
2912 rc = compare_mount_options(sb, mnt_data);
2913out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002914 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002915 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002916 return rc;
2917}
2918
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919int
Steve French96daf2b2011-05-27 04:34:02 +00002920get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
Steve French50c2f752007-07-13 00:33:32 +00002921 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
Steve French366781c2008-01-25 10:12:41 +00002922 struct dfs_info3_param **preferrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923{
2924 char *temp_unc;
2925 int rc = 0;
2926
2927 *pnum_referrals = 0;
Steve French366781c2008-01-25 10:12:41 +00002928 *preferrals = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929
2930 if (pSesInfo->ipc_tid == 0) {
2931 temp_unc = kmalloc(2 /* for slashes */ +
Steve French50c2f752007-07-13 00:33:32 +00002932 strnlen(pSesInfo->serverName,
2933 SERVER_NAME_LEN_WITH_NULL * 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 + 1 + 4 /* slash IPC$ */ + 2,
2935 GFP_KERNEL);
2936 if (temp_unc == NULL)
2937 return -ENOMEM;
2938 temp_unc[0] = '\\';
2939 temp_unc[1] = '\\';
2940 strcpy(temp_unc + 2, pSesInfo->serverName);
2941 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
2942 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002943 cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 kfree(temp_unc);
2945 }
2946 if (rc == 0)
Steve Frenchc2cf07d2008-05-15 06:20:02 +00002947 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
Steve French737b7582005-04-28 22:41:06 -07002948 pnum_referrals, nls_codepage, remap);
Steve French366781c2008-01-25 10:12:41 +00002949 /* BB map targetUNCs to dfs_info3 structures, here or
2950 in CIFSGetDFSRefer BB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951
2952 return rc;
2953}
2954
Jeff Layton09e50d52008-07-23 10:11:19 -04002955#ifdef CONFIG_DEBUG_LOCK_ALLOC
2956static struct lock_class_key cifs_key[2];
2957static struct lock_class_key cifs_slock_key[2];
2958
2959static inline void
2960cifs_reclassify_socket4(struct socket *sock)
2961{
2962 struct sock *sk = sock->sk;
2963 BUG_ON(sock_owned_by_user(sk));
2964 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2965 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2966}
2967
2968static inline void
2969cifs_reclassify_socket6(struct socket *sock)
2970{
2971 struct sock *sk = sock->sk;
2972 BUG_ON(sock_owned_by_user(sk));
2973 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2974 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2975}
2976#else
2977static inline void
2978cifs_reclassify_socket4(struct socket *sock)
2979{
2980}
2981
2982static inline void
2983cifs_reclassify_socket6(struct socket *sock)
2984{
2985}
2986#endif
2987
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002989static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990{
Steve French50c2f752007-07-13 00:33:32 +00002991 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992
Steve French50c2f752007-07-13 00:33:32 +00002993 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 /* mask a nibble at a time and encode */
2995 target[j] = 'A' + (0x0F & (source[i] >> 4));
2996 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002997 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 }
2999
3000}
3001
Ben Greear3eb9a882010-09-01 17:06:02 -07003002static int
3003bind_socket(struct TCP_Server_Info *server)
3004{
3005 int rc = 0;
3006 if (server->srcaddr.ss_family != AF_UNSPEC) {
3007 /* Bind to the specified local IP address */
3008 struct socket *socket = server->ssocket;
3009 rc = socket->ops->bind(socket,
3010 (struct sockaddr *) &server->srcaddr,
3011 sizeof(server->srcaddr));
3012 if (rc < 0) {
3013 struct sockaddr_in *saddr4;
3014 struct sockaddr_in6 *saddr6;
3015 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3016 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3017 if (saddr6->sin6_family == AF_INET6)
3018 cERROR(1, "cifs: "
3019 "Failed to bind to: %pI6c, error: %d\n",
3020 &saddr6->sin6_addr, rc);
3021 else
3022 cERROR(1, "cifs: "
3023 "Failed to bind to: %pI4, error: %d\n",
3024 &saddr4->sin_addr.s_addr, rc);
3025 }
3026 }
3027 return rc;
3028}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
3030static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003031ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032{
3033 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003034 /*
3035 * some servers require RFC1001 sessinit before sending
3036 * negprot - BB check reconnection in case where second
3037 * sessinit is sent but no second negprot
3038 */
3039 struct rfc1002_session_packet *ses_init_buf;
3040 struct smb_hdr *smb_buf;
3041 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3042 GFP_KERNEL);
3043 if (ses_init_buf) {
3044 ses_init_buf->trailer.session_req.called_len = 32;
3045
3046 if (server->server_RFC1001_name &&
3047 server->server_RFC1001_name[0] != 0)
3048 rfc1002mangle(ses_init_buf->trailer.
3049 session_req.called_name,
3050 server->server_RFC1001_name,
3051 RFC1001_NAME_LEN_WITH_NULL);
3052 else
3053 rfc1002mangle(ses_init_buf->trailer.
3054 session_req.called_name,
3055 DEFAULT_CIFS_CALLED_NAME,
3056 RFC1001_NAME_LEN_WITH_NULL);
3057
3058 ses_init_buf->trailer.session_req.calling_len = 32;
3059
3060 /*
3061 * calling name ends in null (byte 16) from old smb
3062 * convention.
3063 */
3064 if (server->workstation_RFC1001_name &&
3065 server->workstation_RFC1001_name[0] != 0)
3066 rfc1002mangle(ses_init_buf->trailer.
3067 session_req.calling_name,
3068 server->workstation_RFC1001_name,
3069 RFC1001_NAME_LEN_WITH_NULL);
3070 else
3071 rfc1002mangle(ses_init_buf->trailer.
3072 session_req.calling_name,
3073 "LINUX_CIFS_CLNT",
3074 RFC1001_NAME_LEN_WITH_NULL);
3075
3076 ses_init_buf->trailer.session_req.scope1 = 0;
3077 ses_init_buf->trailer.session_req.scope2 = 0;
3078 smb_buf = (struct smb_hdr *)ses_init_buf;
3079
3080 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003081 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003082 rc = smb_send(server, smb_buf, 0x44);
3083 kfree(ses_init_buf);
3084 /*
3085 * RFC1001 layer in at least one server
3086 * requires very short break before negprot
3087 * presumably because not expecting negprot
3088 * to follow so fast. This is a simple
3089 * solution that works without
3090 * complicating the code and causes no
3091 * significant slowing down on mount
3092 * for everyone else
3093 */
3094 usleep_range(1000, 2000);
3095 }
3096 /*
3097 * else the negprot may still work without this
3098 * even though malloc failed
3099 */
3100
3101 return rc;
3102}
3103
3104static int
3105generic_ip_connect(struct TCP_Server_Info *server)
3106{
3107 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003108 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003109 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003110 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003111 struct sockaddr *saddr;
3112
3113 saddr = (struct sockaddr *) &server->dstaddr;
3114
3115 if (server->dstaddr.ss_family == AF_INET6) {
3116 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3117 slen = sizeof(struct sockaddr_in6);
3118 sfamily = AF_INET6;
3119 } else {
3120 sport = ((struct sockaddr_in *) saddr)->sin_port;
3121 slen = sizeof(struct sockaddr_in);
3122 sfamily = AF_INET;
3123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003125 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003126 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3127 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003129 cERROR(1, "Error %d creating socket", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003130 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003133
3134 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003135 cFYI(1, "Socket created");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003136 server->ssocket = socket;
3137 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003138 if (sfamily == AF_INET6)
3139 cifs_reclassify_socket6(socket);
3140 else
3141 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 }
3143
Ben Greear3eb9a882010-09-01 17:06:02 -07003144 rc = bind_socket(server);
3145 if (rc < 0)
3146 return rc;
3147
Jeff Laytond5c56052008-12-01 18:42:33 -05003148 /*
3149 * Eventually check for other socket options to change from
3150 * the default. sock_setsockopt not used because it expects
3151 * user space buffer
3152 */
3153 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003154 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003155
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003156 /* make the bufsizes depend on wsize/rsize and max requests */
3157 if (server->noautotune) {
3158 if (socket->sk->sk_sndbuf < (200 * 1024))
3159 socket->sk->sk_sndbuf = 200 * 1024;
3160 if (socket->sk->sk_rcvbuf < (140 * 1024))
3161 socket->sk->sk_rcvbuf = 140 * 1024;
3162 }
3163
Steve French6a5fa2362010-01-01 01:28:43 +00003164 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003165 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003166 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3167 (char *)&val, sizeof(val));
3168 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003169 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003170 }
3171
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003172 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
3173 socket->sk->sk_sndbuf,
3174 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3175
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003176 rc = socket->ops->connect(socket, saddr, slen, 0);
3177 if (rc < 0) {
3178 cFYI(1, "Error %d connecting to server", rc);
3179 sock_release(socket);
3180 server->ssocket = NULL;
3181 return rc;
3182 }
3183
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003184 if (sport == htons(RFC1001_PORT))
3185 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003186
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 return rc;
3188}
3189
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003190static int
3191ip_connect(struct TCP_Server_Info *server)
3192{
Steve French6da97912011-03-13 18:55:55 +00003193 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003194 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3195 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3196
3197 if (server->dstaddr.ss_family == AF_INET6)
3198 sport = &addr6->sin6_port;
3199 else
3200 sport = &addr->sin_port;
3201
3202 if (*sport == 0) {
3203 int rc;
3204
3205 /* try with 445 port at first */
3206 *sport = htons(CIFS_PORT);
3207
3208 rc = generic_ip_connect(server);
3209 if (rc >= 0)
3210 return rc;
3211
3212 /* if it failed, try with 139 port */
3213 *sport = htons(RFC1001_PORT);
3214 }
3215
3216 return generic_ip_connect(server);
3217}
3218
Steve French96daf2b2011-05-27 04:34:02 +00003219void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003220 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003221{
3222 /* if we are reconnecting then should we check to see if
3223 * any requested capabilities changed locally e.g. via
3224 * remount but we can not do much about it here
3225 * if they have (even if we could detect it by the following)
3226 * Perhaps we could add a backpointer to array of sb from tcon
3227 * or if we change to make all sb to same share the same
3228 * sb as NFS - then we only have one backpointer to sb.
3229 * What if we wanted to mount the server share twice once with
3230 * and once without posixacls or posix paths? */
3231 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003232
Steve Frenchc18c8422007-07-18 23:21:09 +00003233 if (vol_info && vol_info->no_linux_ext) {
3234 tcon->fsUnixInfo.Capability = 0;
3235 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003236 cFYI(1, "Linux protocol extensions disabled");
Steve Frenchc18c8422007-07-18 23:21:09 +00003237 return;
3238 } else if (vol_info)
3239 tcon->unix_ext = 1; /* Unix Extensions supported */
3240
3241 if (tcon->unix_ext == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003242 cFYI(1, "Unix extensions disabled so not set on reconnect");
Steve Frenchc18c8422007-07-18 23:21:09 +00003243 return;
3244 }
Steve French50c2f752007-07-13 00:33:32 +00003245
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003246 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003247 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French6848b732011-05-26 18:38:54 +00003248 cFYI(1, "unix caps which server supports %lld", cap);
Steve French8af18972007-02-14 04:42:51 +00003249 /* check for reconnect case in which we do not
3250 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003251 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003252 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003253 originally at mount time */
3254 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3255 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003256 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3257 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003258 cERROR(1, "POSIXPATH support change");
Steve French8af18972007-02-14 04:42:51 +00003259 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003260 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003261 cERROR(1, "possible reconnect error");
3262 cERROR(1, "server disabled POSIX path support");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003263 }
Steve French8af18972007-02-14 04:42:51 +00003264 }
Steve French50c2f752007-07-13 00:33:32 +00003265
Steve French6848b732011-05-26 18:38:54 +00003266 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3267 cERROR(1, "per-share encryption not supported yet");
3268
Steve French8af18972007-02-14 04:42:51 +00003269 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003270 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003271 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003272 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003273 cFYI(1, "negotiated posix acl support");
Al Viro2c6292a2011-06-17 09:05:48 -04003274 if (cifs_sb)
3275 cifs_sb->mnt_cifs_flags |=
3276 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003277 }
3278
Steve French75865f8c2007-06-24 18:30:48 +00003279 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003280 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003281 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003282 cFYI(1, "negotiate posix pathnames");
Al Viro2c6292a2011-06-17 09:05:48 -04003283 if (cifs_sb)
3284 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003285 CIFS_MOUNT_POSIX_PATHS;
3286 }
Steve French50c2f752007-07-13 00:33:32 +00003287
Joe Perchesb6b38f72010-04-21 03:50:45 +00003288 cFYI(1, "Negotiate caps 0x%x", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003289#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003290 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003291 cFYI(1, "FCNTL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003292 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003293 cFYI(1, "EXTATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003294 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003295 cFYI(1, "POSIX path cap");
Steve French75865f8c2007-06-24 18:30:48 +00003296 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003297 cFYI(1, "XATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003298 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003299 cFYI(1, "POSIX ACL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003300 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003301 cFYI(1, "very large read cap");
Steve French75865f8c2007-06-24 18:30:48 +00003302 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003303 cFYI(1, "very large write cap");
Steve French6848b732011-05-26 18:38:54 +00003304 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3305 cFYI(1, "transport encryption cap");
3306 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3307 cFYI(1, "mandatory transport encryption cap");
Steve French8af18972007-02-14 04:42:51 +00003308#endif /* CIFS_DEBUG2 */
3309 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003310 if (vol_info == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003311 cFYI(1, "resetting capabilities failed");
Steve French442aa312007-09-24 20:25:46 +00003312 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003313 cERROR(1, "Negotiating Unix capabilities "
Steve French5a44b312007-09-20 15:16:24 +00003314 "with the server failed. Consider "
3315 "mounting with the Unix Extensions\n"
3316 "disabled, if problems are found, "
3317 "by specifying the nounix mount "
Joe Perchesb6b38f72010-04-21 03:50:45 +00003318 "option.");
Steve French5a44b312007-09-20 15:16:24 +00003319
Steve French8af18972007-02-14 04:42:51 +00003320 }
3321 }
3322}
3323
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003324void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3325 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003326{
Jeff Layton2de970f2010-10-06 19:51:12 -04003327 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3328
Al Viro2ced6f62011-06-17 09:20:04 -04003329 spin_lock_init(&cifs_sb->tlink_tree_lock);
3330 cifs_sb->tlink_tree = RB_ROOT;
3331
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003332 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003333 * Temporarily set r/wsize for matching superblock. If we end up using
3334 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003335 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003336 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003337 cifs_sb->wsize = pvolume_info->wsize;
3338
Steve French3b795212008-11-13 19:45:32 +00003339 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3340 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3341 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3342 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Al Viro5206efd2011-07-26 03:22:14 -04003343 cFYI(1, "file mode: 0x%hx dir mode: 0x%hx",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003344 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003345
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303346 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003347 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303348
Steve French3b795212008-11-13 19:45:32 +00003349 if (pvolume_info->noperm)
3350 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3351 if (pvolume_info->setuids)
3352 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3353 if (pvolume_info->server_ino)
3354 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3355 if (pvolume_info->remap)
3356 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3357 if (pvolume_info->no_xattr)
3358 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3359 if (pvolume_info->sfu_emul)
3360 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3361 if (pvolume_info->nobrl)
3362 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003363 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003364 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003365 if (pvolume_info->mand_lock)
3366 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003367 if (pvolume_info->rwpidforward)
3368 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003369 if (pvolume_info->cifs_acl)
3370 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003371 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003372 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003373 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3374 }
3375 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003376 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003377 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3378 }
Steve French3b795212008-11-13 19:45:32 +00003379 if (pvolume_info->override_uid)
3380 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3381 if (pvolume_info->override_gid)
3382 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3383 if (pvolume_info->dynperm)
3384 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303385 if (pvolume_info->fsc)
3386 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003387 if (pvolume_info->multiuser)
3388 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3389 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003390 if (pvolume_info->strict_io)
3391 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003392 if (pvolume_info->direct_io) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003393 cFYI(1, "mounting share using direct i/o");
Steve French3b795212008-11-13 19:45:32 +00003394 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3395 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003396 if (pvolume_info->mfsymlinks) {
3397 if (pvolume_info->sfu_emul) {
3398 cERROR(1, "mount option mfsymlinks ignored if sfu "
3399 "mount option is used");
3400 } else {
3401 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3402 }
3403 }
Steve French3b795212008-11-13 19:45:32 +00003404
3405 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesb6b38f72010-04-21 03:50:45 +00003406 cERROR(1, "mount option dynperm ignored if cifsacl "
3407 "mount option supported");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003408}
3409
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003410/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003411 * When the server supports very large reads and writes via POSIX extensions,
3412 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
3413 * including the RFC1001 length.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003414 *
3415 * Note that this might make for "interesting" allocation problems during
Jeff Layton1190f6a2011-06-22 17:33:57 -04003416 * writeback however as we have to allocate an array of pointers for the
3417 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003418 *
3419 * For reads, there is a similar problem as we need to allocate an array
3420 * of kvecs to handle the receive, though that should only need to be done
3421 * once.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003422 */
Jeff Layton1190f6a2011-06-22 17:33:57 -04003423#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003424#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003425
3426/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003427 * When the server doesn't allow large posix writes, only allow a rsize/wsize
3428 * of 2^17-1 minus the size of the call header. That allows for a read or
3429 * write up to the maximum size described by RFC1002.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003430 */
Pavel Shilovsky94443f42011-10-07 18:57:45 +04003431#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003432#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003433
3434/*
3435 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
3436 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
3437 * a single wsize request with a single call.
3438 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003439#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
3440
3441/*
Jeff Laytonce91acb2012-01-17 16:08:51 -05003442 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
3443 * those values when posix extensions aren't in force. In actuality here, we
3444 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
3445 * to be ok with the extra byte even though Windows doesn't send writes that
3446 * are that large.
3447 *
3448 * Citation:
3449 *
3450 * 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 -04003451 */
3452#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
Jeff Laytonce91acb2012-01-17 16:08:51 -05003453#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003454
3455static unsigned int
Steve French96daf2b2011-05-27 04:34:02 +00003456cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003457{
3458 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3459 struct TCP_Server_Info *server = tcon->ses->server;
Jeff Laytonce91acb2012-01-17 16:08:51 -05003460 unsigned int wsize;
3461
3462 /* start with specified wsize, or default */
3463 if (pvolume_info->wsize)
3464 wsize = pvolume_info->wsize;
3465 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3466 wsize = CIFS_DEFAULT_IOSIZE;
3467 else
3468 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003469
3470 /* can server support 24-bit write sizes? (via UNIX extensions) */
3471 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
Jeff Layton1190f6a2011-06-22 17:33:57 -04003472 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003473
Jeff Layton1190f6a2011-06-22 17:33:57 -04003474 /*
3475 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
3476 * Limit it to max buffer offered by the server, minus the size of the
3477 * WRITEX header, not including the 4 byte RFC1001 length.
3478 */
3479 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
3480 (!(server->capabilities & CAP_UNIX) &&
3481 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
3482 wsize = min_t(unsigned int, wsize,
3483 server->maxBuf - sizeof(WRITE_REQ) + 4);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003484
3485 /* hard limit of CIFS_MAX_WSIZE */
3486 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3487
3488 return wsize;
3489}
3490
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003491static unsigned int
3492cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3493{
3494 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3495 struct TCP_Server_Info *server = tcon->ses->server;
3496 unsigned int rsize, defsize;
3497
3498 /*
3499 * Set default value...
3500 *
3501 * HACK alert! Ancient servers have very small buffers. Even though
3502 * MS-CIFS indicates that servers are only limited by the client's
3503 * bufsize for reads, testing against win98se shows that it throws
3504 * INVALID_PARAMETER errors if you try to request too large a read.
3505 *
3506 * If the server advertises a MaxBufferSize of less than one page,
3507 * assume that it also can't satisfy reads larger than that either.
3508 *
3509 * FIXME: Is there a better heuristic for this?
3510 */
3511 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
3512 defsize = CIFS_DEFAULT_IOSIZE;
3513 else if (server->capabilities & CAP_LARGE_READ_X)
3514 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
3515 else if (server->maxBuf >= PAGE_CACHE_SIZE)
3516 defsize = CIFSMaxBufSize;
3517 else
3518 defsize = server->maxBuf - sizeof(READ_RSP);
3519
3520 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
3521
3522 /*
3523 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
3524 * the client's MaxBufferSize.
3525 */
3526 if (!(server->capabilities & CAP_LARGE_READ_X))
3527 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3528
3529 /* hard limit of CIFS_MAX_RSIZE */
3530 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3531
3532 return rsize;
3533}
3534
Igor Mammedove4cce942009-02-10 14:10:26 +03003535static int
Steve French96daf2b2011-05-27 04:34:02 +00003536is_path_accessible(int xid, struct cifs_tcon *tcon,
Igor Mammedove4cce942009-02-10 14:10:26 +03003537 struct cifs_sb_info *cifs_sb, const char *full_path)
3538{
3539 int rc;
Igor Mammedove4cce942009-02-10 14:10:26 +03003540 FILE_ALL_INFO *pfile_info;
3541
Igor Mammedove4cce942009-02-10 14:10:26 +03003542 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
3543 if (pfile_info == NULL)
3544 return -ENOMEM;
3545
3546 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
3547 0 /* not legacy */, cifs_sb->local_nls,
3548 cifs_sb->mnt_cifs_flags &
3549 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton221d1d72011-05-17 06:40:30 -04003550
3551 if (rc == -EOPNOTSUPP || rc == -EINVAL)
3552 rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
3553 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
3554 CIFS_MOUNT_MAP_SPECIAL_CHR);
Igor Mammedove4cce942009-02-10 14:10:26 +03003555 kfree(pfile_info);
3556 return rc;
3557}
3558
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003559static void
3560cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003561{
Sean Finneyb9468452011-04-11 13:19:32 +00003562 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003563 kzfree(volume_info->password);
Steve French13589c42011-08-18 04:41:55 +00003564 if (volume_info->UNCip != volume_info->UNC + 2)
3565 kfree(volume_info->UNCip);
Jesper Juhl95c75452011-08-27 18:58:34 +02003566 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003567 kfree(volume_info->domainname);
3568 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003569 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003570}
3571
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003572void
3573cifs_cleanup_volume_info(struct smb_vol *volume_info)
3574{
3575 if (!volume_info)
3576 return;
3577 cleanup_volume_info_contents(volume_info);
3578 kfree(volume_info);
3579}
3580
3581
Steve French2d6d5892009-04-09 00:36:44 +00003582#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003583/* build_path_to_root returns full path to root when
3584 * we do not have an exiting connection (tcon) */
3585static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003586build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003587 const struct cifs_sb_info *cifs_sb)
3588{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003589 char *full_path, *pos;
3590 unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
3591 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003592
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003593 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003594 if (full_path == NULL)
3595 return ERR_PTR(-ENOMEM);
3596
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003597 strncpy(full_path, vol->UNC, unc_len);
3598 pos = full_path + unc_len;
3599
3600 if (pplen) {
3601 strncpy(pos, vol->prepath, pplen);
3602 pos += pplen;
3603 }
3604
3605 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003606 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003607 cFYI(1, "%s: full_path=%s", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003608 return full_path;
3609}
Sean Finneydd613942011-04-11 13:19:30 +00003610
3611/*
3612 * Perform a dfs referral query for a share and (optionally) prefix
3613 *
Sean Finney046462a2011-04-11 13:19:33 +00003614 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3615 * to a string containing updated options for the submount. Otherwise it
3616 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003617 *
3618 * Returns the rc from get_dfs_path to the caller, which can be used to
3619 * determine whether there were referrals.
3620 */
3621static int
Steve French96daf2b2011-05-27 04:34:02 +00003622expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
Sean Finneydd613942011-04-11 13:19:30 +00003623 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003624 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003625{
3626 int rc;
3627 unsigned int num_referrals = 0;
3628 struct dfs_info3_param *referrals = NULL;
3629 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3630
3631 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3632 if (IS_ERR(full_path))
3633 return PTR_ERR(full_path);
3634
3635 /* For DFS paths, skip the first '\' of the UNC */
3636 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3637
3638 rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
3639 &num_referrals, &referrals,
3640 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3641
3642 if (!rc && num_referrals > 0) {
3643 char *fake_devname = NULL;
3644
3645 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3646 full_path + 1, referrals,
3647 &fake_devname);
3648
3649 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003650
Sean Finneydd613942011-04-11 13:19:30 +00003651 if (IS_ERR(mdata)) {
3652 rc = PTR_ERR(mdata);
3653 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003654 } else {
3655 cleanup_volume_info_contents(volume_info);
3656 memset(volume_info, '\0', sizeof(*volume_info));
3657 rc = cifs_setup_volume_info(volume_info, mdata,
3658 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003659 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003660 kfree(fake_devname);
3661 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003662 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003663 }
3664 kfree(full_path);
3665 return rc;
3666}
Steve French2d6d5892009-04-09 00:36:44 +00003667#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003668
Jeff Layton04db79b2011-07-06 08:10:38 -04003669static int
3670cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3671 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003673 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003674
Jeff Layton04db79b2011-07-06 08:10:38 -04003675 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3676 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677
Jeff Layton23db65f2012-05-15 12:20:51 -04003678
Jeff Layton7586b762008-12-01 18:41:49 -05003679 if (volume_info->nullauth) {
Jeff Layton04febab2012-01-17 16:09:15 -05003680 cFYI(1, "Anonymous login");
3681 kfree(volume_info->username);
3682 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003683 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684 /* BB fixme parse for domain name here */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003685 cFYI(1, "Username: %s", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 } else {
Steve Frenchbf820672005-12-01 22:32:42 -08003687 cifserror("No username specified");
Steve French50c2f752007-07-13 00:33:32 +00003688 /* In userspace mount helper we can get user name from alternate
3689 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003690 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 }
3692
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003694 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003695 /* load_nls_default cannot return null */
3696 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003698 volume_info->local_nls = load_nls(volume_info->iocharset);
3699 if (volume_info->local_nls == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003700 cERROR(1, "CIFS mount error: iocharset %s not found",
3701 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003702 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 }
3704 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003705
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003706 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003707}
3708
3709struct smb_vol *
3710cifs_get_volume_info(char *mount_data, const char *devname)
3711{
3712 int rc;
3713 struct smb_vol *volume_info;
3714
3715 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
3716 if (!volume_info)
3717 return ERR_PTR(-ENOMEM);
3718
3719 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3720 if (rc) {
3721 cifs_cleanup_volume_info(volume_info);
3722 volume_info = ERR_PTR(rc);
3723 }
3724
3725 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003726}
3727
3728int
Al Viro2c6292a2011-06-17 09:05:48 -04003729cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003730{
Jeff Layton1daaae82012-03-21 06:30:40 -04003731 int rc;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003732 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003733 struct cifs_ses *pSesInfo;
3734 struct cifs_tcon *tcon;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003735 struct TCP_Server_Info *srvTcp;
3736 char *full_path;
3737 struct tcon_link *tlink;
3738#ifdef CONFIG_CIFS_DFS_UPCALL
3739 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003740#endif
Al Virodd854462011-06-17 08:24:42 -04003741
3742 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3743 if (rc)
3744 return rc;
3745
Jeff Layton20547492011-07-09 12:21:07 -04003746#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003747try_mount_again:
3748 /* cleanup activities if we're chasing a referral */
3749 if (referral_walks_count) {
3750 if (tcon)
3751 cifs_put_tcon(tcon);
3752 else if (pSesInfo)
3753 cifs_put_smb_ses(pSesInfo);
3754
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003755 FreeXid(xid);
3756 }
3757#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003758 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003759 tcon = NULL;
3760 pSesInfo = NULL;
3761 srvTcp = NULL;
3762 full_path = NULL;
3763 tlink = NULL;
3764
3765 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766
Jeff Layton63c038c2008-12-01 18:41:46 -05003767 /* get a reference to a tcp session */
Jeff Layton7586b762008-12-01 18:41:49 -05003768 srvTcp = cifs_get_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05003769 if (IS_ERR(srvTcp)) {
3770 rc = PTR_ERR(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003771 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003772 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 }
3774
Jeff Layton36988c72010-04-24 07:57:43 -04003775 /* get a reference to a SMB session */
3776 pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
3777 if (IS_ERR(pSesInfo)) {
3778 rc = PTR_ERR(pSesInfo);
3779 pSesInfo = NULL;
3780 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 }
Steve French50c2f752007-07-13 00:33:32 +00003782
Jeff Laytond00c28d2010-04-24 07:57:44 -04003783 /* search for existing tcon to this server share */
3784 tcon = cifs_get_tcon(pSesInfo, volume_info);
3785 if (IS_ERR(tcon)) {
3786 rc = PTR_ERR(tcon);
3787 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003788 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003789 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003790
Steve French6848b732011-05-26 18:38:54 +00003791 /* tell server which Unix caps we support */
3792 if (tcon->ses->capabilities & CAP_UNIX) {
3793 /* reset of caps checks mount to see if unix extensions
3794 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003795 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003796 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3797 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3798 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3799 rc = -EACCES;
3800 goto mount_fail_check;
3801 }
3802 } else
3803 tcon->unix_ext = 0; /* server does not support them */
3804
Steve Frenchd82c2df2008-11-15 00:07:26 +00003805 /* do not care if following two calls succeed - informational */
3806 if (!tcon->ipc) {
3807 CIFSSMBQFSDeviceInfo(xid, tcon);
3808 CIFSSMBQFSAttributeInfo(xid, tcon);
3809 }
3810
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003811 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003812 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003813
Jeff Layton66bfaad2011-10-19 15:30:35 -04003814 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003815 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003816
Igor Mammedove4cce942009-02-10 14:10:26 +03003817remote_path_check:
3818#ifdef CONFIG_CIFS_DFS_UPCALL
3819 /*
3820 * Perform an unconditional check for whether there are DFS
3821 * referrals for this path without prefix, to provide support
3822 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003823 * with PATH_NOT_COVERED to requests that include the prefix.
3824 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003825 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003826 if (referral_walks_count == 0) {
3827 int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
3828 cifs_sb, false);
3829 if (!refrc) {
3830 referral_walks_count++;
3831 goto try_mount_again;
3832 }
3833 }
3834#endif
3835
Steve Frenchf87d39d2011-05-27 03:50:55 +00003836 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 if (!rc && tcon) {
3838 /* build_path_to_root works only when we have a valid tcon */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003839 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Steve French7c7b25b2006-06-01 19:20:10 +00003840 if (full_path == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 rc = -ENOMEM;
3842 goto mount_fail_check;
3843 }
3844 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
3845 if (rc != 0 && rc != -EREMOTE) {
3846 kfree(full_path);
3847 goto mount_fail_check;
3848 }
3849 kfree(full_path);
3850 }
3851
3852 /* get referral if needed */
3853 if (rc == -EREMOTE) {
3854#ifdef CONFIG_CIFS_DFS_UPCALL
3855 if (referral_walks_count > MAX_NESTED_LINKS) {
3856 /*
Steve Frencheeac8042006-01-13 21:34:58 -08003857 * BB: when we implement proper loop detection,
Steve French4523cc32007-04-30 20:13:06 +00003858 * we will remove this check. But now we need it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 * to prevent an indefinite loop if 'DFS tree' is
3860 * misconfigured (i.e. has loops).
3861 */
3862 rc = -ELOOP;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003863 goto mount_fail_check;
3864 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003865
Sean Finneydd613942011-04-11 13:19:30 +00003866 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003867 true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003868
Sean Finneydd613942011-04-11 13:19:30 +00003869 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003870 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003871 goto try_mount_again;
3872 }
Sean Finneydd613942011-04-11 13:19:30 +00003873 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003874#else /* No DFS support, return error on mount */
3875 rc = -EOPNOTSUPP;
3876#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003877 }
3878
Jeff Layton9d002df2010-10-06 19:51:11 -04003879 if (rc)
3880 goto mount_fail_check;
3881
3882 /* now, hang the tcon off of the superblock */
3883 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3884 if (tlink == NULL) {
3885 rc = -ENOMEM;
3886 goto mount_fail_check;
3887 }
3888
Jeff Laytonb647c352010-10-28 11:16:44 -04003889 tlink->tl_uid = pSesInfo->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003890 tlink->tl_tcon = tcon;
3891 tlink->tl_time = jiffies;
3892 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3893 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3894
Jeff Layton413e6612010-10-28 13:33:38 -04003895 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003896 spin_lock(&cifs_sb->tlink_tree_lock);
3897 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3898 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003899
Jeff Laytonda472fc2012-03-23 14:40:53 -04003900 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003901 TLINK_IDLE_EXPIRE);
3902
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003903mount_fail_check:
3904 /* on error free sesinfo and tcon struct if needed */
3905 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003906 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003907 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003908 if (tcon)
3909 cifs_put_tcon(tcon);
3910 else if (pSesInfo)
3911 cifs_put_smb_ses(pSesInfo);
3912 else
3913 cifs_put_tcp_session(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003914 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003915 }
3916
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 FreeXid(xid);
3919 return rc;
3920}
3921
Jeff Layton8d1bca32011-06-11 21:17:10 -04003922/*
3923 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3924 * pointer may be NULL.
3925 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926int
Steve French96daf2b2011-05-27 04:34:02 +00003927CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3928 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 const struct nls_table *nls_codepage)
3930{
3931 struct smb_hdr *smb_buffer;
3932 struct smb_hdr *smb_buffer_response;
3933 TCONX_REQ *pSMB;
3934 TCONX_RSP *pSMBr;
3935 unsigned char *bcc_ptr;
3936 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003937 int length;
3938 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
3940 if (ses == NULL)
3941 return -EIO;
3942
3943 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003944 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003946
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 smb_buffer_response = smb_buffer;
3948
3949 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3950 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003951
3952 smb_buffer->Mid = GetNextMid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953 smb_buffer->Uid = ses->Suid;
3954 pSMB = (TCONX_REQ *) smb_buffer;
3955 pSMBr = (TCONX_RSP *) smb_buffer_response;
3956
3957 pSMB->AndXCommand = 0xFF;
3958 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003960 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003961 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003962 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003963 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003964 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003965 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003966 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003967 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3968 specified as required (when that support is added to
3969 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003970 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003971 by Samba (not sure whether other servers allow
3972 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003973#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003974 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003975 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003976 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003977 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003978 SECMODE_PW_ENCRYPT ? true : false,
3979 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003980 else
3981#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003982 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003983 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003984
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003985 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003986 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003987 /* must align unicode strings */
3988 *bcc_ptr = 0; /* null byte password */
3989 bcc_ptr++;
3990 }
Steve Frencheeac8042006-01-13 21:34:58 -08003991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992
Steve French96daf2b2011-05-27 04:34:02 +00003993 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003994 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3996
3997 if (ses->capabilities & CAP_STATUS32) {
3998 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3999 }
4000 if (ses->capabilities & CAP_DFS) {
4001 smb_buffer->Flags2 |= SMBFLG2_DFS;
4002 }
4003 if (ses->capabilities & CAP_UNICODE) {
4004 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
4005 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06004006 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00004007 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00004008 (/* server len*/ + 256 /* share len */), nls_codepage);
4009 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 bcc_ptr += 2; /* skip trailing null */
4011 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 strcpy(bcc_ptr, tree);
4013 bcc_ptr += strlen(tree) + 1;
4014 }
4015 strcpy(bcc_ptr, "?????");
4016 bcc_ptr += strlen("?????");
4017 bcc_ptr += 1;
4018 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004019 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4020 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 pSMB->ByteCount = cpu_to_le16(count);
4022
Steve French133672e2007-11-13 22:41:37 +00004023 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004024 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 /* above now done in SendReceive */
4027 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004028 bool is_unicode;
4029
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004031 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 tcon->tid = smb_buffer_response->Tid;
4033 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004034 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004035 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004036 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4037 is_unicode = true;
4038 else
4039 is_unicode = false;
4040
Jeff Laytoncc20c032009-04-30 07:16:21 -04004041
Steve French50c2f752007-07-13 00:33:32 +00004042 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004043 if (length == 3) {
4044 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4045 (bcc_ptr[2] == 'C')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004046 cFYI(1, "IPC connection");
Steve French7f8ed422007-09-28 22:28:55 +00004047 tcon->ipc = 1;
4048 }
4049 } else if (length == 2) {
4050 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4051 /* the most common case */
Joe Perchesb6b38f72010-04-21 03:50:45 +00004052 cFYI(1, "disk share connection");
Steve French7f8ed422007-09-28 22:28:55 +00004053 }
4054 }
Steve French50c2f752007-07-13 00:33:32 +00004055 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004056 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004058
4059 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004060 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004061 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004062 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004063 nls_codepage);
4064
Joe Perchesb6b38f72010-04-21 03:50:45 +00004065 cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004066
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004067 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004068 (smb_buffer_response->WordCount == 7))
4069 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004070 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4071 else
4072 tcon->Flags = 0;
Joe Perchesb6b38f72010-04-21 03:50:45 +00004073 cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004075 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076 ses->ipc_tid = smb_buffer_response->Tid;
4077 }
4078
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004079 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 return rc;
4081}
4082
Al Viro2a9b9952011-06-17 09:27:16 -04004083void
4084cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085{
Jeff Laytonb647c352010-10-28 11:16:44 -04004086 struct rb_root *root = &cifs_sb->tlink_tree;
4087 struct rb_node *node;
4088 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Jeff Layton2de970f2010-10-06 19:51:12 -04004090 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4091
Jeff Laytonb647c352010-10-28 11:16:44 -04004092 spin_lock(&cifs_sb->tlink_tree_lock);
4093 while ((node = rb_first(root))) {
4094 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4095 cifs_get_tlink(tlink);
4096 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4097 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004098
Jeff Laytonb647c352010-10-28 11:16:44 -04004099 spin_unlock(&cifs_sb->tlink_tree_lock);
4100 cifs_put_tlink(tlink);
4101 spin_lock(&cifs_sb->tlink_tree_lock);
4102 }
4103 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004104
Al Virodd854462011-06-17 08:24:42 -04004105 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004106 kfree(cifs_sb->mountdata);
4107 unload_nls(cifs_sb->local_nls);
4108 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00004109}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
Steve French96daf2b2011-05-27 04:34:02 +00004111int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112{
4113 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004114 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115
Jeff Layton198b5682010-04-24 07:57:48 -04004116 /* only send once per connect */
4117 if (server->maxBuf != 0)
4118 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004120 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004121 rc = CIFSSMBNegotiate(xid, ses);
4122 if (rc == -EAGAIN) {
4123 /* retry only once on 1st time connection */
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004124 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004125 rc = CIFSSMBNegotiate(xid, ses);
4126 if (rc == -EAGAIN)
4127 rc = -EHOSTDOWN;
4128 }
4129 if (rc == 0) {
4130 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004131 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004132 server->tcpStatus = CifsGood;
4133 else
4134 rc = -EHOSTDOWN;
4135 spin_unlock(&GlobalMid_Lock);
4136
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 }
Steve French26b994f2008-08-06 05:11:33 +00004138
Jeff Layton198b5682010-04-24 07:57:48 -04004139 return rc;
4140}
Steve French26b994f2008-08-06 05:11:33 +00004141
Jeff Layton198b5682010-04-24 07:57:48 -04004142
Steve French96daf2b2011-05-27 04:34:02 +00004143int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
Jeff Layton198b5682010-04-24 07:57:48 -04004144 struct nls_table *nls_info)
4145{
4146 int rc = 0;
4147 struct TCP_Server_Info *server = ses->server;
4148
4149 ses->flags = 0;
4150 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004151 if (linuxExtEnabled == 0)
Jeff Layton198b5682010-04-24 07:57:48 -04004152 ses->capabilities &= (~CAP_UNIX);
Steve French20418ac2009-04-30 16:13:32 +00004153
Joe Perchesb6b38f72010-04-21 03:50:45 +00004154 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
Steve French96daf2b2011-05-27 04:34:02 +00004155 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004156
Jeff Layton198b5682010-04-24 07:57:48 -04004157 rc = CIFS_SessSetup(xid, ses, nls_info);
Steve French26b994f2008-08-06 05:11:33 +00004158 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004159 cERROR(1, "Send error in SessSetup = %d", rc);
Steve French26b994f2008-08-06 05:11:33 +00004160 } else {
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004161 mutex_lock(&ses->server->srv_mutex);
4162 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004163 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004164 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004165 server->sequence_number = 0x2;
4166 server->session_estab = true;
4167 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004168 }
4169 mutex_unlock(&server->srv_mutex);
4170
Joe Perchesb6b38f72010-04-21 03:50:45 +00004171 cFYI(1, "CIFS Session Established successfully");
Steve French20418ac2009-04-30 16:13:32 +00004172 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04004173 ses->status = CifsGood;
4174 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00004175 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00004176 }
4177
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004178 kfree(ses->auth_key.response);
4179 ses->auth_key.response = NULL;
4180 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05004181 kfree(ses->ntlmssp);
4182 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004183
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 return rc;
4185}
4186
Jeff Layton8a8798a2012-01-17 16:09:15 -05004187static int
4188cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4189{
4190 switch (ses->server->secType) {
4191 case Kerberos:
4192 vol->secFlg = CIFSSEC_MUST_KRB5;
4193 return 0;
4194 case NTLMv2:
4195 vol->secFlg = CIFSSEC_MUST_NTLMV2;
4196 break;
4197 case NTLM:
4198 vol->secFlg = CIFSSEC_MUST_NTLM;
4199 break;
4200 case RawNTLMSSP:
4201 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
4202 break;
4203 case LANMAN:
4204 vol->secFlg = CIFSSEC_MUST_LANMAN;
4205 break;
4206 }
4207
4208 return cifs_set_cifscreds(vol, ses);
4209}
4210
Steve French96daf2b2011-05-27 04:34:02 +00004211static struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004212cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
4213{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004214 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004215 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4216 struct cifs_ses *ses;
4217 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004218 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004219
4220 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004221 if (vol_info == NULL)
4222 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004223
Jeff Layton9d002df2010-10-06 19:51:11 -04004224 vol_info->local_nls = cifs_sb->local_nls;
4225 vol_info->linux_uid = fsuid;
4226 vol_info->cred_uid = fsuid;
4227 vol_info->UNC = master_tcon->treeName;
4228 vol_info->retry = master_tcon->retry;
4229 vol_info->nocase = master_tcon->nocase;
4230 vol_info->local_lease = master_tcon->local_lease;
4231 vol_info->no_linux_ext = !master_tcon->unix_ext;
4232
Jeff Layton8a8798a2012-01-17 16:09:15 -05004233 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4234 if (rc) {
4235 tcon = ERR_PTR(rc);
4236 goto out;
4237 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004238
4239 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304240 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004241 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304242 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004243
4244 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4245 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004246 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004247 cifs_put_tcp_session(master_tcon->ses->server);
4248 goto out;
4249 }
4250
4251 tcon = cifs_get_tcon(ses, vol_info);
4252 if (IS_ERR(tcon)) {
4253 cifs_put_smb_ses(ses);
4254 goto out;
4255 }
4256
4257 if (ses->capabilities & CAP_UNIX)
4258 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4259out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004260 kfree(vol_info->username);
4261 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004262 kfree(vol_info);
4263
4264 return tcon;
4265}
4266
Steve French96daf2b2011-05-27 04:34:02 +00004267struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004268cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4269{
4270 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4271}
4272
4273static int
4274cifs_sb_tcon_pending_wait(void *unused)
4275{
4276 schedule();
4277 return signal_pending(current) ? -ERESTARTSYS : 0;
4278}
4279
Jeff Laytonb647c352010-10-28 11:16:44 -04004280/* find and return a tlink with given uid */
4281static struct tcon_link *
4282tlink_rb_search(struct rb_root *root, uid_t uid)
4283{
4284 struct rb_node *node = root->rb_node;
4285 struct tcon_link *tlink;
4286
4287 while (node) {
4288 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4289
4290 if (tlink->tl_uid > uid)
4291 node = node->rb_left;
4292 else if (tlink->tl_uid < uid)
4293 node = node->rb_right;
4294 else
4295 return tlink;
4296 }
4297 return NULL;
4298}
4299
4300/* insert a tcon_link into the tree */
4301static void
4302tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4303{
4304 struct rb_node **new = &(root->rb_node), *parent = NULL;
4305 struct tcon_link *tlink;
4306
4307 while (*new) {
4308 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4309 parent = *new;
4310
4311 if (tlink->tl_uid > new_tlink->tl_uid)
4312 new = &((*new)->rb_left);
4313 else
4314 new = &((*new)->rb_right);
4315 }
4316
4317 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4318 rb_insert_color(&new_tlink->tl_rbnode, root);
4319}
4320
Jeff Layton9d002df2010-10-06 19:51:11 -04004321/*
4322 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4323 * current task.
4324 *
4325 * If the superblock doesn't refer to a multiuser mount, then just return
4326 * the master tcon for the mount.
4327 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304328 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004329 * exists, then check to see if it's pending construction. If it is then wait
4330 * for construction to complete. Once it's no longer pending, check to see if
4331 * it failed and either return an error or retry construction, depending on
4332 * the timeout.
4333 *
4334 * If one doesn't exist then insert a new tcon_link struct into the tree and
4335 * try to construct a new one.
4336 */
4337struct tcon_link *
4338cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4339{
4340 int ret;
Jeff Laytonb647c352010-10-28 11:16:44 -04004341 uid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004342 struct tcon_link *tlink, *newtlink;
4343
4344 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4345 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4346
4347 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004348 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004349 if (tlink)
4350 cifs_get_tlink(tlink);
4351 spin_unlock(&cifs_sb->tlink_tree_lock);
4352
4353 if (tlink == NULL) {
4354 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4355 if (newtlink == NULL)
4356 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004357 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004358 newtlink->tl_tcon = ERR_PTR(-EACCES);
4359 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4360 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4361 cifs_get_tlink(newtlink);
4362
Jeff Layton9d002df2010-10-06 19:51:11 -04004363 spin_lock(&cifs_sb->tlink_tree_lock);
4364 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004365 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004366 if (tlink) {
4367 cifs_get_tlink(tlink);
4368 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004369 kfree(newtlink);
4370 goto wait_for_construction;
4371 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004372 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004373 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4374 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004375 } else {
4376wait_for_construction:
4377 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4378 cifs_sb_tcon_pending_wait,
4379 TASK_INTERRUPTIBLE);
4380 if (ret) {
4381 cifs_put_tlink(tlink);
4382 return ERR_PTR(ret);
4383 }
4384
4385 /* if it's good, return it */
4386 if (!IS_ERR(tlink->tl_tcon))
4387 return tlink;
4388
4389 /* return error if we tried this already recently */
4390 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4391 cifs_put_tlink(tlink);
4392 return ERR_PTR(-EACCES);
4393 }
4394
4395 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4396 goto wait_for_construction;
4397 }
4398
4399 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4400 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4401 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4402
4403 if (IS_ERR(tlink->tl_tcon)) {
4404 cifs_put_tlink(tlink);
4405 return ERR_PTR(-EACCES);
4406 }
4407
4408 return tlink;
4409}
Jeff Layton2de970f2010-10-06 19:51:12 -04004410
4411/*
4412 * periodic workqueue job that scans tcon_tree for a superblock and closes
4413 * out tcons.
4414 */
4415static void
4416cifs_prune_tlinks(struct work_struct *work)
4417{
4418 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4419 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004420 struct rb_root *root = &cifs_sb->tlink_tree;
4421 struct rb_node *node = rb_first(root);
4422 struct rb_node *tmp;
4423 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004424
Jeff Laytonb647c352010-10-28 11:16:44 -04004425 /*
4426 * Because we drop the spinlock in the loop in order to put the tlink
4427 * it's not guarded against removal of links from the tree. The only
4428 * places that remove entries from the tree are this function and
4429 * umounts. Because this function is non-reentrant and is canceled
4430 * before umount can proceed, this is safe.
4431 */
4432 spin_lock(&cifs_sb->tlink_tree_lock);
4433 node = rb_first(root);
4434 while (node != NULL) {
4435 tmp = node;
4436 node = rb_next(tmp);
4437 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4438
4439 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4440 atomic_read(&tlink->tl_count) != 0 ||
4441 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4442 continue;
4443
4444 cifs_get_tlink(tlink);
4445 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4446 rb_erase(tmp, root);
4447
Jeff Layton2de970f2010-10-06 19:51:12 -04004448 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004449 cifs_put_tlink(tlink);
4450 spin_lock(&cifs_sb->tlink_tree_lock);
4451 }
4452 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004453
Jeff Laytonda472fc2012-03-23 14:40:53 -04004454 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004455 TLINK_IDLE_EXPIRE);
4456}