blob: ccafdedd0dbc4df14e04c0087d28b1dfa453be1f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve French1080ef72011-02-24 18:07:19 +00004 * Copyright (C) International Business Machines Corp., 2002,2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
24#include <linux/list.h>
25#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070031#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070032#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000033#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070034#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080035#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040036#include <linux/namei.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <asm/uaccess.h>
38#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040039#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040040#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050041#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000042#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040043#include <linux/parser.h>
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "cifspdu.h"
46#include "cifsglob.h"
47#include "cifsproto.h"
48#include "cifs_unicode.h"
49#include "cifs_debug.h"
50#include "cifs_fs_sb.h"
51#include "ntlmssp.h"
52#include "nterr.h"
53#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053054#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#define CIFS_PORT 445
57#define RFC1001_PORT 139
58
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 },
Steve French1080ef72011-02-24 18:07:19 +0000281 { Smb_21, SMB21_VERSION_STRING },
Jeff Layton23db65f2012-05-15 12:20:51 -0400282};
283
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300284static int ip_connect(struct TCP_Server_Info *server);
285static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400286static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400287static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400288static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
289 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Jeff Laytond5c56052008-12-01 18:42:33 -0500291/*
292 * cifs tcp session reconnection
293 *
294 * mark tcp session as reconnecting so temporarily locked
295 * mark all smb sessions as reconnecting for tcp session
296 * reconnect tcp session
297 * wake up waiters on reconnection? - (not needed currently)
298 */
Steve French2cd646a2006-09-28 19:43:08 +0000299static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300cifs_reconnect(struct TCP_Server_Info *server)
301{
302 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500303 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000304 struct cifs_ses *ses;
305 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000306 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400307 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000310 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000311 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 next time through the loop */
313 spin_unlock(&GlobalMid_Lock);
314 return rc;
315 } else
316 server->tcpStatus = CifsNeedReconnect;
317 spin_unlock(&GlobalMid_Lock);
318 server->maxBuf = 0;
319
Joe Perchesb6b38f72010-04-21 03:50:45 +0000320 cFYI(1, "Reconnecting tcp session");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
322 /* before reconnecting the tcp session, mark the smb session (uid)
323 and the tid bad so they are not used until reconnected */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500324 cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530325 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500326 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000327 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500328 ses->need_reconnect = true;
329 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500330 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000331 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500332 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530335 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 /* do not want to be sending data on a socket we are freeing */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500338 cFYI(1, "%s: tearing down socket", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500339 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000340 if (server->ssocket) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000341 cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
342 server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800343 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000344 cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx",
Steve French467a8f82007-06-27 22:41:32 +0000345 server->ssocket->state,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000346 server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 sock_release(server->ssocket);
348 server->ssocket = NULL;
349 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500350 server->sequence_number = 0;
351 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500352 kfree(server->session_key.response);
353 server->session_key.response = NULL;
354 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000355 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500356 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500358 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400359 INIT_LIST_HEAD(&retry_list);
360 cFYI(1, "%s: moving mids to private list", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500362 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
363 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400364 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
365 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400366 list_move(&mid_entry->qhead, &retry_list);
367 }
368 spin_unlock(&GlobalMid_Lock);
369
370 cFYI(1, "%s: issuing mid callbacks", __func__);
371 list_for_each_safe(tmp, tmp2, &retry_list) {
372 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500373 list_del_init(&mid_entry->qhead);
374 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400377 do {
Steve French6c3d8902006-07-31 22:46:20 +0000378 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300379
380 /* we should try only the port we connected to before */
381 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000382 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000383 cFYI(1, "reconnect error %d", rc);
Steve French0cb766a2005-04-28 22:41:11 -0700384 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 } else {
386 atomic_inc(&tcpSesReconnectCount);
387 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000388 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000389 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000390 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400392 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500393
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 return rc;
395}
396
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000397/*
Steve Frenche4eb2952005-04-28 22:41:09 -0700398 return codes:
399 0 not a transact2, or all data present
400 >0 transact2 with that much data missing
401 -EINVAL = invalid transact2
402
403 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400404static int check2ndT2(char *buf)
Steve Frenche4eb2952005-04-28 22:41:09 -0700405{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400406 struct smb_hdr *pSMB = (struct smb_hdr *)buf;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000407 struct smb_t2_rsp *pSMBt;
Steve Frenche4eb2952005-04-28 22:41:09 -0700408 int remaining;
Jeff Layton26ec2542011-01-20 13:36:51 -0500409 __u16 total_data_size, data_in_this_rsp;
Steve Frenche4eb2952005-04-28 22:41:09 -0700410
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000411 if (pSMB->Command != SMB_COM_TRANSACTION2)
Steve Frenche4eb2952005-04-28 22:41:09 -0700412 return 0;
413
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000414 /* check for plausible wct, bcc and t2 data and parm sizes */
415 /* check for parm and data offset going beyond end of smb */
416 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
Joe Perchesb6b38f72010-04-21 03:50:45 +0000417 cFYI(1, "invalid transact2 word count");
Steve Frenche4eb2952005-04-28 22:41:09 -0700418 return -EINVAL;
419 }
420
421 pSMBt = (struct smb_t2_rsp *)pSMB;
422
Jeff Layton26ec2542011-01-20 13:36:51 -0500423 total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
424 data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700425
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400426 if (total_data_size == data_in_this_rsp)
Steve Frenche4eb2952005-04-28 22:41:09 -0700427 return 0;
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400428 else if (total_data_size < data_in_this_rsp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000429 cFYI(1, "total data %d smaller than data in frame %d",
430 total_data_size, data_in_this_rsp);
Steve Frenche4eb2952005-04-28 22:41:09 -0700431 return -EINVAL;
Steve Frenche4eb2952005-04-28 22:41:09 -0700432 }
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400433
434 remaining = total_data_size - data_in_this_rsp;
435
436 cFYI(1, "missing %d bytes from transact2, check next response",
437 remaining);
Jeff Laytonc974bef2011-10-11 06:41:32 -0400438 if (total_data_size > CIFSMaxBufSize) {
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400439 cERROR(1, "TotalDataSize %d is over maximum buffer %d",
Jeff Laytonc974bef2011-10-11 06:41:32 -0400440 total_data_size, CIFSMaxBufSize);
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400441 return -EINVAL;
442 }
443 return remaining;
Steve Frenche4eb2952005-04-28 22:41:09 -0700444}
445
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400446static int coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
Steve Frenche4eb2952005-04-28 22:41:09 -0700447{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400448 struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
449 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500450 char *data_area_of_tgt;
451 char *data_area_of_src;
Jeff Layton26ec2542011-01-20 13:36:51 -0500452 int remaining;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500453 unsigned int byte_count, total_in_tgt;
454 __u16 tgt_total_cnt, src_total_cnt, total_in_src;
Steve Frenche4eb2952005-04-28 22:41:09 -0700455
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500456 src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
457 tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700458
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500459 if (tgt_total_cnt != src_total_cnt)
460 cFYI(1, "total data count of primary and secondary t2 differ "
461 "source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
Steve Frenche4eb2952005-04-28 22:41:09 -0700462
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500463 total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700464
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500465 remaining = tgt_total_cnt - total_in_tgt;
Steve French50c2f752007-07-13 00:33:32 +0000466
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500467 if (remaining < 0) {
468 cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
469 "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400470 return -EPROTO;
Steve Frenche4eb2952005-04-28 22:41:09 -0700471 }
472
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500473 if (remaining == 0) {
474 /* nothing to do, ignore */
475 cFYI(1, "no more data remains");
476 return 0;
477 }
478
479 total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
480 if (remaining < total_in_src)
481 cFYI(1, "transact2 2nd response contains too much data");
482
Steve Frenche4eb2952005-04-28 22:41:09 -0700483 /* find end of first SMB data area */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500484 data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
Jeff Layton26ec2542011-01-20 13:36:51 -0500485 get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500486
Steve Frenche4eb2952005-04-28 22:41:09 -0700487 /* validate target area */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500488 data_area_of_src = (char *)&pSMBs->hdr.Protocol +
489 get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
Steve Frenche4eb2952005-04-28 22:41:09 -0700490
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500491 data_area_of_tgt += total_in_tgt;
Steve Frenche4eb2952005-04-28 22:41:09 -0700492
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500493 total_in_tgt += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400494 /* is the result too big for the field? */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500495 if (total_in_tgt > USHRT_MAX) {
496 cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400497 return -EPROTO;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500498 }
499 put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400500
501 /* fix up the BCC */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400502 byte_count = get_bcc(target_hdr);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500503 byte_count += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400504 /* is the result too big for the field? */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500505 if (byte_count > USHRT_MAX) {
506 cFYI(1, "coalesced BCC too large (%u)", byte_count);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400507 return -EPROTO;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500508 }
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400509 put_bcc(byte_count, target_hdr);
Steve Frenche4eb2952005-04-28 22:41:09 -0700510
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400511 byte_count = be32_to_cpu(target_hdr->smb_buf_length);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500512 byte_count += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400513 /* don't allow buffer to overflow */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500514 if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
515 cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400516 return -ENOBUFS;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500517 }
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400518 target_hdr->smb_buf_length = cpu_to_be32(byte_count);
Steve Frenche4eb2952005-04-28 22:41:09 -0700519
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500520 /* copy second buffer into end of first buffer */
521 memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400522
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500523 if (remaining != total_in_src) {
524 /* more responses to go */
525 cFYI(1, "waiting for more secondary responses");
Steve Frenche4eb2952005-04-28 22:41:09 -0700526 return 1;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500527 }
528
529 /* we are done */
530 cFYI(1, "found the last secondary response");
531 return 0;
Steve Frenche4eb2952005-04-28 22:41:09 -0700532}
533
Jeff Laytonc74093b2011-01-11 07:24:23 -0500534static void
535cifs_echo_request(struct work_struct *work)
536{
537 int rc;
538 struct TCP_Server_Info *server = container_of(work,
539 struct TCP_Server_Info, echo.work);
540
Jeff Layton247ec9b2011-02-04 17:09:50 -0500541 /*
Jeff Layton195291e2011-02-09 12:01:42 -0500542 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is
543 * done, which is indicated by maxBuf != 0. Also, no need to ping if
544 * we got a response recently
Jeff Layton247ec9b2011-02-04 17:09:50 -0500545 */
Jeff Layton195291e2011-02-09 12:01:42 -0500546 if (server->maxBuf == 0 ||
Jeff Layton247ec9b2011-02-04 17:09:50 -0500547 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500548 goto requeue_echo;
549
550 rc = CIFSSMBEcho(server);
551 if (rc)
552 cFYI(1, "Unable to send echo request to server: %s",
553 server->hostname);
554
555requeue_echo:
Jeff Laytonda472fc2012-03-23 14:40:53 -0400556 queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500557}
558
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400559static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400560allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400561{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400562 if (!server->bigbuf) {
563 server->bigbuf = (char *)cifs_buf_get();
564 if (!server->bigbuf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400565 cERROR(1, "No memory for large SMB response");
566 msleep(3000);
567 /* retry will check if exiting */
568 return false;
569 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400570 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400571 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400572 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400573 }
574
Jeff Layton2a37ef92011-10-19 15:29:23 -0400575 if (!server->smallbuf) {
576 server->smallbuf = (char *)cifs_small_buf_get();
577 if (!server->smallbuf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400578 cERROR(1, "No memory for SMB response");
579 msleep(1000);
580 /* retry will check if exiting */
581 return false;
582 }
583 /* beginning of smb buffer is cleared in our buf_get */
584 } else {
585 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400586 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400587 }
588
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400589 return true;
590}
591
Jeff Laytonba749e62011-10-11 06:41:32 -0400592static bool
593server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400594{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300595 /*
596 * We need to wait 2 echo intervals to make sure we handle such
597 * situations right:
598 * 1s client sends a normal SMB request
599 * 2s client gets a response
600 * 30s echo workqueue job pops, and decides we got a response recently
601 * and don't need to send another
602 * ...
603 * 65s kernel_recvmsg times out, and we see that we haven't gotten
604 * a response in >60s.
605 */
606 if (server->tcpStatus == CifsGood &&
607 time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
Jeff Laytonba749e62011-10-11 06:41:32 -0400608 cERROR(1, "Server %s has not responded in %d seconds. "
609 "Reconnecting...", server->hostname,
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300610 (2 * SMB_ECHO_INTERVAL) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400611 cifs_reconnect(server);
612 wake_up(&server->response_q);
613 return true;
614 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400615
Jeff Laytonba749e62011-10-11 06:41:32 -0400616 return false;
617}
618
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400619/*
620 * kvec_array_init - clone a kvec array, and advance into it
621 * @new: pointer to memory for cloned array
622 * @iov: pointer to original array
623 * @nr_segs: number of members in original array
624 * @bytes: number of bytes to advance into the cloned array
625 *
626 * This function will copy the array provided in iov to a section of memory
627 * and advance the specified number of bytes into the new array. It returns
628 * the number of segments in the new array. "new" must be at least as big as
629 * the original iov array.
630 */
631static unsigned int
632kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
633 size_t bytes)
634{
635 size_t base = 0;
636
637 while (bytes || !iov->iov_len) {
638 int copy = min(bytes, iov->iov_len);
639
640 bytes -= copy;
641 base += copy;
642 if (iov->iov_len == base) {
643 iov++;
644 nr_segs--;
645 base = 0;
646 }
647 }
648 memcpy(new, iov, sizeof(*iov) * nr_segs);
649 new->iov_base += base;
650 new->iov_len -= base;
651 return nr_segs;
652}
653
Jeff Layton1041e3f2011-10-19 15:28:27 -0400654static struct kvec *
655get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
656{
657 struct kvec *new_iov;
658
659 if (server->iov && nr_segs <= server->nr_iov)
660 return server->iov;
661
662 /* not big enough -- allocate a new one and release the old */
663 new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
664 if (new_iov) {
665 kfree(server->iov);
666 server->iov = new_iov;
667 server->nr_iov = nr_segs;
668 }
669 return new_iov;
670}
671
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400672int
673cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
674 unsigned int nr_segs, unsigned int to_read)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400675{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400676 int length = 0;
677 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400678 unsigned int segs;
Jeff Laytone831e6c2011-10-11 06:41:32 -0400679 struct msghdr smb_msg;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400680 struct kvec *iov;
681
Jeff Layton1041e3f2011-10-19 15:28:27 -0400682 iov = get_server_iovec(server, nr_segs);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400683 if (!iov)
684 return -ENOMEM;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400685
Jeff Laytone831e6c2011-10-11 06:41:32 -0400686 smb_msg.msg_control = NULL;
687 smb_msg.msg_controllen = 0;
688
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400689 for (total_read = 0; to_read; total_read += length, to_read -= length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500690 try_to_freeze();
691
Jeff Laytonba749e62011-10-11 06:41:32 -0400692 if (server_unresponsive(server)) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400693 total_read = -EAGAIN;
Jeff Laytonba749e62011-10-11 06:41:32 -0400694 break;
695 }
696
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400697 segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
698
699 length = kernel_recvmsg(server->ssocket, &smb_msg,
700 iov, segs, to_read, 0);
701
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400702 if (server->tcpStatus == CifsExiting) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400703 total_read = -ESHUTDOWN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400704 break;
705 } else if (server->tcpStatus == CifsNeedReconnect) {
706 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400707 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400708 break;
709 } else if (length == -ERESTARTSYS ||
710 length == -EAGAIN ||
711 length == -EINTR) {
712 /*
713 * Minimum sleep to prevent looping, allowing socket
714 * to clear and app threads to set tcpStatus
715 * CifsNeedReconnect if server hung.
716 */
717 usleep_range(1000, 2000);
718 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400719 continue;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400720 } else if (length <= 0) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400721 cFYI(1, "Received no data or error: expecting %d "
722 "got %d", to_read, length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400723 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400724 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400725 break;
726 }
727 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400728 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400729}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400730
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400731int
732cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
733 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400734{
735 struct kvec iov;
736
737 iov.iov_base = buf;
738 iov.iov_len = to_read;
739
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400740 return cifs_readv_from_socket(server, &iov, 1, to_read);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400741}
742
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400743static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400744is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400745{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400746 /*
747 * The first byte big endian of the length field,
748 * is actually not part of the length but the type
749 * with the most common, zero, as regular data.
750 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400751 switch (type) {
752 case RFC1002_SESSION_MESSAGE:
753 /* Regular SMB response */
754 return true;
755 case RFC1002_SESSION_KEEP_ALIVE:
756 cFYI(1, "RFC 1002 session keep alive");
757 break;
758 case RFC1002_POSITIVE_SESSION_RESPONSE:
759 cFYI(1, "RFC 1002 positive session response");
760 break;
761 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400762 /*
763 * We get this from Windows 98 instead of an error on
764 * SMB negprot response.
765 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400766 cFYI(1, "RFC 1002 negative session response");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400767 /* give server a second to clean up */
768 msleep(1000);
769 /*
770 * Always try 445 first on reconnect since we get NACK
771 * on some if we ever connected to port 139 (the NACK
772 * is since we do not begin with RFC1001 session
773 * initialize frame).
774 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400775 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400776 cifs_reconnect(server);
777 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400778 break;
779 default:
780 cERROR(1, "RFC 1002 unknown response type 0x%x", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400781 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400782 }
783
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400784 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400785}
786
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400787void
788dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400789{
790#ifdef CONFIG_CIFS_STATS2
791 mid->when_received = jiffies;
792#endif
793 spin_lock(&GlobalMid_Lock);
794 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400795 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400796 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400797 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400798 list_del_init(&mid->qhead);
799 spin_unlock(&GlobalMid_Lock);
800}
801
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400802static void
803handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400804 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400805{
Jeff Laytonffc00e22011-10-19 15:29:13 -0400806 if (malformed == 0 && check2ndT2(buf) > 0) {
807 mid->multiRsp = true;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400808 if (mid->resp_buf) {
809 /* merge response - fix up 1st*/
Jeff Laytonffc00e22011-10-19 15:29:13 -0400810 malformed = coalesce_t2(buf, mid->resp_buf);
811 if (malformed > 0)
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400812 return;
Jeff Laytonffc00e22011-10-19 15:29:13 -0400813
Jeff Laytonea1f4502011-10-19 15:29:05 -0400814 /* All parts received or packet is malformed. */
815 mid->multiEnd = true;
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400816 return dequeue_mid(mid, malformed);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400817 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400818 if (!server->large_buf) {
Jeff Laytonea1f4502011-10-19 15:29:05 -0400819 /*FIXME: switch to already allocated largebuf?*/
820 cERROR(1, "1st trans2 resp needs bigbuf");
821 } else {
822 /* Have first buffer */
823 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400824 mid->large_buf = true;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400825 server->bigbuf = NULL;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400826 }
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400827 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400828 }
829 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400830 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400831 /* Was previous buf put in mpx struct for multi-rsp? */
832 if (!mid->multiRsp) {
833 /* smb buffer will be freed by user thread */
834 if (server->large_buf)
835 server->bigbuf = NULL;
836 else
837 server->smallbuf = NULL;
838 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400839 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400840}
841
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400842static void clean_demultiplex_info(struct TCP_Server_Info *server)
843{
844 int length;
845
846 /* take it off the list, if it's not already */
847 spin_lock(&cifs_tcp_ses_lock);
848 list_del_init(&server->tcp_ses_list);
849 spin_unlock(&cifs_tcp_ses_lock);
850
851 spin_lock(&GlobalMid_Lock);
852 server->tcpStatus = CifsExiting;
853 spin_unlock(&GlobalMid_Lock);
854 wake_up_all(&server->response_q);
855
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400856 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300857 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400858 if (server->credits <= 0)
859 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300860 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400861 /*
862 * Although there should not be any requests blocked on this queue it
863 * can not hurt to be paranoid and try to wake up requests that may
864 * haven been blocked when more than 50 at time were on the wire to the
865 * same server - they now will see the session is in exit state and get
866 * out of SendReceive.
867 */
868 wake_up_all(&server->request_q);
869 /* give those requests time to exit */
870 msleep(125);
871
872 if (server->ssocket) {
873 sock_release(server->ssocket);
874 server->ssocket = NULL;
875 }
876
877 if (!list_empty(&server->pending_mid_q)) {
878 struct list_head dispose_list;
879 struct mid_q_entry *mid_entry;
880 struct list_head *tmp, *tmp2;
881
882 INIT_LIST_HEAD(&dispose_list);
883 spin_lock(&GlobalMid_Lock);
884 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
885 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400886 cFYI(1, "Clearing mid 0x%llx", mid_entry->mid);
887 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400888 list_move(&mid_entry->qhead, &dispose_list);
889 }
890 spin_unlock(&GlobalMid_Lock);
891
892 /* now walk dispose list and issue callbacks */
893 list_for_each_safe(tmp, tmp2, &dispose_list) {
894 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400895 cFYI(1, "Callback mid 0x%llx", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400896 list_del_init(&mid_entry->qhead);
897 mid_entry->callback(mid_entry);
898 }
899 /* 1/8th of sec is more than enough time for them to exit */
900 msleep(125);
901 }
902
903 if (!list_empty(&server->pending_mid_q)) {
904 /*
905 * mpx threads have not exited yet give them at least the smb
906 * send timeout time for long ops.
907 *
908 * Due to delays on oplock break requests, we need to wait at
909 * least 45 seconds before giving up on a request getting a
910 * response and going ahead and killing cifsd.
911 */
912 cFYI(1, "Wait for exit from demultiplex thread");
913 msleep(46000);
914 /*
915 * If threads still have not exited they are probably never
916 * coming home not much else we can do but free the memory.
917 */
918 }
919
920 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400921 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400922 kfree(server);
923
924 length = atomic_dec_return(&tcpSesAllocCount);
925 if (length > 0)
926 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
927 GFP_KERNEL);
928}
929
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400930static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400931standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
932{
933 int length;
934 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400935 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400936
937 /* make sure this will fit in a large buffer */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400938 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
Jeff Laytone9097ab2011-10-19 15:29:40 -0400939 cERROR(1, "SMB response too long (%u bytes)",
940 pdu_length);
941 cifs_reconnect(server);
942 wake_up(&server->response_q);
943 return -EAGAIN;
944 }
945
946 /* switch to large buffer if too big for a small one */
947 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
948 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400949 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400950 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400951 }
952
953 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400954 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
955 pdu_length - HEADER_SIZE(server) + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400956 if (length < 0)
957 return length;
958 server->total_read += length;
959
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400960 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400961
962 /*
963 * We know that we received enough to get to the MID as we
964 * checked the pdu_length earlier. Now check to see
965 * if the rest of the header is OK. We borrow the length
966 * var for the rest of the loop to avoid a new stack var.
967 *
968 * 48 bytes is enough to display the header and a little bit
969 * into the payload for debugging purposes.
970 */
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +0400971 length = server->ops->check_message(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400972 if (length != 0)
973 cifs_dump_mem("Bad SMB: ", buf,
974 min_t(unsigned int, server->total_read, 48));
975
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500976 if (!mid)
977 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400978
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400979 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500980 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400981}
982
983static int
Al Viro7c97c202011-06-21 08:51:28 -0400984cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985{
986 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400987 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400988 unsigned int pdu_length;
989 char *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 struct task_struct *task_to_wake = NULL;
991 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 current->flags |= PF_MEMALLOC;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000994 cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400995
996 length = atomic_inc_return(&tcpSesAllocCount);
997 if (length > 1)
Steve French26f57362007-08-30 22:09:15 +0000998 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
999 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001001 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +00001002 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001003 if (try_to_freeze())
1004 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001005
Jeff Layton2a37ef92011-10-19 15:29:23 -04001006 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001007 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001008
Jeff Layton2a37ef92011-10-19 15:29:23 -04001009 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001010 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001011 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001012
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001013 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001014 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001015 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001016 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001017
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001018 /*
1019 * The right amount was read from socket - 4 bytes,
1020 * so we can now interpret the length field.
1021 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001022 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001023
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001024 cFYI(1, "RFC1002 header 0x%x", pdu_length);
1025 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001026 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001027
Jeff Layton89482a52011-10-19 15:28:57 -04001028 /* make sure we have enough to get to the MID */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001029 if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
Jeff Layton89482a52011-10-19 15:28:57 -04001030 cERROR(1, "SMB response too short (%u bytes)",
1031 pdu_length);
1032 cifs_reconnect(server);
1033 wake_up(&server->response_q);
1034 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001035 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001036
Jeff Layton89482a52011-10-19 15:28:57 -04001037 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001038 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001039 HEADER_SIZE(server) - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -04001040 if (length < 0)
1041 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001042 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001043
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +04001044 mid_entry = server->ops->find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001045
Jeff Layton44d22d82011-10-19 15:29:49 -04001046 if (!mid_entry || !mid_entry->receive)
1047 length = standard_receive3(server, mid_entry);
1048 else
1049 length = mid_entry->receive(server, mid_entry);
1050
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001051 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -07001052 continue;
1053
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001054 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001055 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001056
Steve Frenchfda35942011-01-20 18:06:34 +00001057 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -05001058 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -04001059 if (!mid_entry->multiRsp || mid_entry->multiEnd)
1060 mid_entry->callback(mid_entry);
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +04001061 } else if (!server->ops->is_oplock_break(buf, server)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001062 cERROR(1, "No task to wake, unknown frame received! "
Jeff Layton80975312011-01-11 07:24:02 -05001063 "NumMids %d", atomic_read(&midCount));
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001064 cifs_dump_mem("Received Data is: ", buf,
1065 HEADER_SIZE(server));
Steve French39798772006-05-31 22:40:51 +00001066#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovsky8aa26f32012-05-17 13:25:35 +04001067 server->ops->dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +00001068 cifs_dump_mids(server);
1069#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +00001070
Steve Frenche4eb2952005-04-28 22:41:09 -07001071 }
1072 } /* end while !EXITING */
1073
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001074 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001075 cifs_buf_release(server->bigbuf);
1076 if (server->smallbuf) /* no sense logging a debug message if NULL */
1077 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001079 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001080 clean_demultiplex_info(server);
Steve French50c2f752007-07-13 00:33:32 +00001081
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001082 /* if server->tsk was NULL then wait for a signal before exiting */
1083 if (!task_to_wake) {
1084 set_current_state(TASK_INTERRUPTIBLE);
1085 while (!signal_pending(current)) {
1086 schedule();
1087 set_current_state(TASK_INTERRUPTIBLE);
1088 }
1089 set_current_state(TASK_RUNNING);
1090 }
1091
Jeff Layton0468a2c2008-12-01 07:09:35 -05001092 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093}
1094
Jeff Laytonc359cf32007-11-16 22:22:06 +00001095/* extract the host portion of the UNC string */
1096static char *
1097extract_hostname(const char *unc)
1098{
1099 const char *src;
1100 char *dst, *delim;
1101 unsigned int len;
1102
1103 /* skip double chars at beginning of string */
1104 /* BB: check validity of these bytes? */
1105 src = unc + 2;
1106
1107 /* delimiter between hostname and sharename is always '\\' now */
1108 delim = strchr(src, '\\');
1109 if (!delim)
1110 return ERR_PTR(-EINVAL);
1111
1112 len = delim - src;
1113 dst = kmalloc((len + 1), GFP_KERNEL);
1114 if (dst == NULL)
1115 return ERR_PTR(-ENOMEM);
1116
1117 memcpy(dst, src, len);
1118 dst[len] = '\0';
1119
1120 return dst;
1121}
1122
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001123static int get_option_ul(substring_t args[], unsigned long *option)
1124{
1125 int rc;
1126 char *string;
1127
1128 string = match_strdup(args);
1129 if (string == NULL)
1130 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001131 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001132 kfree(string);
1133
1134 return rc;
1135}
1136
1137
1138static int cifs_parse_security_flavors(char *value,
1139 struct smb_vol *vol)
1140{
1141
1142 substring_t args[MAX_OPT_ARGS];
1143
1144 switch (match_token(value, cifs_secflavor_tokens, args)) {
1145 case Opt_sec_krb5:
1146 vol->secFlg |= CIFSSEC_MAY_KRB5;
1147 break;
1148 case Opt_sec_krb5i:
1149 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
1150 break;
1151 case Opt_sec_krb5p:
1152 /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
1153 cERROR(1, "Krb5 cifs privacy not supported");
1154 break;
1155 case Opt_sec_ntlmssp:
1156 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1157 break;
1158 case Opt_sec_ntlmsspi:
1159 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
1160 break;
1161 case Opt_ntlm:
1162 /* ntlm is default so can be turned off too */
1163 vol->secFlg |= CIFSSEC_MAY_NTLM;
1164 break;
1165 case Opt_sec_ntlmi:
1166 vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
1167 break;
1168 case Opt_sec_nontlm:
1169 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1170 break;
1171 case Opt_sec_ntlmv2i:
1172 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
1173 break;
1174#ifdef CONFIG_CIFS_WEAK_PW_HASH
1175 case Opt_sec_lanman:
1176 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1177 break;
1178#endif
1179 case Opt_sec_none:
1180 vol->nullauth = 1;
1181 break;
1182 default:
1183 cERROR(1, "bad security option: %s", value);
1184 return 1;
1185 }
1186
1187 return 0;
1188}
1189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001191cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1192{
1193 substring_t args[MAX_OPT_ARGS];
1194
1195 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1196 case Opt_cache_loose:
1197 vol->direct_io = false;
1198 vol->strict_io = false;
1199 break;
1200 case Opt_cache_strict:
1201 vol->direct_io = false;
1202 vol->strict_io = true;
1203 break;
1204 case Opt_cache_none:
1205 vol->direct_io = true;
1206 vol->strict_io = false;
1207 break;
1208 default:
1209 cERROR(1, "bad cache= option: %s", value);
1210 return 1;
1211 }
1212 return 0;
1213}
1214
1215static int
Jeff Layton23db65f2012-05-15 12:20:51 -04001216cifs_parse_smb_version(char *value, struct smb_vol *vol)
1217{
1218 substring_t args[MAX_OPT_ARGS];
1219
1220 switch (match_token(value, cifs_smb_version_tokens, args)) {
1221 case Smb_1:
1222 vol->ops = &smb1_operations;
1223 vol->vals = &smb1_values;
1224 break;
Steve French1080ef72011-02-24 18:07:19 +00001225#ifdef CONFIG_CIFS_SMB2
1226 case Smb_21:
1227 vol->ops = &smb21_operations;
1228 vol->vals = &smb21_values;
1229 break;
1230#endif
Jeff Layton23db65f2012-05-15 12:20:51 -04001231 default:
1232 cERROR(1, "Unknown vers= option specified: %s", value);
1233 return 1;
1234 }
1235 return 0;
1236}
1237
1238static int
Sean Finneyb9468452011-04-11 13:19:32 +00001239cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001240 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001242 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001243 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 unsigned int temp_len, i, j;
1245 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001246 short int override_uid = -1;
1247 short int override_gid = -1;
1248 bool uid_specified = false;
1249 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001250 bool sloppy = false;
1251 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001252 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001253 char *string = NULL;
1254 char *tmp_end, *value;
1255 char delim;
Jeff Layton296838b2012-05-16 07:53:01 -04001256 bool cache_specified = false;
1257 static bool cache_warned = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
1259 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001260 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001261 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
Jeff Layton88463992010-11-22 15:31:03 -05001263 /*
1264 * does not have to be perfect mapping since field is
1265 * informational, only used for servers that do not support
1266 * port 445 and it can be overridden at mount time
1267 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001268 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1269 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001270 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1271
Jeff Layton1397f2e2011-01-07 11:30:28 -05001272 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001273 /* null target name indicates to use *SMBSERVR default called name
1274 if we end up sending RFC1001 session initialize */
1275 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001276 vol->cred_uid = current_uid();
1277 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001278 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001279
1280 /* default to only allowing write access to owner of the mount */
1281 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
1283 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001284 /* default is always to request posix paths. */
1285 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001286 /* default to using server inode numbers where available */
1287 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001288
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301289 vol->actimeo = CIFS_DEF_ACTIMEO;
1290
Jeff Layton23db65f2012-05-15 12:20:51 -04001291 /* FIXME: add autonegotiation -- for now, SMB1 is default */
1292 vol->ops = &smb1_operations;
1293 vol->vals = &smb1_values;
1294
Sean Finneyb9468452011-04-11 13:19:32 +00001295 if (!mountdata)
1296 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Sean Finneyb9468452011-04-11 13:19:32 +00001298 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1299 if (!mountdata_copy)
1300 goto cifs_parse_mount_err;
1301
1302 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001303 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001304
Steve French50c2f752007-07-13 00:33:32 +00001305 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001306 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 separator[0] = options[4];
1308 options += 5;
1309 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001310 cFYI(1, "Null separator not allowed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 }
1312 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001313 vol->backupuid_specified = false; /* no backup intent for a user */
1314 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001315
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001317 substring_t args[MAX_OPT_ARGS];
1318 unsigned long option;
1319 int token;
1320
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 if (!*data)
1322 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001324 token = match_token(data, cifs_mount_option_tokens, args);
1325
1326 switch (token) {
1327
1328 /* Ingnore the following */
1329 case Opt_ignore:
1330 break;
1331
1332 /* Boolean values */
1333 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001335 break;
1336 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001338 break;
1339 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001340 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001341 break;
1342 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001343 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001344 break;
1345 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001346 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001347 break;
1348 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001349 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001350 break;
1351 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001353 break;
1354 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001356 break;
1357 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001359 break;
1360 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362 break;
1363 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001364 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001365 break;
1366 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001367 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 break;
1369 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001370 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371 break;
1372 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001373 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001374 break;
1375 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001376 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001377 break;
1378 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001379 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001380 break;
1381 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001382 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 break;
1384 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001385 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001386 break;
1387 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001388 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001389 break;
1390 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001391 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 break;
1393 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001394 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001395 /*
1396 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001397 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001398 * local vfs will do advisory
1399 */
Steve French50c2f752007-07-13 00:33:32 +00001400 if (vol->file_mode ==
1401 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001402 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001403 break;
1404 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001405 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001406 break;
1407 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001409 break;
1410 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001412 break;
1413 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001414 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001417 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
1425 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 break;
1428 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001432 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001435 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001439 break;
1440 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
1443 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001444 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001447 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001450 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 break;
1452 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001454 break;
1455 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001457 break;
1458 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001459 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 break;
1461 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001462 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001463 break;
1464 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001465 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001466 * is a per tree connection (mount) not a per socket
1467 * or per-smb connection option in the protocol
1468 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1469 */
Steve French95b1cb92008-05-15 16:44:38 +00001470 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001471 break;
1472 case Opt_direct:
Jeff Layton296838b2012-05-16 07:53:01 -04001473 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001474 vol->direct_io = true;
1475 vol->strict_io = false;
Jeff Layton09983b22012-05-16 07:53:00 -04001476 cERROR(1, "The \"directio\" option will be removed in "
1477 "3.7. Please switch to the \"cache=none\" "
1478 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001479 break;
1480 case Opt_strictcache:
Jeff Layton296838b2012-05-16 07:53:01 -04001481 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001482 vol->direct_io = false;
1483 vol->strict_io = true;
Jeff Layton09983b22012-05-16 07:53:00 -04001484 cERROR(1, "The \"strictcache\" option will be removed "
1485 "in 3.7. Please switch to the \"cache=strict\" "
1486 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001487 break;
1488 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001489 printk(KERN_WARNING "CIFS: Mount option noac not "
1490 "supported. Instead set "
1491 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001492 break;
1493 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301494#ifndef CONFIG_CIFS_FSCACHE
Jeff Layton83fb0862011-06-08 07:35:24 -04001495 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301496 "kernel config option set");
Sean Finneyb9468452011-04-11 13:19:32 +00001497 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301498#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301499 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001500 break;
1501 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001502 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001503 break;
1504 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001505 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001506 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001507 case Opt_sloppy:
1508 sloppy = true;
1509 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001510
1511 /* Numeric Values */
1512 case Opt_backupuid:
1513 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001514 cERROR(1, "%s: Invalid backupuid value",
1515 __func__);
1516 goto cifs_parse_mount_err;
1517 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001518 vol->backupuid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001519 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001520 break;
1521 case Opt_backupgid:
1522 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001523 cERROR(1, "%s: Invalid backupgid value",
1524 __func__);
1525 goto cifs_parse_mount_err;
1526 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001527 vol->backupgid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001528 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001529 break;
1530 case Opt_uid:
1531 if (get_option_ul(args, &option)) {
1532 cERROR(1, "%s: Invalid uid value",
1533 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001534 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001536 vol->linux_uid = option;
1537 uid_specified = true;
1538 break;
1539 case Opt_cruid:
1540 if (get_option_ul(args, &option)) {
1541 cERROR(1, "%s: Invalid cruid value",
1542 __func__);
1543 goto cifs_parse_mount_err;
1544 }
1545 vol->cred_uid = option;
1546 break;
1547 case Opt_gid:
1548 if (get_option_ul(args, &option)) {
1549 cERROR(1, "%s: Invalid gid value",
1550 __func__);
1551 goto cifs_parse_mount_err;
1552 }
1553 vol->linux_gid = option;
1554 gid_specified = true;
1555 break;
1556 case Opt_file_mode:
1557 if (get_option_ul(args, &option)) {
1558 cERROR(1, "%s: Invalid file_mode value",
1559 __func__);
1560 goto cifs_parse_mount_err;
1561 }
1562 vol->file_mode = option;
1563 break;
1564 case Opt_dirmode:
1565 if (get_option_ul(args, &option)) {
1566 cERROR(1, "%s: Invalid dir_mode value",
1567 __func__);
1568 goto cifs_parse_mount_err;
1569 }
1570 vol->dir_mode = option;
1571 break;
1572 case Opt_port:
1573 if (get_option_ul(args, &option)) {
1574 cERROR(1, "%s: Invalid port value",
1575 __func__);
1576 goto cifs_parse_mount_err;
1577 }
1578 vol->port = option;
1579 break;
1580 case Opt_rsize:
1581 if (get_option_ul(args, &option)) {
1582 cERROR(1, "%s: Invalid rsize value",
1583 __func__);
1584 goto cifs_parse_mount_err;
1585 }
1586 vol->rsize = option;
1587 break;
1588 case Opt_wsize:
1589 if (get_option_ul(args, &option)) {
1590 cERROR(1, "%s: Invalid wsize value",
1591 __func__);
1592 goto cifs_parse_mount_err;
1593 }
1594 vol->wsize = option;
1595 break;
1596 case Opt_actimeo:
1597 if (get_option_ul(args, &option)) {
1598 cERROR(1, "%s: Invalid actimeo value",
1599 __func__);
1600 goto cifs_parse_mount_err;
1601 }
1602 vol->actimeo = HZ * option;
1603 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1604 cERROR(1, "CIFS: attribute cache"
1605 "timeout too large");
1606 goto cifs_parse_mount_err;
1607 }
1608 break;
1609
1610 /* String Arguments */
1611
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001612 case Opt_blank_user:
1613 /* null user, ie. anonymous authentication */
1614 vol->nullauth = 1;
1615 vol->username = NULL;
1616 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001617 case Opt_user:
1618 string = match_strdup(args);
1619 if (string == NULL)
1620 goto out_nomem;
1621
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001622 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001623 MAX_USERNAME_SIZE) {
1624 printk(KERN_WARNING "CIFS: username too long\n");
1625 goto cifs_parse_mount_err;
1626 }
1627 vol->username = kstrdup(string, GFP_KERNEL);
1628 if (!vol->username) {
1629 printk(KERN_WARNING "CIFS: no memory "
1630 "for username\n");
1631 goto cifs_parse_mount_err;
1632 }
1633 break;
1634 case Opt_blank_pass:
1635 vol->password = NULL;
1636 break;
1637 case Opt_pass:
1638 /* passwords have to be handled differently
1639 * to allow the character used for deliminator
1640 * to be passed within them
1641 */
1642
1643 /* Obtain the value string */
1644 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001645 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001646
1647 /* Set tmp_end to end of the string */
1648 tmp_end = (char *) value + strlen(value);
1649
1650 /* Check if following character is the deliminator
1651 * If yes, we have encountered a double deliminator
1652 * reset the NULL character to the deliminator
1653 */
1654 if (tmp_end < end && tmp_end[1] == delim)
1655 tmp_end[0] = delim;
1656
1657 /* Keep iterating until we get to a single deliminator
1658 * OR the end
1659 */
1660 while ((tmp_end = strchr(tmp_end, delim)) != NULL &&
1661 (tmp_end[1] == delim)) {
1662 tmp_end = (char *) &tmp_end[2];
1663 }
1664
1665 /* Reset var options to point to next element */
1666 if (tmp_end) {
1667 tmp_end[0] = '\0';
1668 options = (char *) &tmp_end[1];
1669 } else
1670 /* Reached the end of the mount option string */
1671 options = end;
1672
1673 /* Now build new password string */
1674 temp_len = strlen(value);
1675 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1676 if (vol->password == NULL) {
1677 printk(KERN_WARNING "CIFS: no memory "
1678 "for password\n");
1679 goto cifs_parse_mount_err;
1680 }
1681
1682 for (i = 0, j = 0; i < temp_len; i++, j++) {
1683 vol->password[j] = value[i];
1684 if ((value[i] == delim) &&
1685 value[i+1] == delim)
1686 /* skip the second deliminator */
1687 i++;
1688 }
1689 vol->password[j] = '\0';
1690 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001691 case Opt_blank_ip:
1692 vol->UNCip = NULL;
1693 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001694 case Opt_ip:
1695 string = match_strdup(args);
1696 if (string == NULL)
1697 goto out_nomem;
1698
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001699 if (strnlen(string, INET6_ADDRSTRLEN) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001700 INET6_ADDRSTRLEN) {
1701 printk(KERN_WARNING "CIFS: ip address "
1702 "too long\n");
1703 goto cifs_parse_mount_err;
1704 }
1705 vol->UNCip = kstrdup(string, GFP_KERNEL);
1706 if (!vol->UNCip) {
1707 printk(KERN_WARNING "CIFS: no memory "
1708 "for UNC IP\n");
1709 goto cifs_parse_mount_err;
1710 }
1711 break;
1712 case Opt_unc:
1713 string = match_strdup(args);
1714 if (string == NULL)
1715 goto out_nomem;
1716
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001717 temp_len = strnlen(string, 300);
1718 if (temp_len == 300) {
1719 printk(KERN_WARNING "CIFS: UNC name too long\n");
1720 goto cifs_parse_mount_err;
1721 }
1722
Sachin Prabhue4b41fb2012-04-04 01:58:56 +01001723 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1724 if (vol->UNC == NULL) {
1725 printk(KERN_WARNING "CIFS: no memory for UNC\n");
1726 goto cifs_parse_mount_err;
1727 }
1728 strcpy(vol->UNC, string);
1729
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001730 if (strncmp(string, "//", 2) == 0) {
1731 vol->UNC[0] = '\\';
1732 vol->UNC[1] = '\\';
1733 } else if (strncmp(string, "\\\\", 2) != 0) {
1734 printk(KERN_WARNING "CIFS: UNC Path does not "
1735 "begin with // or \\\\\n");
1736 goto cifs_parse_mount_err;
1737 }
1738
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001739 break;
1740 case Opt_domain:
1741 string = match_strdup(args);
1742 if (string == NULL)
1743 goto out_nomem;
1744
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001745 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001746 printk(KERN_WARNING "CIFS: domain name too"
1747 " long\n");
1748 goto cifs_parse_mount_err;
1749 }
1750
1751 vol->domainname = kstrdup(string, GFP_KERNEL);
1752 if (!vol->domainname) {
1753 printk(KERN_WARNING "CIFS: no memory "
1754 "for domainname\n");
1755 goto cifs_parse_mount_err;
1756 }
1757 cFYI(1, "Domain name set");
1758 break;
1759 case Opt_srcaddr:
1760 string = match_strdup(args);
1761 if (string == NULL)
1762 goto out_nomem;
1763
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001764 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001765 (struct sockaddr *)&vol->srcaddr,
1766 string, strlen(string))) {
1767 printk(KERN_WARNING "CIFS: Could not parse"
1768 " srcaddr: %s\n", string);
1769 goto cifs_parse_mount_err;
1770 }
1771 break;
1772 case Opt_prefixpath:
1773 string = match_strdup(args);
1774 if (string == NULL)
1775 goto out_nomem;
1776
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001777 temp_len = strnlen(string, 1024);
1778 if (string[0] != '/')
1779 temp_len++; /* missing leading slash */
1780 if (temp_len > 1024) {
1781 printk(KERN_WARNING "CIFS: prefix too long\n");
1782 goto cifs_parse_mount_err;
1783 }
1784
1785 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1786 if (vol->prepath == NULL) {
1787 printk(KERN_WARNING "CIFS: no memory "
1788 "for path prefix\n");
1789 goto cifs_parse_mount_err;
1790 }
1791
1792 if (string[0] != '/') {
1793 vol->prepath[0] = '/';
1794 strcpy(vol->prepath+1, string);
1795 } else
1796 strcpy(vol->prepath, string);
1797
1798 break;
1799 case Opt_iocharset:
1800 string = match_strdup(args);
1801 if (string == NULL)
1802 goto out_nomem;
1803
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001804 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001805 printk(KERN_WARNING "CIFS: iocharset name "
1806 "too long.\n");
1807 goto cifs_parse_mount_err;
1808 }
1809
1810 if (strnicmp(string, "default", 7) != 0) {
1811 vol->iocharset = kstrdup(string,
1812 GFP_KERNEL);
1813 if (!vol->iocharset) {
1814 printk(KERN_WARNING "CIFS: no memory"
1815 "for charset\n");
1816 goto cifs_parse_mount_err;
1817 }
1818 }
1819 /* if iocharset not set then load_nls_default
1820 * is used by caller
1821 */
1822 cFYI(1, "iocharset set to %s", string);
1823 break;
1824 case Opt_sockopt:
1825 string = match_strdup(args);
1826 if (string == NULL)
1827 goto out_nomem;
1828
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001829 if (strnicmp(string, "TCP_NODELAY", 11) == 0)
1830 vol->sockopt_tcp_nodelay = 1;
1831 break;
1832 case Opt_netbiosname:
1833 string = match_strdup(args);
1834 if (string == NULL)
1835 goto out_nomem;
1836
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001837 memset(vol->source_rfc1001_name, 0x20,
1838 RFC1001_NAME_LEN);
1839 /*
1840 * FIXME: are there cases in which a comma can
1841 * be valid in workstation netbios name (and
1842 * need special handling)?
1843 */
1844 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1845 /* don't ucase netbiosname for user */
1846 if (string[i] == 0)
1847 break;
1848 vol->source_rfc1001_name[i] = string[i];
1849 }
1850 /* The string has 16th byte zero still from
1851 * set at top of the function
1852 */
1853 if (i == RFC1001_NAME_LEN && string[i] != 0)
1854 printk(KERN_WARNING "CIFS: netbiosname"
1855 " longer than 15 truncated.\n");
1856
1857 break;
1858 case Opt_servern:
1859 /* servernetbiosname specified override *SMBSERVER */
1860 string = match_strdup(args);
1861 if (string == NULL)
1862 goto out_nomem;
1863
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001864 /* last byte, type, is 0x20 for servr type */
1865 memset(vol->target_rfc1001_name, 0x20,
1866 RFC1001_NAME_LEN_WITH_NULL);
1867
1868 /* BB are there cases in which a comma can be
1869 valid in this workstation netbios name
1870 (and need special handling)? */
1871
1872 /* user or mount helper must uppercase the
1873 netbios name */
1874 for (i = 0; i < 15; i++) {
1875 if (string[i] == 0)
1876 break;
1877 vol->target_rfc1001_name[i] = string[i];
1878 }
1879 /* The string has 16th byte zero still from
1880 set at top of the function */
1881 if (i == RFC1001_NAME_LEN && string[i] != 0)
1882 printk(KERN_WARNING "CIFS: server net"
1883 "biosname longer than 15 truncated.\n");
1884 break;
1885 case Opt_ver:
1886 string = match_strdup(args);
1887 if (string == NULL)
1888 goto out_nomem;
1889
Jeff Layton5249af32012-05-15 12:04:03 -04001890 if (strnicmp(string, "1", 1) == 0) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001891 /* This is the default */
1892 break;
1893 }
1894 /* For all other value, error */
1895 printk(KERN_WARNING "CIFS: Invalid version"
1896 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001897 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04001898 case Opt_vers:
1899 string = match_strdup(args);
1900 if (string == NULL)
1901 goto out_nomem;
1902
1903 if (cifs_parse_smb_version(string, vol) != 0)
1904 goto cifs_parse_mount_err;
1905 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001906 case Opt_sec:
1907 string = match_strdup(args);
1908 if (string == NULL)
1909 goto out_nomem;
1910
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911 if (cifs_parse_security_flavors(string, vol) != 0)
1912 goto cifs_parse_mount_err;
1913 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001914 case Opt_cache:
Jeff Layton296838b2012-05-16 07:53:01 -04001915 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001916 string = match_strdup(args);
1917 if (string == NULL)
1918 goto out_nomem;
1919
1920 if (cifs_parse_cache_flavor(string, vol) != 0)
1921 goto cifs_parse_mount_err;
1922 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001923 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001924 /*
1925 * An option we don't recognize. Save it off for later
1926 * if we haven't already found one
1927 */
1928 if (!invalid)
1929 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001930 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001932 /* Free up any allocated string */
1933 kfree(string);
1934 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001936
Jeff Laytond8162552012-03-23 14:40:56 -04001937 if (!sloppy && invalid) {
1938 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1939 goto cifs_parse_mount_err;
1940 }
1941
Jeff Layton8a8798a2012-01-17 16:09:15 -05001942#ifndef CONFIG_KEYS
1943 /* Muliuser mounts require CONFIG_KEYS support */
1944 if (vol->multiuser) {
1945 cERROR(1, "Multiuser mounts require kernels with "
1946 "CONFIG_KEYS enabled.");
Sean Finneyb9468452011-04-11 13:19:32 +00001947 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001948 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001949#endif
Jeff Layton0eb8a132010-10-06 19:51:12 -04001950
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001951 if (vol->UNCip == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 vol->UNCip = &vol->UNC[2];
1953
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001954 if (uid_specified)
1955 vol->override_uid = override_uid;
1956 else if (override_uid == 1)
1957 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1958 "specified with no uid= option.\n");
1959
1960 if (gid_specified)
1961 vol->override_gid = override_gid;
1962 else if (override_gid == 1)
1963 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1964 "specified with no gid= option.\n");
1965
Jeff Layton296838b2012-05-16 07:53:01 -04001966 /* FIXME: remove this block in 3.7 */
1967 if (!cache_specified && !cache_warned) {
1968 cache_warned = true;
1969 printk(KERN_NOTICE "CIFS: no cache= option specified, using "
1970 "\"cache=loose\". This default will change "
1971 "to \"cache=strict\" in 3.7.\n");
1972 }
1973
Sean Finneyb9468452011-04-11 13:19:32 +00001974 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001976
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001977out_nomem:
1978 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001979cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001980 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001981 kfree(mountdata_copy);
1982 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983}
1984
Ben Greear3eb9a882010-09-01 17:06:02 -07001985/** Returns true if srcaddr isn't specified and rhs isn't
1986 * specified, or if srcaddr is specified and
1987 * matches the IP address of the rhs argument.
1988 */
Jeff Layton45151482010-07-06 20:43:02 -04001989static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001990srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1991{
1992 switch (srcaddr->sa_family) {
1993 case AF_UNSPEC:
1994 return (rhs->sa_family == AF_UNSPEC);
1995 case AF_INET: {
1996 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1997 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1998 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1999 }
2000 case AF_INET6: {
2001 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
2002 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
2003 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2004 }
2005 default:
2006 WARN_ON(1);
2007 return false; /* don't expect to be here */
2008 }
2009}
2010
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002011/*
2012 * If no port is specified in addr structure, we try to match with 445 port
2013 * and if it fails - with 139 ports. It should be called only if address
2014 * families of server and addr are equal.
2015 */
2016static bool
2017match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2018{
Steve French6da97912011-03-13 18:55:55 +00002019 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002020
2021 switch (addr->sa_family) {
2022 case AF_INET:
2023 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2024 port = ((struct sockaddr_in *) addr)->sin_port;
2025 break;
2026 case AF_INET6:
2027 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2028 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2029 break;
2030 default:
2031 WARN_ON(1);
2032 return false;
2033 }
2034
2035 if (!port) {
2036 port = htons(CIFS_PORT);
2037 if (port == *sport)
2038 return true;
2039
2040 port = htons(RFC1001_PORT);
2041 }
2042
2043 return port == *sport;
2044}
Ben Greear3eb9a882010-09-01 17:06:02 -07002045
2046static bool
2047match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2048 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049{
Jeff Layton45151482010-07-06 20:43:02 -04002050 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002051 case AF_INET: {
2052 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2053 struct sockaddr_in *srv_addr4 =
2054 (struct sockaddr_in *)&server->dstaddr;
2055
2056 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002057 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002058 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002059 }
2060 case AF_INET6: {
2061 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2062 struct sockaddr_in6 *srv_addr6 =
2063 (struct sockaddr_in6 *)&server->dstaddr;
2064
Jeff Layton45151482010-07-06 20:43:02 -04002065 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002066 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002067 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002068 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002069 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002070 break;
2071 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002072 default:
2073 WARN_ON(1);
2074 return false; /* don't expect to be here */
2075 }
Jeff Layton45151482010-07-06 20:43:02 -04002076
Ben Greear3eb9a882010-09-01 17:06:02 -07002077 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2078 return false;
2079
Jeff Layton45151482010-07-06 20:43:02 -04002080 return true;
2081}
2082
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002083static bool
2084match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2085{
2086 unsigned int secFlags;
2087
2088 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
2089 secFlags = vol->secFlg;
2090 else
2091 secFlags = global_secflags | vol->secFlg;
2092
2093 switch (server->secType) {
2094 case LANMAN:
2095 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
2096 return false;
2097 break;
2098 case NTLMv2:
2099 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
2100 return false;
2101 break;
2102 case NTLM:
2103 if (!(secFlags & CIFSSEC_MAY_NTLM))
2104 return false;
2105 break;
2106 case Kerberos:
2107 if (!(secFlags & CIFSSEC_MAY_KRB5))
2108 return false;
2109 break;
2110 case RawNTLMSSP:
2111 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2112 return false;
2113 break;
2114 default:
2115 /* shouldn't happen */
2116 return false;
2117 }
2118
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002119 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002120 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002121 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002122 return false;
2123 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002124 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002125 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2126 return false;
2127
2128 return true;
2129}
2130
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002131static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
2132 struct smb_vol *vol)
2133{
Jeff Layton23db65f2012-05-15 12:20:51 -04002134 if ((server->vals != vol->vals) || (server->ops != vol->ops))
2135 return 0;
2136
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002137 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2138 return 0;
2139
2140 if (!match_address(server, addr,
2141 (struct sockaddr *)&vol->srcaddr))
2142 return 0;
2143
2144 if (!match_port(server, addr))
2145 return 0;
2146
2147 if (!match_security(server, vol))
2148 return 0;
2149
2150 return 1;
2151}
2152
Jeff Layton45151482010-07-06 20:43:02 -04002153static struct TCP_Server_Info *
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002154cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002155{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002156 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302158 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002159 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002160 if (!match_server(server, addr, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002161 continue;
2162
Jeff Laytone7ddee92008-11-14 13:44:38 -05002163 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302164 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002165 cFYI(1, "Existing tcp session with server found");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002166 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302168 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 return NULL;
2170}
2171
Jeff Layton14fbf502008-11-14 13:53:46 -05002172static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002173cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002175 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302177 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002178 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302179 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002180 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002182
Rob Landleyf1d0c992011-01-22 15:44:05 -06002183 put_net(cifs_net_ns(server));
2184
Jeff Laytone7ddee92008-11-14 13:44:38 -05002185 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302186 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002187
Jeff Laytonc74093b2011-01-11 07:24:23 -05002188 cancel_delayed_work_sync(&server->echo);
2189
Jeff Laytone7ddee92008-11-14 13:44:38 -05002190 spin_lock(&GlobalMid_Lock);
2191 server->tcpStatus = CifsExiting;
2192 spin_unlock(&GlobalMid_Lock);
2193
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002194 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302195 cifs_fscache_release_client_cookie(server);
2196
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002197 kfree(server->session_key.response);
2198 server->session_key.response = NULL;
2199 server->session_key.len = 0;
2200
Jeff Laytone7ddee92008-11-14 13:44:38 -05002201 task = xchg(&server->tsk, NULL);
2202 if (task)
2203 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204}
2205
Jeff Layton63c038c2008-12-01 18:41:46 -05002206static struct TCP_Server_Info *
2207cifs_get_tcp_session(struct smb_vol *volume_info)
2208{
2209 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002210 struct sockaddr_storage addr;
Jeff Layton63c038c2008-12-01 18:41:46 -05002211 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2212 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2213 int rc;
2214
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002215 memset(&addr, 0, sizeof(struct sockaddr_storage));
Jeff Layton63c038c2008-12-01 18:41:46 -05002216
Joe Perchesb6b38f72010-04-21 03:50:45 +00002217 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002218
Jeff Layton63c038c2008-12-01 18:41:46 -05002219 if (volume_info->UNCip && volume_info->UNC) {
Jeff Layton50d97162010-07-06 20:43:01 -04002220 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2221 volume_info->UNCip,
David Howells67b76262010-07-22 18:33:01 +01002222 strlen(volume_info->UNCip),
Jeff Layton50d97162010-07-06 20:43:01 -04002223 volume_info->port);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002224 if (!rc) {
Jeff Layton63c038c2008-12-01 18:41:46 -05002225 /* we failed translating address */
2226 rc = -EINVAL;
2227 goto out_err;
2228 }
Jeff Layton63c038c2008-12-01 18:41:46 -05002229 } else if (volume_info->UNCip) {
2230 /* BB using ip addr as tcp_ses name to connect to the
2231 DFS root below */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002232 cERROR(1, "Connecting to DFS root not implemented yet");
Jeff Layton63c038c2008-12-01 18:41:46 -05002233 rc = -EINVAL;
2234 goto out_err;
2235 } else /* which tcp_sess DFS root would we conect to */ {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002236 cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
2237 "unc=//192.168.1.100/public) specified");
Jeff Layton63c038c2008-12-01 18:41:46 -05002238 rc = -EINVAL;
2239 goto out_err;
2240 }
2241
2242 /* see if we already have a matching tcp_ses */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002243 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002244 if (tcp_ses)
2245 return tcp_ses;
2246
2247 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2248 if (!tcp_ses) {
2249 rc = -ENOMEM;
2250 goto out_err;
2251 }
2252
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002253 rc = cifs_crypto_shash_allocate(tcp_ses);
2254 if (rc) {
2255 cERROR(1, "could not setup hash structures rc %d", rc);
2256 goto out_err;
2257 }
2258
Jeff Layton23db65f2012-05-15 12:20:51 -04002259 tcp_ses->ops = volume_info->ops;
2260 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002261 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002262 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2263 if (IS_ERR(tcp_ses->hostname)) {
2264 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002265 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002266 }
2267
2268 tcp_ses->noblocksnd = volume_info->noblocksnd;
2269 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002270 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002271 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002272 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002273 init_waitqueue_head(&tcp_ses->response_q);
2274 init_waitqueue_head(&tcp_ses->request_q);
2275 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2276 mutex_init(&tcp_ses->srv_mutex);
2277 memcpy(tcp_ses->workstation_RFC1001_name,
2278 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2279 memcpy(tcp_ses->server_RFC1001_name,
2280 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002281 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002282 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002283 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002284 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002285 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2286 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002287 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton63c038c2008-12-01 18:41:46 -05002288
2289 /*
2290 * at this point we are the only ones with the pointer
2291 * to the struct since the kernel thread not created yet
2292 * no need to spinlock this init of tcpStatus or srv_count
2293 */
2294 tcp_ses->tcpStatus = CifsNew;
Ben Greear3eb9a882010-09-01 17:06:02 -07002295 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2296 sizeof(tcp_ses->srcaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002297 ++tcp_ses->srv_count;
2298
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002299 if (addr.ss_family == AF_INET6) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002300 cFYI(1, "attempting ipv6 connect");
Jeff Layton63c038c2008-12-01 18:41:46 -05002301 /* BB should we allow ipv6 on port 139? */
2302 /* other OS never observed in Wild doing 139 with v6 */
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002303 memcpy(&tcp_ses->dstaddr, sin_server6,
2304 sizeof(struct sockaddr_in6));
2305 } else
2306 memcpy(&tcp_ses->dstaddr, sin_server,
2307 sizeof(struct sockaddr_in));
2308
2309 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002310 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002311 cERROR(1, "Error connecting to socket. Aborting operation");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002312 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002313 }
2314
2315 /*
2316 * since we're in a cifs function already, we know that
2317 * this will succeed. No need for try_module_get().
2318 */
2319 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002320 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002321 tcp_ses, "cifsd");
2322 if (IS_ERR(tcp_ses->tsk)) {
2323 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002324 cERROR(1, "error %d create cifsd thread", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002325 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002326 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002327 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002328 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002329
2330 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302331 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002332 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302333 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002334
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302335 cifs_fscache_get_client_cookie(tcp_ses);
2336
Jeff Laytonc74093b2011-01-11 07:24:23 -05002337 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002338 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002339
Jeff Layton63c038c2008-12-01 18:41:46 -05002340 return tcp_ses;
2341
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002342out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002343 cifs_crypto_shash_release(tcp_ses);
2344
Rob Landleyf1d0c992011-01-22 15:44:05 -06002345 put_net(cifs_net_ns(tcp_ses));
2346
Jeff Layton63c038c2008-12-01 18:41:46 -05002347out_err:
2348 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002349 if (!IS_ERR(tcp_ses->hostname))
2350 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002351 if (tcp_ses->ssocket)
2352 sock_release(tcp_ses->ssocket);
2353 kfree(tcp_ses);
2354 }
2355 return ERR_PTR(rc);
2356}
2357
Steve French96daf2b2011-05-27 04:34:02 +00002358static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002359{
2360 switch (ses->server->secType) {
2361 case Kerberos:
2362 if (vol->cred_uid != ses->cred_uid)
2363 return 0;
2364 break;
2365 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002366 /* NULL username means anonymous session */
2367 if (ses->user_name == NULL) {
2368 if (!vol->nullauth)
2369 return 0;
2370 break;
2371 }
2372
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002373 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002374 if (strncmp(ses->user_name,
2375 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002376 MAX_USERNAME_SIZE))
2377 return 0;
2378 if (strlen(vol->username) != 0 &&
2379 ses->password != NULL &&
2380 strncmp(ses->password,
2381 vol->password ? vol->password : "",
2382 MAX_PASSWORD_SIZE))
2383 return 0;
2384 }
2385 return 1;
2386}
2387
Steve French96daf2b2011-05-27 04:34:02 +00002388static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002389cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390{
Steve French96daf2b2011-05-27 04:34:02 +00002391 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302393 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002394 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002395 if (!match_session(ses, vol))
2396 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002397 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302398 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002399 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302401 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 return NULL;
2403}
2404
Jeff Layton14fbf502008-11-14 13:53:46 -05002405static void
Steve French96daf2b2011-05-27 04:34:02 +00002406cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002407{
2408 int xid;
2409 struct TCP_Server_Info *server = ses->server;
2410
Jeff Layton36988c72010-04-24 07:57:43 -04002411 cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302412 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002413 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302414 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002415 return;
2416 }
2417
2418 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302419 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002420
2421 if (ses->status == CifsGood) {
2422 xid = GetXid();
2423 CIFSSMBLogoff(xid, ses);
2424 _FreeXid(xid);
2425 }
2426 sesInfoFree(ses);
2427 cifs_put_tcp_session(server);
2428}
2429
Jeff Layton8a8798a2012-01-17 16:09:15 -05002430#ifdef CONFIG_KEYS
2431
2432/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2433#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2434
2435/* Populate username and pw fields from keyring if possible */
2436static int
2437cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2438{
2439 int rc = 0;
2440 char *desc, *delim, *payload;
2441 ssize_t len;
2442 struct key *key;
2443 struct TCP_Server_Info *server = ses->server;
2444 struct sockaddr_in *sa;
2445 struct sockaddr_in6 *sa6;
2446 struct user_key_payload *upayload;
2447
2448 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2449 if (!desc)
2450 return -ENOMEM;
2451
2452 /* try to find an address key first */
2453 switch (server->dstaddr.ss_family) {
2454 case AF_INET:
2455 sa = (struct sockaddr_in *)&server->dstaddr;
2456 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2457 break;
2458 case AF_INET6:
2459 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2460 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2461 break;
2462 default:
2463 cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
2464 rc = -EINVAL;
2465 goto out_err;
2466 }
2467
2468 cFYI(1, "%s: desc=%s", __func__, desc);
2469 key = request_key(&key_type_logon, desc, "");
2470 if (IS_ERR(key)) {
2471 if (!ses->domainName) {
2472 cFYI(1, "domainName is NULL");
2473 rc = PTR_ERR(key);
2474 goto out_err;
2475 }
2476
2477 /* didn't work, try to find a domain key */
2478 sprintf(desc, "cifs:d:%s", ses->domainName);
2479 cFYI(1, "%s: desc=%s", __func__, desc);
2480 key = request_key(&key_type_logon, desc, "");
2481 if (IS_ERR(key)) {
2482 rc = PTR_ERR(key);
2483 goto out_err;
2484 }
2485 }
2486
2487 down_read(&key->sem);
2488 upayload = key->payload.data;
2489 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002490 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002491 goto out_key_put;
2492 }
2493
2494 /* find first : in payload */
2495 payload = (char *)upayload->data;
2496 delim = strnchr(payload, upayload->datalen, ':');
2497 cFYI(1, "payload=%s", payload);
2498 if (!delim) {
2499 cFYI(1, "Unable to find ':' in payload (datalen=%d)",
2500 upayload->datalen);
2501 rc = -EINVAL;
2502 goto out_key_put;
2503 }
2504
2505 len = delim - payload;
2506 if (len > MAX_USERNAME_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002507 cFYI(1, "Bad value from username search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002508 rc = -EINVAL;
2509 goto out_key_put;
2510 }
2511
2512 vol->username = kstrndup(payload, len, GFP_KERNEL);
2513 if (!vol->username) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002514 cFYI(1, "Unable to allocate %zd bytes for username", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002515 rc = -ENOMEM;
2516 goto out_key_put;
2517 }
2518 cFYI(1, "%s: username=%s", __func__, vol->username);
2519
2520 len = key->datalen - (len + 1);
2521 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002522 cFYI(1, "Bad len for password search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002523 rc = -EINVAL;
2524 kfree(vol->username);
2525 vol->username = NULL;
2526 goto out_key_put;
2527 }
2528
2529 ++delim;
2530 vol->password = kstrndup(delim, len, GFP_KERNEL);
2531 if (!vol->password) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002532 cFYI(1, "Unable to allocate %zd bytes for password", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002533 rc = -ENOMEM;
2534 kfree(vol->username);
2535 vol->username = NULL;
2536 goto out_key_put;
2537 }
2538
2539out_key_put:
2540 up_read(&key->sem);
2541 key_put(key);
2542out_err:
2543 kfree(desc);
2544 cFYI(1, "%s: returning %d", __func__, rc);
2545 return rc;
2546}
2547#else /* ! CONFIG_KEYS */
2548static inline int
2549cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2550 struct cifs_ses *ses __attribute__((unused)))
2551{
2552 return -ENOSYS;
2553}
2554#endif /* CONFIG_KEYS */
2555
Steve Frenchd9b94202011-04-12 01:24:57 +00002556static bool warned_on_ntlm; /* globals init to false automatically */
2557
Steve French96daf2b2011-05-27 04:34:02 +00002558static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002559cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2560{
2561 int rc = -ENOMEM, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002562 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002563 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2564 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002565
2566 xid = GetXid();
2567
Jeff Layton4ff67b72010-07-06 20:43:02 -04002568 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002569 if (ses) {
2570 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
2571
Jeff Layton36988c72010-04-24 07:57:43 -04002572 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002573 rc = cifs_negotiate_protocol(xid, ses);
2574 if (rc) {
2575 mutex_unlock(&ses->session_mutex);
2576 /* problem -- put our ses reference */
2577 cifs_put_smb_ses(ses);
2578 FreeXid(xid);
2579 return ERR_PTR(rc);
2580 }
Jeff Layton36988c72010-04-24 07:57:43 -04002581 if (ses->need_reconnect) {
2582 cFYI(1, "Session needs reconnect");
2583 rc = cifs_setup_session(xid, ses,
2584 volume_info->local_nls);
2585 if (rc) {
2586 mutex_unlock(&ses->session_mutex);
2587 /* problem -- put our reference */
2588 cifs_put_smb_ses(ses);
2589 FreeXid(xid);
2590 return ERR_PTR(rc);
2591 }
2592 }
2593 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002594
2595 /* existing SMB ses has a server reference already */
2596 cifs_put_tcp_session(server);
Jeff Layton36988c72010-04-24 07:57:43 -04002597 FreeXid(xid);
2598 return ses;
2599 }
2600
2601 cFYI(1, "Existing smb sess not found");
2602 ses = sesInfoAlloc();
2603 if (ses == NULL)
2604 goto get_ses_fail;
2605
2606 /* new SMB session uses our server ref */
2607 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002608 if (server->dstaddr.ss_family == AF_INET6)
2609 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002610 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002611 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002612
Steve French8727c8a2011-02-25 01:11:56 -06002613 if (volume_info->username) {
2614 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2615 if (!ses->user_name)
2616 goto get_ses_fail;
2617 }
Jeff Layton36988c72010-04-24 07:57:43 -04002618
2619 /* volume_info->password freed at unmount */
2620 if (volume_info->password) {
2621 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2622 if (!ses->password)
2623 goto get_ses_fail;
2624 }
2625 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002626 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2627 if (!ses->domainName)
2628 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002629 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002630 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002631 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002632
2633 /* ntlmv2 is much stronger than ntlm security, and has been broadly
2634 supported for many years, time to update default security mechanism */
2635 if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
2636 warned_on_ntlm = true;
2637 cERROR(1, "default security mechanism requested. The default "
2638 "security mechanism will be upgraded from ntlm to "
Steve French225de112012-01-03 23:08:24 -06002639 "ntlmv2 in kernel release 3.3");
Steve Frenchd9b94202011-04-12 01:24:57 +00002640 }
Jeff Layton36988c72010-04-24 07:57:43 -04002641 ses->overrideSecFlg = volume_info->secFlg;
2642
2643 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002644 rc = cifs_negotiate_protocol(xid, ses);
2645 if (!rc)
2646 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002647 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002648 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002649 goto get_ses_fail;
2650
2651 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302652 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002653 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302654 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002655
2656 FreeXid(xid);
2657 return ses;
2658
2659get_ses_fail:
2660 sesInfoFree(ses);
2661 FreeXid(xid);
2662 return ERR_PTR(rc);
2663}
2664
Steve French96daf2b2011-05-27 04:34:02 +00002665static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002666{
2667 if (tcon->tidStatus == CifsExiting)
2668 return 0;
2669 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2670 return 0;
2671 return 1;
2672}
2673
Steve French96daf2b2011-05-27 04:34:02 +00002674static struct cifs_tcon *
2675cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676{
2677 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002678 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302680 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002681 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002682 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002683 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002684 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002685 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302686 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 return tcon;
2688 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302689 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 return NULL;
2691}
2692
Jeff Laytonf1987b42008-11-15 11:12:47 -05002693static void
Steve French96daf2b2011-05-27 04:34:02 +00002694cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002695{
2696 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002697 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002698
Jeff Laytond00c28d2010-04-24 07:57:44 -04002699 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302700 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002701 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302702 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002703 return;
2704 }
2705
2706 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302707 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002708
2709 xid = GetXid();
2710 CIFSSMBTDis(xid, tcon);
2711 _FreeXid(xid);
2712
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302713 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002714 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002715 cifs_put_smb_ses(ses);
2716}
2717
Steve French96daf2b2011-05-27 04:34:02 +00002718static struct cifs_tcon *
2719cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002720{
2721 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002722 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002723
2724 tcon = cifs_find_tcon(ses, volume_info->UNC);
2725 if (tcon) {
2726 cFYI(1, "Found match on UNC path");
2727 /* existing tcon already has a reference */
2728 cifs_put_smb_ses(ses);
2729 if (tcon->seal != volume_info->seal)
2730 cERROR(1, "transport encryption setting "
2731 "conflicts with existing tid");
2732 return tcon;
2733 }
2734
2735 tcon = tconInfoAlloc();
2736 if (tcon == NULL) {
2737 rc = -ENOMEM;
2738 goto out_fail;
2739 }
2740
2741 tcon->ses = ses;
2742 if (volume_info->password) {
2743 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2744 if (!tcon->password) {
2745 rc = -ENOMEM;
2746 goto out_fail;
2747 }
2748 }
2749
2750 if (strchr(volume_info->UNC + 3, '\\') == NULL
2751 && strchr(volume_info->UNC + 3, '/') == NULL) {
2752 cERROR(1, "Missing share name");
2753 rc = -ENODEV;
2754 goto out_fail;
2755 }
2756
2757 /* BB Do we need to wrap session_mutex around
2758 * this TCon call and Unix SetFS as
2759 * we do on SessSetup and reconnect? */
2760 xid = GetXid();
2761 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
2762 FreeXid(xid);
2763 cFYI(1, "CIFS Tcon rc = %d", rc);
2764 if (rc)
2765 goto out_fail;
2766
2767 if (volume_info->nodfs) {
2768 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2769 cFYI(1, "DFS disabled (%d)", tcon->Flags);
2770 }
2771 tcon->seal = volume_info->seal;
2772 /* we can have only one retry value for a connection
2773 to a share so for resources mounted more than once
2774 to the same server share the last value passed in
2775 for the retry flag is used */
2776 tcon->retry = volume_info->retry;
2777 tcon->nocase = volume_info->nocase;
2778 tcon->local_lease = volume_info->local_lease;
2779
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302780 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002781 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302782 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002783
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302784 cifs_fscache_get_super_cookie(tcon);
2785
Jeff Laytond00c28d2010-04-24 07:57:44 -04002786 return tcon;
2787
2788out_fail:
2789 tconInfoFree(tcon);
2790 return ERR_PTR(rc);
2791}
2792
Jeff Layton9d002df2010-10-06 19:51:11 -04002793void
2794cifs_put_tlink(struct tcon_link *tlink)
2795{
2796 if (!tlink || IS_ERR(tlink))
2797 return;
2798
2799 if (!atomic_dec_and_test(&tlink->tl_count) ||
2800 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2801 tlink->tl_time = jiffies;
2802 return;
2803 }
2804
2805 if (!IS_ERR(tlink_tcon(tlink)))
2806 cifs_put_tcon(tlink_tcon(tlink));
2807 kfree(tlink);
2808 return;
2809}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002810
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002811static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002812cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2813{
2814 return cifs_sb->master_tlink;
2815}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002816
2817static int
2818compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2819{
2820 struct cifs_sb_info *old = CIFS_SB(sb);
2821 struct cifs_sb_info *new = mnt_data->cifs_sb;
2822
2823 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2824 return 0;
2825
2826 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2827 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2828 return 0;
2829
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002830 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002831 * We want to share sb only if we don't specify an r/wsize or
2832 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002833 */
2834 if (new->wsize && new->wsize < old->wsize)
2835 return 0;
2836
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002837 if (new->rsize && new->rsize < old->rsize)
2838 return 0;
2839
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002840 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2841 return 0;
2842
2843 if (old->mnt_file_mode != new->mnt_file_mode ||
2844 old->mnt_dir_mode != new->mnt_dir_mode)
2845 return 0;
2846
2847 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2848 return 0;
2849
2850 if (old->actimeo != new->actimeo)
2851 return 0;
2852
2853 return 1;
2854}
2855
2856int
2857cifs_match_super(struct super_block *sb, void *data)
2858{
2859 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2860 struct smb_vol *volume_info;
2861 struct cifs_sb_info *cifs_sb;
2862 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002863 struct cifs_ses *ses;
2864 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002865 struct tcon_link *tlink;
2866 struct sockaddr_storage addr;
2867 int rc = 0;
2868
2869 memset(&addr, 0, sizeof(struct sockaddr_storage));
2870
2871 spin_lock(&cifs_tcp_ses_lock);
2872 cifs_sb = CIFS_SB(sb);
2873 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2874 if (IS_ERR(tlink)) {
2875 spin_unlock(&cifs_tcp_ses_lock);
2876 return rc;
2877 }
2878 tcon = tlink_tcon(tlink);
2879 ses = tcon->ses;
2880 tcp_srv = ses->server;
2881
2882 volume_info = mnt_data->vol;
2883
2884 if (!volume_info->UNCip || !volume_info->UNC)
2885 goto out;
2886
2887 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2888 volume_info->UNCip,
2889 strlen(volume_info->UNCip),
2890 volume_info->port);
2891 if (!rc)
2892 goto out;
2893
2894 if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
2895 !match_session(ses, volume_info) ||
2896 !match_tcon(tcon, volume_info->UNC)) {
2897 rc = 0;
2898 goto out;
2899 }
2900
2901 rc = compare_mount_options(sb, mnt_data);
2902out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002903 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002904 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002905 return rc;
2906}
2907
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908int
Steve French96daf2b2011-05-27 04:34:02 +00002909get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
Steve French50c2f752007-07-13 00:33:32 +00002910 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
Steve French366781c2008-01-25 10:12:41 +00002911 struct dfs_info3_param **preferrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912{
2913 char *temp_unc;
2914 int rc = 0;
2915
2916 *pnum_referrals = 0;
Steve French366781c2008-01-25 10:12:41 +00002917 *preferrals = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918
2919 if (pSesInfo->ipc_tid == 0) {
2920 temp_unc = kmalloc(2 /* for slashes */ +
Steve French50c2f752007-07-13 00:33:32 +00002921 strnlen(pSesInfo->serverName,
2922 SERVER_NAME_LEN_WITH_NULL * 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 + 1 + 4 /* slash IPC$ */ + 2,
2924 GFP_KERNEL);
2925 if (temp_unc == NULL)
2926 return -ENOMEM;
2927 temp_unc[0] = '\\';
2928 temp_unc[1] = '\\';
2929 strcpy(temp_unc + 2, pSesInfo->serverName);
2930 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
2931 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002932 cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 kfree(temp_unc);
2934 }
2935 if (rc == 0)
Steve Frenchc2cf07d2008-05-15 06:20:02 +00002936 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
Steve French737b7582005-04-28 22:41:06 -07002937 pnum_referrals, nls_codepage, remap);
Steve French366781c2008-01-25 10:12:41 +00002938 /* BB map targetUNCs to dfs_info3 structures, here or
2939 in CIFSGetDFSRefer BB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940
2941 return rc;
2942}
2943
Jeff Layton09e50d52008-07-23 10:11:19 -04002944#ifdef CONFIG_DEBUG_LOCK_ALLOC
2945static struct lock_class_key cifs_key[2];
2946static struct lock_class_key cifs_slock_key[2];
2947
2948static inline void
2949cifs_reclassify_socket4(struct socket *sock)
2950{
2951 struct sock *sk = sock->sk;
2952 BUG_ON(sock_owned_by_user(sk));
2953 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2954 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2955}
2956
2957static inline void
2958cifs_reclassify_socket6(struct socket *sock)
2959{
2960 struct sock *sk = sock->sk;
2961 BUG_ON(sock_owned_by_user(sk));
2962 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2963 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2964}
2965#else
2966static inline void
2967cifs_reclassify_socket4(struct socket *sock)
2968{
2969}
2970
2971static inline void
2972cifs_reclassify_socket6(struct socket *sock)
2973{
2974}
2975#endif
2976
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002978static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979{
Steve French50c2f752007-07-13 00:33:32 +00002980 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981
Steve French50c2f752007-07-13 00:33:32 +00002982 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 /* mask a nibble at a time and encode */
2984 target[j] = 'A' + (0x0F & (source[i] >> 4));
2985 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002986 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 }
2988
2989}
2990
Ben Greear3eb9a882010-09-01 17:06:02 -07002991static int
2992bind_socket(struct TCP_Server_Info *server)
2993{
2994 int rc = 0;
2995 if (server->srcaddr.ss_family != AF_UNSPEC) {
2996 /* Bind to the specified local IP address */
2997 struct socket *socket = server->ssocket;
2998 rc = socket->ops->bind(socket,
2999 (struct sockaddr *) &server->srcaddr,
3000 sizeof(server->srcaddr));
3001 if (rc < 0) {
3002 struct sockaddr_in *saddr4;
3003 struct sockaddr_in6 *saddr6;
3004 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3005 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3006 if (saddr6->sin6_family == AF_INET6)
3007 cERROR(1, "cifs: "
3008 "Failed to bind to: %pI6c, error: %d\n",
3009 &saddr6->sin6_addr, rc);
3010 else
3011 cERROR(1, "cifs: "
3012 "Failed to bind to: %pI4, error: %d\n",
3013 &saddr4->sin_addr.s_addr, rc);
3014 }
3015 }
3016 return rc;
3017}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018
3019static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003020ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021{
3022 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003023 /*
3024 * some servers require RFC1001 sessinit before sending
3025 * negprot - BB check reconnection in case where second
3026 * sessinit is sent but no second negprot
3027 */
3028 struct rfc1002_session_packet *ses_init_buf;
3029 struct smb_hdr *smb_buf;
3030 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3031 GFP_KERNEL);
3032 if (ses_init_buf) {
3033 ses_init_buf->trailer.session_req.called_len = 32;
3034
3035 if (server->server_RFC1001_name &&
3036 server->server_RFC1001_name[0] != 0)
3037 rfc1002mangle(ses_init_buf->trailer.
3038 session_req.called_name,
3039 server->server_RFC1001_name,
3040 RFC1001_NAME_LEN_WITH_NULL);
3041 else
3042 rfc1002mangle(ses_init_buf->trailer.
3043 session_req.called_name,
3044 DEFAULT_CIFS_CALLED_NAME,
3045 RFC1001_NAME_LEN_WITH_NULL);
3046
3047 ses_init_buf->trailer.session_req.calling_len = 32;
3048
3049 /*
3050 * calling name ends in null (byte 16) from old smb
3051 * convention.
3052 */
3053 if (server->workstation_RFC1001_name &&
3054 server->workstation_RFC1001_name[0] != 0)
3055 rfc1002mangle(ses_init_buf->trailer.
3056 session_req.calling_name,
3057 server->workstation_RFC1001_name,
3058 RFC1001_NAME_LEN_WITH_NULL);
3059 else
3060 rfc1002mangle(ses_init_buf->trailer.
3061 session_req.calling_name,
3062 "LINUX_CIFS_CLNT",
3063 RFC1001_NAME_LEN_WITH_NULL);
3064
3065 ses_init_buf->trailer.session_req.scope1 = 0;
3066 ses_init_buf->trailer.session_req.scope2 = 0;
3067 smb_buf = (struct smb_hdr *)ses_init_buf;
3068
3069 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003070 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003071 rc = smb_send(server, smb_buf, 0x44);
3072 kfree(ses_init_buf);
3073 /*
3074 * RFC1001 layer in at least one server
3075 * requires very short break before negprot
3076 * presumably because not expecting negprot
3077 * to follow so fast. This is a simple
3078 * solution that works without
3079 * complicating the code and causes no
3080 * significant slowing down on mount
3081 * for everyone else
3082 */
3083 usleep_range(1000, 2000);
3084 }
3085 /*
3086 * else the negprot may still work without this
3087 * even though malloc failed
3088 */
3089
3090 return rc;
3091}
3092
3093static int
3094generic_ip_connect(struct TCP_Server_Info *server)
3095{
3096 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003097 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003098 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003099 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003100 struct sockaddr *saddr;
3101
3102 saddr = (struct sockaddr *) &server->dstaddr;
3103
3104 if (server->dstaddr.ss_family == AF_INET6) {
3105 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3106 slen = sizeof(struct sockaddr_in6);
3107 sfamily = AF_INET6;
3108 } else {
3109 sport = ((struct sockaddr_in *) saddr)->sin_port;
3110 slen = sizeof(struct sockaddr_in);
3111 sfamily = AF_INET;
3112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003114 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003115 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3116 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003118 cERROR(1, "Error %d creating socket", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003119 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003122
3123 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003124 cFYI(1, "Socket created");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003125 server->ssocket = socket;
3126 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003127 if (sfamily == AF_INET6)
3128 cifs_reclassify_socket6(socket);
3129 else
3130 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 }
3132
Ben Greear3eb9a882010-09-01 17:06:02 -07003133 rc = bind_socket(server);
3134 if (rc < 0)
3135 return rc;
3136
Jeff Laytond5c56052008-12-01 18:42:33 -05003137 /*
3138 * Eventually check for other socket options to change from
3139 * the default. sock_setsockopt not used because it expects
3140 * user space buffer
3141 */
3142 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003143 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003144
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003145 /* make the bufsizes depend on wsize/rsize and max requests */
3146 if (server->noautotune) {
3147 if (socket->sk->sk_sndbuf < (200 * 1024))
3148 socket->sk->sk_sndbuf = 200 * 1024;
3149 if (socket->sk->sk_rcvbuf < (140 * 1024))
3150 socket->sk->sk_rcvbuf = 140 * 1024;
3151 }
3152
Steve French6a5fa2362010-01-01 01:28:43 +00003153 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003154 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003155 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3156 (char *)&val, sizeof(val));
3157 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003158 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003159 }
3160
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003161 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
3162 socket->sk->sk_sndbuf,
3163 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3164
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003165 rc = socket->ops->connect(socket, saddr, slen, 0);
3166 if (rc < 0) {
3167 cFYI(1, "Error %d connecting to server", rc);
3168 sock_release(socket);
3169 server->ssocket = NULL;
3170 return rc;
3171 }
3172
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003173 if (sport == htons(RFC1001_PORT))
3174 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003175
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 return rc;
3177}
3178
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003179static int
3180ip_connect(struct TCP_Server_Info *server)
3181{
Steve French6da97912011-03-13 18:55:55 +00003182 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003183 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3184 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3185
3186 if (server->dstaddr.ss_family == AF_INET6)
3187 sport = &addr6->sin6_port;
3188 else
3189 sport = &addr->sin_port;
3190
3191 if (*sport == 0) {
3192 int rc;
3193
3194 /* try with 445 port at first */
3195 *sport = htons(CIFS_PORT);
3196
3197 rc = generic_ip_connect(server);
3198 if (rc >= 0)
3199 return rc;
3200
3201 /* if it failed, try with 139 port */
3202 *sport = htons(RFC1001_PORT);
3203 }
3204
3205 return generic_ip_connect(server);
3206}
3207
Steve French96daf2b2011-05-27 04:34:02 +00003208void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003209 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003210{
3211 /* if we are reconnecting then should we check to see if
3212 * any requested capabilities changed locally e.g. via
3213 * remount but we can not do much about it here
3214 * if they have (even if we could detect it by the following)
3215 * Perhaps we could add a backpointer to array of sb from tcon
3216 * or if we change to make all sb to same share the same
3217 * sb as NFS - then we only have one backpointer to sb.
3218 * What if we wanted to mount the server share twice once with
3219 * and once without posixacls or posix paths? */
3220 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003221
Steve Frenchc18c8422007-07-18 23:21:09 +00003222 if (vol_info && vol_info->no_linux_ext) {
3223 tcon->fsUnixInfo.Capability = 0;
3224 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003225 cFYI(1, "Linux protocol extensions disabled");
Steve Frenchc18c8422007-07-18 23:21:09 +00003226 return;
3227 } else if (vol_info)
3228 tcon->unix_ext = 1; /* Unix Extensions supported */
3229
3230 if (tcon->unix_ext == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003231 cFYI(1, "Unix extensions disabled so not set on reconnect");
Steve Frenchc18c8422007-07-18 23:21:09 +00003232 return;
3233 }
Steve French50c2f752007-07-13 00:33:32 +00003234
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003235 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003236 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French6848b732011-05-26 18:38:54 +00003237 cFYI(1, "unix caps which server supports %lld", cap);
Steve French8af18972007-02-14 04:42:51 +00003238 /* check for reconnect case in which we do not
3239 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003240 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003241 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003242 originally at mount time */
3243 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3244 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003245 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3246 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003247 cERROR(1, "POSIXPATH support change");
Steve French8af18972007-02-14 04:42:51 +00003248 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003249 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003250 cERROR(1, "possible reconnect error");
3251 cERROR(1, "server disabled POSIX path support");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003252 }
Steve French8af18972007-02-14 04:42:51 +00003253 }
Steve French50c2f752007-07-13 00:33:32 +00003254
Steve French6848b732011-05-26 18:38:54 +00003255 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3256 cERROR(1, "per-share encryption not supported yet");
3257
Steve French8af18972007-02-14 04:42:51 +00003258 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003259 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003260 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003261 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003262 cFYI(1, "negotiated posix acl support");
Al Viro2c6292a2011-06-17 09:05:48 -04003263 if (cifs_sb)
3264 cifs_sb->mnt_cifs_flags |=
3265 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003266 }
3267
Steve French75865f8c2007-06-24 18:30:48 +00003268 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003269 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003270 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003271 cFYI(1, "negotiate posix pathnames");
Al Viro2c6292a2011-06-17 09:05:48 -04003272 if (cifs_sb)
3273 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003274 CIFS_MOUNT_POSIX_PATHS;
3275 }
Steve French50c2f752007-07-13 00:33:32 +00003276
Joe Perchesb6b38f72010-04-21 03:50:45 +00003277 cFYI(1, "Negotiate caps 0x%x", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003278#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003279 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003280 cFYI(1, "FCNTL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003281 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003282 cFYI(1, "EXTATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003283 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003284 cFYI(1, "POSIX path cap");
Steve French75865f8c2007-06-24 18:30:48 +00003285 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003286 cFYI(1, "XATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003287 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003288 cFYI(1, "POSIX ACL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003289 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003290 cFYI(1, "very large read cap");
Steve French75865f8c2007-06-24 18:30:48 +00003291 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003292 cFYI(1, "very large write cap");
Steve French6848b732011-05-26 18:38:54 +00003293 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3294 cFYI(1, "transport encryption cap");
3295 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3296 cFYI(1, "mandatory transport encryption cap");
Steve French8af18972007-02-14 04:42:51 +00003297#endif /* CIFS_DEBUG2 */
3298 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003299 if (vol_info == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003300 cFYI(1, "resetting capabilities failed");
Steve French442aa312007-09-24 20:25:46 +00003301 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003302 cERROR(1, "Negotiating Unix capabilities "
Steve French5a44b312007-09-20 15:16:24 +00003303 "with the server failed. Consider "
3304 "mounting with the Unix Extensions\n"
3305 "disabled, if problems are found, "
3306 "by specifying the nounix mount "
Joe Perchesb6b38f72010-04-21 03:50:45 +00003307 "option.");
Steve French5a44b312007-09-20 15:16:24 +00003308
Steve French8af18972007-02-14 04:42:51 +00003309 }
3310 }
3311}
3312
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003313void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3314 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003315{
Jeff Layton2de970f2010-10-06 19:51:12 -04003316 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3317
Al Viro2ced6f62011-06-17 09:20:04 -04003318 spin_lock_init(&cifs_sb->tlink_tree_lock);
3319 cifs_sb->tlink_tree = RB_ROOT;
3320
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003321 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003322 * Temporarily set r/wsize for matching superblock. If we end up using
3323 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003324 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003325 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003326 cifs_sb->wsize = pvolume_info->wsize;
3327
Steve French3b795212008-11-13 19:45:32 +00003328 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3329 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3330 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3331 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Al Viro5206efd2011-07-26 03:22:14 -04003332 cFYI(1, "file mode: 0x%hx dir mode: 0x%hx",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003333 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003334
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303335 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003336 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303337
Steve French3b795212008-11-13 19:45:32 +00003338 if (pvolume_info->noperm)
3339 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3340 if (pvolume_info->setuids)
3341 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3342 if (pvolume_info->server_ino)
3343 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3344 if (pvolume_info->remap)
3345 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3346 if (pvolume_info->no_xattr)
3347 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3348 if (pvolume_info->sfu_emul)
3349 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3350 if (pvolume_info->nobrl)
3351 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003352 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003353 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003354 if (pvolume_info->mand_lock)
3355 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003356 if (pvolume_info->rwpidforward)
3357 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003358 if (pvolume_info->cifs_acl)
3359 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003360 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003361 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003362 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3363 }
3364 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003365 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003366 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3367 }
Steve French3b795212008-11-13 19:45:32 +00003368 if (pvolume_info->override_uid)
3369 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3370 if (pvolume_info->override_gid)
3371 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3372 if (pvolume_info->dynperm)
3373 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303374 if (pvolume_info->fsc)
3375 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003376 if (pvolume_info->multiuser)
3377 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3378 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003379 if (pvolume_info->strict_io)
3380 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003381 if (pvolume_info->direct_io) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003382 cFYI(1, "mounting share using direct i/o");
Steve French3b795212008-11-13 19:45:32 +00003383 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3384 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003385 if (pvolume_info->mfsymlinks) {
3386 if (pvolume_info->sfu_emul) {
3387 cERROR(1, "mount option mfsymlinks ignored if sfu "
3388 "mount option is used");
3389 } else {
3390 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3391 }
3392 }
Steve French3b795212008-11-13 19:45:32 +00003393
3394 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesb6b38f72010-04-21 03:50:45 +00003395 cERROR(1, "mount option dynperm ignored if cifsacl "
3396 "mount option supported");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003397}
3398
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003399/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003400 * When the server supports very large reads and writes via POSIX extensions,
3401 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
3402 * including the RFC1001 length.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003403 *
3404 * Note that this might make for "interesting" allocation problems during
Jeff Layton1190f6a2011-06-22 17:33:57 -04003405 * writeback however as we have to allocate an array of pointers for the
3406 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003407 *
3408 * For reads, there is a similar problem as we need to allocate an array
3409 * of kvecs to handle the receive, though that should only need to be done
3410 * once.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003411 */
Jeff Layton1190f6a2011-06-22 17:33:57 -04003412#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003413#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003414
3415/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003416 * When the server doesn't allow large posix writes, only allow a rsize/wsize
3417 * of 2^17-1 minus the size of the call header. That allows for a read or
3418 * write up to the maximum size described by RFC1002.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003419 */
Pavel Shilovsky94443f42011-10-07 18:57:45 +04003420#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003421#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003422
3423/*
3424 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
3425 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
3426 * a single wsize request with a single call.
3427 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003428#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
3429
3430/*
Jeff Laytonce91acb2012-01-17 16:08:51 -05003431 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
3432 * those values when posix extensions aren't in force. In actuality here, we
3433 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
3434 * to be ok with the extra byte even though Windows doesn't send writes that
3435 * are that large.
3436 *
3437 * Citation:
3438 *
3439 * 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 -04003440 */
3441#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
Jeff Laytonce91acb2012-01-17 16:08:51 -05003442#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003443
3444static unsigned int
Steve French96daf2b2011-05-27 04:34:02 +00003445cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003446{
3447 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3448 struct TCP_Server_Info *server = tcon->ses->server;
Jeff Laytonce91acb2012-01-17 16:08:51 -05003449 unsigned int wsize;
3450
3451 /* start with specified wsize, or default */
3452 if (pvolume_info->wsize)
3453 wsize = pvolume_info->wsize;
3454 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3455 wsize = CIFS_DEFAULT_IOSIZE;
3456 else
3457 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003458
3459 /* can server support 24-bit write sizes? (via UNIX extensions) */
3460 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
Jeff Layton1190f6a2011-06-22 17:33:57 -04003461 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003462
Jeff Layton1190f6a2011-06-22 17:33:57 -04003463 /*
3464 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
3465 * Limit it to max buffer offered by the server, minus the size of the
3466 * WRITEX header, not including the 4 byte RFC1001 length.
3467 */
3468 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
3469 (!(server->capabilities & CAP_UNIX) &&
3470 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
3471 wsize = min_t(unsigned int, wsize,
3472 server->maxBuf - sizeof(WRITE_REQ) + 4);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003473
3474 /* hard limit of CIFS_MAX_WSIZE */
3475 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3476
3477 return wsize;
3478}
3479
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003480static unsigned int
3481cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3482{
3483 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3484 struct TCP_Server_Info *server = tcon->ses->server;
3485 unsigned int rsize, defsize;
3486
3487 /*
3488 * Set default value...
3489 *
3490 * HACK alert! Ancient servers have very small buffers. Even though
3491 * MS-CIFS indicates that servers are only limited by the client's
3492 * bufsize for reads, testing against win98se shows that it throws
3493 * INVALID_PARAMETER errors if you try to request too large a read.
3494 *
3495 * If the server advertises a MaxBufferSize of less than one page,
3496 * assume that it also can't satisfy reads larger than that either.
3497 *
3498 * FIXME: Is there a better heuristic for this?
3499 */
3500 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
3501 defsize = CIFS_DEFAULT_IOSIZE;
3502 else if (server->capabilities & CAP_LARGE_READ_X)
3503 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
3504 else if (server->maxBuf >= PAGE_CACHE_SIZE)
3505 defsize = CIFSMaxBufSize;
3506 else
3507 defsize = server->maxBuf - sizeof(READ_RSP);
3508
3509 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
3510
3511 /*
3512 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
3513 * the client's MaxBufferSize.
3514 */
3515 if (!(server->capabilities & CAP_LARGE_READ_X))
3516 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3517
3518 /* hard limit of CIFS_MAX_RSIZE */
3519 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3520
3521 return rsize;
3522}
3523
Igor Mammedove4cce942009-02-10 14:10:26 +03003524static int
Steve French96daf2b2011-05-27 04:34:02 +00003525is_path_accessible(int xid, struct cifs_tcon *tcon,
Igor Mammedove4cce942009-02-10 14:10:26 +03003526 struct cifs_sb_info *cifs_sb, const char *full_path)
3527{
3528 int rc;
Igor Mammedove4cce942009-02-10 14:10:26 +03003529 FILE_ALL_INFO *pfile_info;
3530
Igor Mammedove4cce942009-02-10 14:10:26 +03003531 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
3532 if (pfile_info == NULL)
3533 return -ENOMEM;
3534
3535 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
3536 0 /* not legacy */, cifs_sb->local_nls,
3537 cifs_sb->mnt_cifs_flags &
3538 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton221d1d72011-05-17 06:40:30 -04003539
3540 if (rc == -EOPNOTSUPP || rc == -EINVAL)
3541 rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
3542 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
3543 CIFS_MOUNT_MAP_SPECIAL_CHR);
Igor Mammedove4cce942009-02-10 14:10:26 +03003544 kfree(pfile_info);
3545 return rc;
3546}
3547
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003548static void
3549cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003550{
Sean Finneyb9468452011-04-11 13:19:32 +00003551 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003552 kzfree(volume_info->password);
Steve French13589c42011-08-18 04:41:55 +00003553 if (volume_info->UNCip != volume_info->UNC + 2)
3554 kfree(volume_info->UNCip);
Jesper Juhl95c75452011-08-27 18:58:34 +02003555 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003556 kfree(volume_info->domainname);
3557 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003558 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003559}
3560
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003561void
3562cifs_cleanup_volume_info(struct smb_vol *volume_info)
3563{
3564 if (!volume_info)
3565 return;
3566 cleanup_volume_info_contents(volume_info);
3567 kfree(volume_info);
3568}
3569
3570
Steve French2d6d5892009-04-09 00:36:44 +00003571#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003572/* build_path_to_root returns full path to root when
3573 * we do not have an exiting connection (tcon) */
3574static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003575build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003576 const struct cifs_sb_info *cifs_sb)
3577{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003578 char *full_path, *pos;
3579 unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
3580 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003581
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003582 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003583 if (full_path == NULL)
3584 return ERR_PTR(-ENOMEM);
3585
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003586 strncpy(full_path, vol->UNC, unc_len);
3587 pos = full_path + unc_len;
3588
3589 if (pplen) {
3590 strncpy(pos, vol->prepath, pplen);
3591 pos += pplen;
3592 }
3593
3594 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003595 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003596 cFYI(1, "%s: full_path=%s", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003597 return full_path;
3598}
Sean Finneydd613942011-04-11 13:19:30 +00003599
3600/*
3601 * Perform a dfs referral query for a share and (optionally) prefix
3602 *
Sean Finney046462a2011-04-11 13:19:33 +00003603 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3604 * to a string containing updated options for the submount. Otherwise it
3605 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003606 *
3607 * Returns the rc from get_dfs_path to the caller, which can be used to
3608 * determine whether there were referrals.
3609 */
3610static int
Steve French96daf2b2011-05-27 04:34:02 +00003611expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
Sean Finneydd613942011-04-11 13:19:30 +00003612 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003613 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003614{
3615 int rc;
3616 unsigned int num_referrals = 0;
3617 struct dfs_info3_param *referrals = NULL;
3618 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3619
3620 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3621 if (IS_ERR(full_path))
3622 return PTR_ERR(full_path);
3623
3624 /* For DFS paths, skip the first '\' of the UNC */
3625 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3626
3627 rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
3628 &num_referrals, &referrals,
3629 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3630
3631 if (!rc && num_referrals > 0) {
3632 char *fake_devname = NULL;
3633
3634 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3635 full_path + 1, referrals,
3636 &fake_devname);
3637
3638 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003639
Sean Finneydd613942011-04-11 13:19:30 +00003640 if (IS_ERR(mdata)) {
3641 rc = PTR_ERR(mdata);
3642 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003643 } else {
3644 cleanup_volume_info_contents(volume_info);
3645 memset(volume_info, '\0', sizeof(*volume_info));
3646 rc = cifs_setup_volume_info(volume_info, mdata,
3647 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003648 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003649 kfree(fake_devname);
3650 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003651 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003652 }
3653 kfree(full_path);
3654 return rc;
3655}
Steve French2d6d5892009-04-09 00:36:44 +00003656#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003657
Jeff Layton04db79b2011-07-06 08:10:38 -04003658static int
3659cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3660 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003662 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003663
Jeff Layton04db79b2011-07-06 08:10:38 -04003664 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3665 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666
Jeff Layton23db65f2012-05-15 12:20:51 -04003667
Jeff Layton7586b762008-12-01 18:41:49 -05003668 if (volume_info->nullauth) {
Jeff Layton04febab2012-01-17 16:09:15 -05003669 cFYI(1, "Anonymous login");
3670 kfree(volume_info->username);
3671 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003672 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 /* BB fixme parse for domain name here */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003674 cFYI(1, "Username: %s", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 } else {
Steve Frenchbf820672005-12-01 22:32:42 -08003676 cifserror("No username specified");
Steve French50c2f752007-07-13 00:33:32 +00003677 /* In userspace mount helper we can get user name from alternate
3678 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003679 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 }
3681
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003683 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003684 /* load_nls_default cannot return null */
3685 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003687 volume_info->local_nls = load_nls(volume_info->iocharset);
3688 if (volume_info->local_nls == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003689 cERROR(1, "CIFS mount error: iocharset %s not found",
3690 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003691 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 }
3693 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003694
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003695 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003696}
3697
3698struct smb_vol *
3699cifs_get_volume_info(char *mount_data, const char *devname)
3700{
3701 int rc;
3702 struct smb_vol *volume_info;
3703
3704 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
3705 if (!volume_info)
3706 return ERR_PTR(-ENOMEM);
3707
3708 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3709 if (rc) {
3710 cifs_cleanup_volume_info(volume_info);
3711 volume_info = ERR_PTR(rc);
3712 }
3713
3714 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003715}
3716
3717int
Al Viro2c6292a2011-06-17 09:05:48 -04003718cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003719{
Jeff Layton1daaae82012-03-21 06:30:40 -04003720 int rc;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003721 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003722 struct cifs_ses *pSesInfo;
3723 struct cifs_tcon *tcon;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003724 struct TCP_Server_Info *srvTcp;
3725 char *full_path;
3726 struct tcon_link *tlink;
3727#ifdef CONFIG_CIFS_DFS_UPCALL
3728 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003729#endif
Al Virodd854462011-06-17 08:24:42 -04003730
3731 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3732 if (rc)
3733 return rc;
3734
Jeff Layton20547492011-07-09 12:21:07 -04003735#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003736try_mount_again:
3737 /* cleanup activities if we're chasing a referral */
3738 if (referral_walks_count) {
3739 if (tcon)
3740 cifs_put_tcon(tcon);
3741 else if (pSesInfo)
3742 cifs_put_smb_ses(pSesInfo);
3743
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003744 FreeXid(xid);
3745 }
3746#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003747 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003748 tcon = NULL;
3749 pSesInfo = NULL;
3750 srvTcp = NULL;
3751 full_path = NULL;
3752 tlink = NULL;
3753
3754 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
Jeff Layton63c038c2008-12-01 18:41:46 -05003756 /* get a reference to a tcp session */
Jeff Layton7586b762008-12-01 18:41:49 -05003757 srvTcp = cifs_get_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05003758 if (IS_ERR(srvTcp)) {
3759 rc = PTR_ERR(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003760 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003761 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762 }
3763
Jeff Layton36988c72010-04-24 07:57:43 -04003764 /* get a reference to a SMB session */
3765 pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
3766 if (IS_ERR(pSesInfo)) {
3767 rc = PTR_ERR(pSesInfo);
3768 pSesInfo = NULL;
3769 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 }
Steve French50c2f752007-07-13 00:33:32 +00003771
Jeff Laytond00c28d2010-04-24 07:57:44 -04003772 /* search for existing tcon to this server share */
3773 tcon = cifs_get_tcon(pSesInfo, volume_info);
3774 if (IS_ERR(tcon)) {
3775 rc = PTR_ERR(tcon);
3776 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003777 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003778 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003779
Steve French6848b732011-05-26 18:38:54 +00003780 /* tell server which Unix caps we support */
3781 if (tcon->ses->capabilities & CAP_UNIX) {
3782 /* reset of caps checks mount to see if unix extensions
3783 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003784 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003785 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3786 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3787 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3788 rc = -EACCES;
3789 goto mount_fail_check;
3790 }
3791 } else
3792 tcon->unix_ext = 0; /* server does not support them */
3793
Steve Frenchd82c2df2008-11-15 00:07:26 +00003794 /* do not care if following two calls succeed - informational */
3795 if (!tcon->ipc) {
3796 CIFSSMBQFSDeviceInfo(xid, tcon);
3797 CIFSSMBQFSAttributeInfo(xid, tcon);
3798 }
3799
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003800 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003801 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003802
Jeff Layton66bfaad2011-10-19 15:30:35 -04003803 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003804 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003805
Igor Mammedove4cce942009-02-10 14:10:26 +03003806remote_path_check:
3807#ifdef CONFIG_CIFS_DFS_UPCALL
3808 /*
3809 * Perform an unconditional check for whether there are DFS
3810 * referrals for this path without prefix, to provide support
3811 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003812 * with PATH_NOT_COVERED to requests that include the prefix.
3813 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003814 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003815 if (referral_walks_count == 0) {
3816 int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
3817 cifs_sb, false);
3818 if (!refrc) {
3819 referral_walks_count++;
3820 goto try_mount_again;
3821 }
3822 }
3823#endif
3824
Steve Frenchf87d39d2011-05-27 03:50:55 +00003825 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 if (!rc && tcon) {
3827 /* build_path_to_root works only when we have a valid tcon */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003828 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Steve French7c7b25b2006-06-01 19:20:10 +00003829 if (full_path == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 rc = -ENOMEM;
3831 goto mount_fail_check;
3832 }
3833 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
3834 if (rc != 0 && rc != -EREMOTE) {
3835 kfree(full_path);
3836 goto mount_fail_check;
3837 }
3838 kfree(full_path);
3839 }
3840
3841 /* get referral if needed */
3842 if (rc == -EREMOTE) {
3843#ifdef CONFIG_CIFS_DFS_UPCALL
3844 if (referral_walks_count > MAX_NESTED_LINKS) {
3845 /*
Steve Frencheeac8042006-01-13 21:34:58 -08003846 * BB: when we implement proper loop detection,
Steve French4523cc32007-04-30 20:13:06 +00003847 * we will remove this check. But now we need it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 * to prevent an indefinite loop if 'DFS tree' is
3849 * misconfigured (i.e. has loops).
3850 */
3851 rc = -ELOOP;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003852 goto mount_fail_check;
3853 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003854
Sean Finneydd613942011-04-11 13:19:30 +00003855 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003856 true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003857
Sean Finneydd613942011-04-11 13:19:30 +00003858 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003859 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003860 goto try_mount_again;
3861 }
Sean Finneydd613942011-04-11 13:19:30 +00003862 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003863#else /* No DFS support, return error on mount */
3864 rc = -EOPNOTSUPP;
3865#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003866 }
3867
Jeff Layton9d002df2010-10-06 19:51:11 -04003868 if (rc)
3869 goto mount_fail_check;
3870
3871 /* now, hang the tcon off of the superblock */
3872 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3873 if (tlink == NULL) {
3874 rc = -ENOMEM;
3875 goto mount_fail_check;
3876 }
3877
Jeff Laytonb647c352010-10-28 11:16:44 -04003878 tlink->tl_uid = pSesInfo->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003879 tlink->tl_tcon = tcon;
3880 tlink->tl_time = jiffies;
3881 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3882 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3883
Jeff Layton413e6612010-10-28 13:33:38 -04003884 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003885 spin_lock(&cifs_sb->tlink_tree_lock);
3886 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3887 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003888
Jeff Laytonda472fc2012-03-23 14:40:53 -04003889 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003890 TLINK_IDLE_EXPIRE);
3891
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003892mount_fail_check:
3893 /* on error free sesinfo and tcon struct if needed */
3894 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003895 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003896 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003897 if (tcon)
3898 cifs_put_tcon(tcon);
3899 else if (pSesInfo)
3900 cifs_put_smb_ses(pSesInfo);
3901 else
3902 cifs_put_tcp_session(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003903 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003904 }
3905
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 FreeXid(xid);
3908 return rc;
3909}
3910
Jeff Layton8d1bca32011-06-11 21:17:10 -04003911/*
3912 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3913 * pointer may be NULL.
3914 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915int
Steve French96daf2b2011-05-27 04:34:02 +00003916CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3917 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 const struct nls_table *nls_codepage)
3919{
3920 struct smb_hdr *smb_buffer;
3921 struct smb_hdr *smb_buffer_response;
3922 TCONX_REQ *pSMB;
3923 TCONX_RSP *pSMBr;
3924 unsigned char *bcc_ptr;
3925 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003926 int length;
3927 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928
3929 if (ses == NULL)
3930 return -EIO;
3931
3932 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003933 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003935
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 smb_buffer_response = smb_buffer;
3937
3938 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3939 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003940
3941 smb_buffer->Mid = GetNextMid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 smb_buffer->Uid = ses->Suid;
3943 pSMB = (TCONX_REQ *) smb_buffer;
3944 pSMBr = (TCONX_RSP *) smb_buffer_response;
3945
3946 pSMB->AndXCommand = 0xFF;
3947 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003949 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003950 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003951 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003952 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003953 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003954 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003955 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003956 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3957 specified as required (when that support is added to
3958 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003959 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003960 by Samba (not sure whether other servers allow
3961 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003962#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003963 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003964 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003965 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003966 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003967 SECMODE_PW_ENCRYPT ? true : false,
3968 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003969 else
3970#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003971 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003972 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003973
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003974 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003975 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003976 /* must align unicode strings */
3977 *bcc_ptr = 0; /* null byte password */
3978 bcc_ptr++;
3979 }
Steve Frencheeac8042006-01-13 21:34:58 -08003980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
Steve French96daf2b2011-05-27 04:34:02 +00003982 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003983 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3985
3986 if (ses->capabilities & CAP_STATUS32) {
3987 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3988 }
3989 if (ses->capabilities & CAP_DFS) {
3990 smb_buffer->Flags2 |= SMBFLG2_DFS;
3991 }
3992 if (ses->capabilities & CAP_UNICODE) {
3993 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3994 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003995 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003996 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003997 (/* server len*/ + 256 /* share len */), nls_codepage);
3998 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 bcc_ptr += 2; /* skip trailing null */
4000 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 strcpy(bcc_ptr, tree);
4002 bcc_ptr += strlen(tree) + 1;
4003 }
4004 strcpy(bcc_ptr, "?????");
4005 bcc_ptr += strlen("?????");
4006 bcc_ptr += 1;
4007 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00004008 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4009 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 pSMB->ByteCount = cpu_to_le16(count);
4011
Steve French133672e2007-11-13 22:41:37 +00004012 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05004013 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015 /* above now done in SendReceive */
4016 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00004017 bool is_unicode;
4018
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00004020 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 tcon->tid = smb_buffer_response->Tid;
4022 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05004023 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004024 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00004025 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4026 is_unicode = true;
4027 else
4028 is_unicode = false;
4029
Jeff Laytoncc20c032009-04-30 07:16:21 -04004030
Steve French50c2f752007-07-13 00:33:32 +00004031 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004032 if (length == 3) {
4033 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4034 (bcc_ptr[2] == 'C')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004035 cFYI(1, "IPC connection");
Steve French7f8ed422007-09-28 22:28:55 +00004036 tcon->ipc = 1;
4037 }
4038 } else if (length == 2) {
4039 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4040 /* the most common case */
Joe Perchesb6b38f72010-04-21 03:50:45 +00004041 cFYI(1, "disk share connection");
Steve French7f8ed422007-09-28 22:28:55 +00004042 }
4043 }
Steve French50c2f752007-07-13 00:33:32 +00004044 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004045 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004047
4048 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004049 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004050 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004051 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004052 nls_codepage);
4053
Joe Perchesb6b38f72010-04-21 03:50:45 +00004054 cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004055
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004056 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004057 (smb_buffer_response->WordCount == 7))
4058 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004059 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4060 else
4061 tcon->Flags = 0;
Joe Perchesb6b38f72010-04-21 03:50:45 +00004062 cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004064 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 ses->ipc_tid = smb_buffer_response->Tid;
4066 }
4067
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004068 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 return rc;
4070}
4071
Al Viro2a9b9952011-06-17 09:27:16 -04004072void
4073cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074{
Jeff Laytonb647c352010-10-28 11:16:44 -04004075 struct rb_root *root = &cifs_sb->tlink_tree;
4076 struct rb_node *node;
4077 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Jeff Layton2de970f2010-10-06 19:51:12 -04004079 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4080
Jeff Laytonb647c352010-10-28 11:16:44 -04004081 spin_lock(&cifs_sb->tlink_tree_lock);
4082 while ((node = rb_first(root))) {
4083 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4084 cifs_get_tlink(tlink);
4085 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4086 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004087
Jeff Laytonb647c352010-10-28 11:16:44 -04004088 spin_unlock(&cifs_sb->tlink_tree_lock);
4089 cifs_put_tlink(tlink);
4090 spin_lock(&cifs_sb->tlink_tree_lock);
4091 }
4092 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004093
Al Virodd854462011-06-17 08:24:42 -04004094 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004095 kfree(cifs_sb->mountdata);
4096 unload_nls(cifs_sb->local_nls);
4097 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00004098}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099
Steve French96daf2b2011-05-27 04:34:02 +00004100int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101{
4102 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004103 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
Jeff Layton198b5682010-04-24 07:57:48 -04004105 /* only send once per connect */
4106 if (server->maxBuf != 0)
4107 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
Pavel Shilovsky45275782012-05-17 17:53:29 +04004109 set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004110 rc = CIFSSMBNegotiate(xid, ses);
4111 if (rc == -EAGAIN) {
4112 /* retry only once on 1st time connection */
Pavel Shilovsky45275782012-05-17 17:53:29 +04004113 set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004114 rc = CIFSSMBNegotiate(xid, ses);
4115 if (rc == -EAGAIN)
4116 rc = -EHOSTDOWN;
4117 }
4118 if (rc == 0) {
4119 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004120 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004121 server->tcpStatus = CifsGood;
4122 else
4123 rc = -EHOSTDOWN;
4124 spin_unlock(&GlobalMid_Lock);
4125
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 }
Steve French26b994f2008-08-06 05:11:33 +00004127
Jeff Layton198b5682010-04-24 07:57:48 -04004128 return rc;
4129}
Steve French26b994f2008-08-06 05:11:33 +00004130
Jeff Layton198b5682010-04-24 07:57:48 -04004131
Steve French96daf2b2011-05-27 04:34:02 +00004132int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
Jeff Layton198b5682010-04-24 07:57:48 -04004133 struct nls_table *nls_info)
4134{
4135 int rc = 0;
4136 struct TCP_Server_Info *server = ses->server;
4137
4138 ses->flags = 0;
4139 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004140 if (linuxExtEnabled == 0)
Jeff Layton198b5682010-04-24 07:57:48 -04004141 ses->capabilities &= (~CAP_UNIX);
Steve French20418ac2009-04-30 16:13:32 +00004142
Joe Perchesb6b38f72010-04-21 03:50:45 +00004143 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
Steve French96daf2b2011-05-27 04:34:02 +00004144 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004145
Jeff Layton198b5682010-04-24 07:57:48 -04004146 rc = CIFS_SessSetup(xid, ses, nls_info);
Steve French26b994f2008-08-06 05:11:33 +00004147 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004148 cERROR(1, "Send error in SessSetup = %d", rc);
Steve French26b994f2008-08-06 05:11:33 +00004149 } else {
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004150 mutex_lock(&ses->server->srv_mutex);
4151 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004152 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004153 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004154 server->sequence_number = 0x2;
4155 server->session_estab = true;
4156 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004157 }
4158 mutex_unlock(&server->srv_mutex);
4159
Joe Perchesb6b38f72010-04-21 03:50:45 +00004160 cFYI(1, "CIFS Session Established successfully");
Steve French20418ac2009-04-30 16:13:32 +00004161 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04004162 ses->status = CifsGood;
4163 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00004164 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00004165 }
4166
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004167 kfree(ses->auth_key.response);
4168 ses->auth_key.response = NULL;
4169 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05004170 kfree(ses->ntlmssp);
4171 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004172
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 return rc;
4174}
4175
Jeff Layton8a8798a2012-01-17 16:09:15 -05004176static int
4177cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4178{
4179 switch (ses->server->secType) {
4180 case Kerberos:
4181 vol->secFlg = CIFSSEC_MUST_KRB5;
4182 return 0;
4183 case NTLMv2:
4184 vol->secFlg = CIFSSEC_MUST_NTLMV2;
4185 break;
4186 case NTLM:
4187 vol->secFlg = CIFSSEC_MUST_NTLM;
4188 break;
4189 case RawNTLMSSP:
4190 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
4191 break;
4192 case LANMAN:
4193 vol->secFlg = CIFSSEC_MUST_LANMAN;
4194 break;
4195 }
4196
4197 return cifs_set_cifscreds(vol, ses);
4198}
4199
Steve French96daf2b2011-05-27 04:34:02 +00004200static struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004201cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
4202{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004203 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004204 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4205 struct cifs_ses *ses;
4206 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004207 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004208
4209 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004210 if (vol_info == NULL)
4211 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004212
Jeff Layton9d002df2010-10-06 19:51:11 -04004213 vol_info->local_nls = cifs_sb->local_nls;
4214 vol_info->linux_uid = fsuid;
4215 vol_info->cred_uid = fsuid;
4216 vol_info->UNC = master_tcon->treeName;
4217 vol_info->retry = master_tcon->retry;
4218 vol_info->nocase = master_tcon->nocase;
4219 vol_info->local_lease = master_tcon->local_lease;
4220 vol_info->no_linux_ext = !master_tcon->unix_ext;
4221
Jeff Layton8a8798a2012-01-17 16:09:15 -05004222 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4223 if (rc) {
4224 tcon = ERR_PTR(rc);
4225 goto out;
4226 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004227
4228 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304229 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004230 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304231 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004232
4233 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4234 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004235 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004236 cifs_put_tcp_session(master_tcon->ses->server);
4237 goto out;
4238 }
4239
4240 tcon = cifs_get_tcon(ses, vol_info);
4241 if (IS_ERR(tcon)) {
4242 cifs_put_smb_ses(ses);
4243 goto out;
4244 }
4245
4246 if (ses->capabilities & CAP_UNIX)
4247 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4248out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004249 kfree(vol_info->username);
4250 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004251 kfree(vol_info);
4252
4253 return tcon;
4254}
4255
Steve French96daf2b2011-05-27 04:34:02 +00004256struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004257cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4258{
4259 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4260}
4261
4262static int
4263cifs_sb_tcon_pending_wait(void *unused)
4264{
4265 schedule();
4266 return signal_pending(current) ? -ERESTARTSYS : 0;
4267}
4268
Jeff Laytonb647c352010-10-28 11:16:44 -04004269/* find and return a tlink with given uid */
4270static struct tcon_link *
4271tlink_rb_search(struct rb_root *root, uid_t uid)
4272{
4273 struct rb_node *node = root->rb_node;
4274 struct tcon_link *tlink;
4275
4276 while (node) {
4277 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4278
4279 if (tlink->tl_uid > uid)
4280 node = node->rb_left;
4281 else if (tlink->tl_uid < uid)
4282 node = node->rb_right;
4283 else
4284 return tlink;
4285 }
4286 return NULL;
4287}
4288
4289/* insert a tcon_link into the tree */
4290static void
4291tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4292{
4293 struct rb_node **new = &(root->rb_node), *parent = NULL;
4294 struct tcon_link *tlink;
4295
4296 while (*new) {
4297 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4298 parent = *new;
4299
4300 if (tlink->tl_uid > new_tlink->tl_uid)
4301 new = &((*new)->rb_left);
4302 else
4303 new = &((*new)->rb_right);
4304 }
4305
4306 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4307 rb_insert_color(&new_tlink->tl_rbnode, root);
4308}
4309
Jeff Layton9d002df2010-10-06 19:51:11 -04004310/*
4311 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4312 * current task.
4313 *
4314 * If the superblock doesn't refer to a multiuser mount, then just return
4315 * the master tcon for the mount.
4316 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304317 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004318 * exists, then check to see if it's pending construction. If it is then wait
4319 * for construction to complete. Once it's no longer pending, check to see if
4320 * it failed and either return an error or retry construction, depending on
4321 * the timeout.
4322 *
4323 * If one doesn't exist then insert a new tcon_link struct into the tree and
4324 * try to construct a new one.
4325 */
4326struct tcon_link *
4327cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4328{
4329 int ret;
Jeff Laytonb647c352010-10-28 11:16:44 -04004330 uid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004331 struct tcon_link *tlink, *newtlink;
4332
4333 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4334 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4335
4336 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004337 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004338 if (tlink)
4339 cifs_get_tlink(tlink);
4340 spin_unlock(&cifs_sb->tlink_tree_lock);
4341
4342 if (tlink == NULL) {
4343 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4344 if (newtlink == NULL)
4345 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004346 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004347 newtlink->tl_tcon = ERR_PTR(-EACCES);
4348 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4349 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4350 cifs_get_tlink(newtlink);
4351
Jeff Layton9d002df2010-10-06 19:51:11 -04004352 spin_lock(&cifs_sb->tlink_tree_lock);
4353 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004354 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004355 if (tlink) {
4356 cifs_get_tlink(tlink);
4357 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004358 kfree(newtlink);
4359 goto wait_for_construction;
4360 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004361 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004362 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4363 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004364 } else {
4365wait_for_construction:
4366 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4367 cifs_sb_tcon_pending_wait,
4368 TASK_INTERRUPTIBLE);
4369 if (ret) {
4370 cifs_put_tlink(tlink);
4371 return ERR_PTR(ret);
4372 }
4373
4374 /* if it's good, return it */
4375 if (!IS_ERR(tlink->tl_tcon))
4376 return tlink;
4377
4378 /* return error if we tried this already recently */
4379 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4380 cifs_put_tlink(tlink);
4381 return ERR_PTR(-EACCES);
4382 }
4383
4384 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4385 goto wait_for_construction;
4386 }
4387
4388 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4389 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4390 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4391
4392 if (IS_ERR(tlink->tl_tcon)) {
4393 cifs_put_tlink(tlink);
4394 return ERR_PTR(-EACCES);
4395 }
4396
4397 return tlink;
4398}
Jeff Layton2de970f2010-10-06 19:51:12 -04004399
4400/*
4401 * periodic workqueue job that scans tcon_tree for a superblock and closes
4402 * out tcons.
4403 */
4404static void
4405cifs_prune_tlinks(struct work_struct *work)
4406{
4407 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4408 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004409 struct rb_root *root = &cifs_sb->tlink_tree;
4410 struct rb_node *node = rb_first(root);
4411 struct rb_node *tmp;
4412 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004413
Jeff Laytonb647c352010-10-28 11:16:44 -04004414 /*
4415 * Because we drop the spinlock in the loop in order to put the tlink
4416 * it's not guarded against removal of links from the tree. The only
4417 * places that remove entries from the tree are this function and
4418 * umounts. Because this function is non-reentrant and is canceled
4419 * before umount can proceed, this is safe.
4420 */
4421 spin_lock(&cifs_sb->tlink_tree_lock);
4422 node = rb_first(root);
4423 while (node != NULL) {
4424 tmp = node;
4425 node = rb_next(tmp);
4426 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4427
4428 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4429 atomic_read(&tlink->tl_count) != 0 ||
4430 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4431 continue;
4432
4433 cifs_get_tlink(tlink);
4434 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4435 rb_erase(tmp, root);
4436
Jeff Layton2de970f2010-10-06 19:51:12 -04004437 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004438 cifs_put_tlink(tlink);
4439 spin_lock(&cifs_sb->tlink_tree_lock);
4440 }
4441 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004442
Jeff Laytonda472fc2012-03-23 14:40:53 -04004443 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004444 TLINK_IDLE_EXPIRE);
4445}