blob: 4898759d97cc6be513357d1f8b9dc5a73ef6dda2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve Frenchd185cda2009-04-30 17:45:10 +00004 * Copyright (C) International Business Machines Corp., 2002,2009
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
24#include <linux/list.h>
25#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070031#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070032#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000033#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070034#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080035#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040036#include <linux/namei.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <asm/uaccess.h>
38#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040039#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040040#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050041#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000042#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040043#include <linux/parser.h>
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include "cifspdu.h"
46#include "cifsglob.h"
47#include "cifsproto.h"
48#include "cifs_unicode.h"
49#include "cifs_debug.h"
50#include "cifs_fs_sb.h"
51#include "ntlmssp.h"
52#include "nterr.h"
53#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053054#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#define CIFS_PORT 445
57#define RFC1001_PORT 139
58
Jeff Laytonc74093b2011-01-11 07:24:23 -050059/* SMB echo "timeout" -- FIXME: tunable? */
60#define SMB_ECHO_INTERVAL (60 * HZ)
61
Linus Torvalds1da177e2005-04-16 15:20:36 -070062extern mempool_t *cifs_req_poolp;
63
Jeff Layton2de970f2010-10-06 19:51:12 -040064/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040065#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040066#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040067
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040068enum {
69
70 /* Mount options that take no arguments */
71 Opt_user_xattr, Opt_nouser_xattr,
72 Opt_forceuid, Opt_noforceuid,
73 Opt_noblocksend, Opt_noautotune,
74 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
75 Opt_mapchars, Opt_nomapchars, Opt_sfu,
76 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
77 Opt_noposixpaths, Opt_nounix,
78 Opt_nocase,
79 Opt_brl, Opt_nobrl,
80 Opt_forcemandatorylock, Opt_setuids,
81 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
82 Opt_nohard, Opt_nosoft,
83 Opt_nointr, Opt_intr,
84 Opt_nostrictsync, Opt_strictsync,
85 Opt_serverino, Opt_noserverino,
86 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
87 Opt_acl, Opt_noacl, Opt_locallease,
88 Opt_sign, Opt_seal, Opt_direct,
89 Opt_strictcache, Opt_noac,
90 Opt_fsc, Opt_mfsymlinks,
Jeff Laytond8162552012-03-23 14:40:56 -040091 Opt_multiuser, Opt_sloppy,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040092
93 /* Mount options which take numeric value */
94 Opt_backupuid, Opt_backupgid, Opt_uid,
95 Opt_cruid, Opt_gid, Opt_file_mode,
96 Opt_dirmode, Opt_port,
97 Opt_rsize, Opt_wsize, Opt_actimeo,
98
99 /* Mount options which take string value */
100 Opt_user, Opt_pass, Opt_ip,
101 Opt_unc, Opt_domain,
102 Opt_srcaddr, Opt_prefixpath,
103 Opt_iocharset, Opt_sockopt,
104 Opt_netbiosname, Opt_servern,
Jeff Layton15b6a472012-05-16 07:50:15 -0400105 Opt_ver, 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" },
213 { Opt_ver, "vers=%s" },
214 { Opt_ver, "version=%s" },
215 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400216 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400217
218 { Opt_ignore, "cred" },
219 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400220 { Opt_ignore, "cred=%s" },
221 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400222 { Opt_ignore, "guest" },
223 { Opt_ignore, "rw" },
224 { Opt_ignore, "ro" },
225 { Opt_ignore, "suid" },
226 { Opt_ignore, "nosuid" },
227 { Opt_ignore, "exec" },
228 { Opt_ignore, "noexec" },
229 { Opt_ignore, "nodev" },
230 { Opt_ignore, "noauto" },
231 { Opt_ignore, "dev" },
232 { Opt_ignore, "mand" },
233 { Opt_ignore, "nomand" },
234 { Opt_ignore, "_netdev" },
235
236 { Opt_err, NULL }
237};
238
239enum {
240 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
241 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
242 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i,
243 Opt_sec_nontlm, Opt_sec_lanman,
244 Opt_sec_none,
245
246 Opt_sec_err
247};
248
249static const match_table_t cifs_secflavor_tokens = {
250 { Opt_sec_krb5, "krb5" },
251 { Opt_sec_krb5i, "krb5i" },
252 { Opt_sec_krb5p, "krb5p" },
253 { Opt_sec_ntlmsspi, "ntlmsspi" },
254 { Opt_sec_ntlmssp, "ntlmssp" },
255 { Opt_ntlm, "ntlm" },
256 { Opt_sec_ntlmi, "ntlmi" },
257 { Opt_sec_ntlmv2i, "ntlmv2i" },
258 { Opt_sec_nontlm, "nontlm" },
259 { Opt_sec_lanman, "lanman" },
260 { Opt_sec_none, "none" },
261
262 { Opt_sec_err, NULL }
263};
264
Jeff Layton15b6a472012-05-16 07:50:15 -0400265/* cache flavors */
266enum {
267 Opt_cache_loose,
268 Opt_cache_strict,
269 Opt_cache_none,
270 Opt_cache_err
271};
272
273static const match_table_t cifs_cacheflavor_tokens = {
274 { Opt_cache_loose, "loose" },
275 { Opt_cache_strict, "strict" },
276 { Opt_cache_none, "none" },
277 { Opt_cache_err, NULL }
278};
279
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300280static int ip_connect(struct TCP_Server_Info *server);
281static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400282static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400283static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -0400284static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
285 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Jeff Laytond5c56052008-12-01 18:42:33 -0500287/*
288 * cifs tcp session reconnection
289 *
290 * mark tcp session as reconnecting so temporarily locked
291 * mark all smb sessions as reconnecting for tcp session
292 * reconnect tcp session
293 * wake up waiters on reconnection? - (not needed currently)
294 */
Steve French2cd646a2006-09-28 19:43:08 +0000295static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296cifs_reconnect(struct TCP_Server_Info *server)
297{
298 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500299 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000300 struct cifs_ses *ses;
301 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000302 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400303 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +0000304
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000306 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000307 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 next time through the loop */
309 spin_unlock(&GlobalMid_Lock);
310 return rc;
311 } else
312 server->tcpStatus = CifsNeedReconnect;
313 spin_unlock(&GlobalMid_Lock);
314 server->maxBuf = 0;
315
Joe Perchesb6b38f72010-04-21 03:50:45 +0000316 cFYI(1, "Reconnecting tcp session");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
318 /* before reconnecting the tcp session, mark the smb session (uid)
319 and the tid bad so they are not used until reconnected */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500320 cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530321 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500322 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000323 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500324 ses->need_reconnect = true;
325 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500326 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000327 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500328 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530331 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 /* do not want to be sending data on a socket we are freeing */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500334 cFYI(1, "%s: tearing down socket", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500335 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000336 if (server->ssocket) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000337 cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
338 server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800339 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000340 cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx",
Steve French467a8f82007-06-27 22:41:32 +0000341 server->ssocket->state,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000342 server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 sock_release(server->ssocket);
344 server->ssocket = NULL;
345 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500346 server->sequence_number = 0;
347 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500348 kfree(server->session_key.response);
349 server->session_key.response = NULL;
350 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000351 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500352 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500354 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400355 INIT_LIST_HEAD(&retry_list);
356 cFYI(1, "%s: moving mids to private list", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500358 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
359 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400360 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
361 mid_entry->mid_state = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400362 list_move(&mid_entry->qhead, &retry_list);
363 }
364 spin_unlock(&GlobalMid_Lock);
365
366 cFYI(1, "%s: issuing mid callbacks", __func__);
367 list_for_each_safe(tmp, tmp2, &retry_list) {
368 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500369 list_del_init(&mid_entry->qhead);
370 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400373 do {
Steve French6c3d8902006-07-31 22:46:20 +0000374 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300375
376 /* we should try only the port we connected to before */
377 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000378 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000379 cFYI(1, "reconnect error %d", rc);
Steve French0cb766a2005-04-28 22:41:11 -0700380 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 } else {
382 atomic_inc(&tcpSesReconnectCount);
383 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000384 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000385 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000386 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400388 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500389
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 return rc;
391}
392
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000393/*
Steve Frenche4eb2952005-04-28 22:41:09 -0700394 return codes:
395 0 not a transact2, or all data present
396 >0 transact2 with that much data missing
397 -EINVAL = invalid transact2
398
399 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400400static int check2ndT2(char *buf)
Steve Frenche4eb2952005-04-28 22:41:09 -0700401{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400402 struct smb_hdr *pSMB = (struct smb_hdr *)buf;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000403 struct smb_t2_rsp *pSMBt;
Steve Frenche4eb2952005-04-28 22:41:09 -0700404 int remaining;
Jeff Layton26ec2542011-01-20 13:36:51 -0500405 __u16 total_data_size, data_in_this_rsp;
Steve Frenche4eb2952005-04-28 22:41:09 -0700406
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000407 if (pSMB->Command != SMB_COM_TRANSACTION2)
Steve Frenche4eb2952005-04-28 22:41:09 -0700408 return 0;
409
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000410 /* check for plausible wct, bcc and t2 data and parm sizes */
411 /* check for parm and data offset going beyond end of smb */
412 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
Joe Perchesb6b38f72010-04-21 03:50:45 +0000413 cFYI(1, "invalid transact2 word count");
Steve Frenche4eb2952005-04-28 22:41:09 -0700414 return -EINVAL;
415 }
416
417 pSMBt = (struct smb_t2_rsp *)pSMB;
418
Jeff Layton26ec2542011-01-20 13:36:51 -0500419 total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
420 data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700421
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400422 if (total_data_size == data_in_this_rsp)
Steve Frenche4eb2952005-04-28 22:41:09 -0700423 return 0;
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400424 else if (total_data_size < data_in_this_rsp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000425 cFYI(1, "total data %d smaller than data in frame %d",
426 total_data_size, data_in_this_rsp);
Steve Frenche4eb2952005-04-28 22:41:09 -0700427 return -EINVAL;
Steve Frenche4eb2952005-04-28 22:41:09 -0700428 }
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400429
430 remaining = total_data_size - data_in_this_rsp;
431
432 cFYI(1, "missing %d bytes from transact2, check next response",
433 remaining);
Jeff Laytonc974bef2011-10-11 06:41:32 -0400434 if (total_data_size > CIFSMaxBufSize) {
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400435 cERROR(1, "TotalDataSize %d is over maximum buffer %d",
Jeff Laytonc974bef2011-10-11 06:41:32 -0400436 total_data_size, CIFSMaxBufSize);
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400437 return -EINVAL;
438 }
439 return remaining;
Steve Frenche4eb2952005-04-28 22:41:09 -0700440}
441
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400442static int coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
Steve Frenche4eb2952005-04-28 22:41:09 -0700443{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400444 struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
445 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500446 char *data_area_of_tgt;
447 char *data_area_of_src;
Jeff Layton26ec2542011-01-20 13:36:51 -0500448 int remaining;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500449 unsigned int byte_count, total_in_tgt;
450 __u16 tgt_total_cnt, src_total_cnt, total_in_src;
Steve Frenche4eb2952005-04-28 22:41:09 -0700451
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500452 src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
453 tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700454
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500455 if (tgt_total_cnt != src_total_cnt)
456 cFYI(1, "total data count of primary and secondary t2 differ "
457 "source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
Steve Frenche4eb2952005-04-28 22:41:09 -0700458
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500459 total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700460
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500461 remaining = tgt_total_cnt - total_in_tgt;
Steve French50c2f752007-07-13 00:33:32 +0000462
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500463 if (remaining < 0) {
464 cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
465 "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400466 return -EPROTO;
Steve Frenche4eb2952005-04-28 22:41:09 -0700467 }
468
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500469 if (remaining == 0) {
470 /* nothing to do, ignore */
471 cFYI(1, "no more data remains");
472 return 0;
473 }
474
475 total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
476 if (remaining < total_in_src)
477 cFYI(1, "transact2 2nd response contains too much data");
478
Steve Frenche4eb2952005-04-28 22:41:09 -0700479 /* find end of first SMB data area */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500480 data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
Jeff Layton26ec2542011-01-20 13:36:51 -0500481 get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500482
Steve Frenche4eb2952005-04-28 22:41:09 -0700483 /* validate target area */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500484 data_area_of_src = (char *)&pSMBs->hdr.Protocol +
485 get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
Steve Frenche4eb2952005-04-28 22:41:09 -0700486
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500487 data_area_of_tgt += total_in_tgt;
Steve Frenche4eb2952005-04-28 22:41:09 -0700488
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500489 total_in_tgt += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400490 /* is the result too big for the field? */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500491 if (total_in_tgt > USHRT_MAX) {
492 cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400493 return -EPROTO;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500494 }
495 put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400496
497 /* fix up the BCC */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400498 byte_count = get_bcc(target_hdr);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500499 byte_count += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400500 /* is the result too big for the field? */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500501 if (byte_count > USHRT_MAX) {
502 cFYI(1, "coalesced BCC too large (%u)", byte_count);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400503 return -EPROTO;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500504 }
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400505 put_bcc(byte_count, target_hdr);
Steve Frenche4eb2952005-04-28 22:41:09 -0700506
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400507 byte_count = be32_to_cpu(target_hdr->smb_buf_length);
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500508 byte_count += total_in_src;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400509 /* don't allow buffer to overflow */
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500510 if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
511 cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400512 return -ENOBUFS;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500513 }
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400514 target_hdr->smb_buf_length = cpu_to_be32(byte_count);
Steve Frenche4eb2952005-04-28 22:41:09 -0700515
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500516 /* copy second buffer into end of first buffer */
517 memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400518
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500519 if (remaining != total_in_src) {
520 /* more responses to go */
521 cFYI(1, "waiting for more secondary responses");
Steve Frenche4eb2952005-04-28 22:41:09 -0700522 return 1;
Jeff Laytonf5fffce2012-01-17 13:49:17 -0500523 }
524
525 /* we are done */
526 cFYI(1, "found the last secondary response");
527 return 0;
Steve Frenche4eb2952005-04-28 22:41:09 -0700528}
529
Jeff Laytonc74093b2011-01-11 07:24:23 -0500530static void
531cifs_echo_request(struct work_struct *work)
532{
533 int rc;
534 struct TCP_Server_Info *server = container_of(work,
535 struct TCP_Server_Info, echo.work);
536
Jeff Layton247ec9b2011-02-04 17:09:50 -0500537 /*
Jeff Layton195291e2011-02-09 12:01:42 -0500538 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is
539 * done, which is indicated by maxBuf != 0. Also, no need to ping if
540 * we got a response recently
Jeff Layton247ec9b2011-02-04 17:09:50 -0500541 */
Jeff Layton195291e2011-02-09 12:01:42 -0500542 if (server->maxBuf == 0 ||
Jeff Layton247ec9b2011-02-04 17:09:50 -0500543 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500544 goto requeue_echo;
545
546 rc = CIFSSMBEcho(server);
547 if (rc)
548 cFYI(1, "Unable to send echo request to server: %s",
549 server->hostname);
550
551requeue_echo:
Jeff Laytonda472fc2012-03-23 14:40:53 -0400552 queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500553}
554
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400555static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400556allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400557{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400558 if (!server->bigbuf) {
559 server->bigbuf = (char *)cifs_buf_get();
560 if (!server->bigbuf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400561 cERROR(1, "No memory for large SMB response");
562 msleep(3000);
563 /* retry will check if exiting */
564 return false;
565 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400566 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400567 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400568 memset(server->bigbuf, 0, header_size());
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400569 }
570
Jeff Layton2a37ef92011-10-19 15:29:23 -0400571 if (!server->smallbuf) {
572 server->smallbuf = (char *)cifs_small_buf_get();
573 if (!server->smallbuf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400574 cERROR(1, "No memory for SMB response");
575 msleep(1000);
576 /* retry will check if exiting */
577 return false;
578 }
579 /* beginning of smb buffer is cleared in our buf_get */
580 } else {
581 /* if existing small buf clear beginning */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400582 memset(server->smallbuf, 0, header_size());
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400583 }
584
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400585 return true;
586}
587
Jeff Laytonba749e62011-10-11 06:41:32 -0400588static bool
589server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400590{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300591 /*
592 * We need to wait 2 echo intervals to make sure we handle such
593 * situations right:
594 * 1s client sends a normal SMB request
595 * 2s client gets a response
596 * 30s echo workqueue job pops, and decides we got a response recently
597 * and don't need to send another
598 * ...
599 * 65s kernel_recvmsg times out, and we see that we haven't gotten
600 * a response in >60s.
601 */
602 if (server->tcpStatus == CifsGood &&
603 time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) {
Jeff Laytonba749e62011-10-11 06:41:32 -0400604 cERROR(1, "Server %s has not responded in %d seconds. "
605 "Reconnecting...", server->hostname,
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300606 (2 * SMB_ECHO_INTERVAL) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400607 cifs_reconnect(server);
608 wake_up(&server->response_q);
609 return true;
610 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400611
Jeff Laytonba749e62011-10-11 06:41:32 -0400612 return false;
613}
614
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400615/*
616 * kvec_array_init - clone a kvec array, and advance into it
617 * @new: pointer to memory for cloned array
618 * @iov: pointer to original array
619 * @nr_segs: number of members in original array
620 * @bytes: number of bytes to advance into the cloned array
621 *
622 * This function will copy the array provided in iov to a section of memory
623 * and advance the specified number of bytes into the new array. It returns
624 * the number of segments in the new array. "new" must be at least as big as
625 * the original iov array.
626 */
627static unsigned int
628kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
629 size_t bytes)
630{
631 size_t base = 0;
632
633 while (bytes || !iov->iov_len) {
634 int copy = min(bytes, iov->iov_len);
635
636 bytes -= copy;
637 base += copy;
638 if (iov->iov_len == base) {
639 iov++;
640 nr_segs--;
641 base = 0;
642 }
643 }
644 memcpy(new, iov, sizeof(*iov) * nr_segs);
645 new->iov_base += base;
646 new->iov_len -= base;
647 return nr_segs;
648}
649
Jeff Layton1041e3f2011-10-19 15:28:27 -0400650static struct kvec *
651get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
652{
653 struct kvec *new_iov;
654
655 if (server->iov && nr_segs <= server->nr_iov)
656 return server->iov;
657
658 /* not big enough -- allocate a new one and release the old */
659 new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
660 if (new_iov) {
661 kfree(server->iov);
662 server->iov = new_iov;
663 server->nr_iov = nr_segs;
664 }
665 return new_iov;
666}
667
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400668int
669cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
670 unsigned int nr_segs, unsigned int to_read)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400671{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400672 int length = 0;
673 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400674 unsigned int segs;
Jeff Laytone831e6c2011-10-11 06:41:32 -0400675 struct msghdr smb_msg;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400676 struct kvec *iov;
677
Jeff Layton1041e3f2011-10-19 15:28:27 -0400678 iov = get_server_iovec(server, nr_segs);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400679 if (!iov)
680 return -ENOMEM;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400681
Jeff Laytone831e6c2011-10-11 06:41:32 -0400682 smb_msg.msg_control = NULL;
683 smb_msg.msg_controllen = 0;
684
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400685 for (total_read = 0; to_read; total_read += length, to_read -= length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500686 try_to_freeze();
687
Jeff Laytonba749e62011-10-11 06:41:32 -0400688 if (server_unresponsive(server)) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400689 total_read = -EAGAIN;
Jeff Laytonba749e62011-10-11 06:41:32 -0400690 break;
691 }
692
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400693 segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
694
695 length = kernel_recvmsg(server->ssocket, &smb_msg,
696 iov, segs, to_read, 0);
697
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400698 if (server->tcpStatus == CifsExiting) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400699 total_read = -ESHUTDOWN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400700 break;
701 } else if (server->tcpStatus == CifsNeedReconnect) {
702 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400703 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400704 break;
705 } else if (length == -ERESTARTSYS ||
706 length == -EAGAIN ||
707 length == -EINTR) {
708 /*
709 * Minimum sleep to prevent looping, allowing socket
710 * to clear and app threads to set tcpStatus
711 * CifsNeedReconnect if server hung.
712 */
713 usleep_range(1000, 2000);
714 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400715 continue;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400716 } else if (length <= 0) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400717 cFYI(1, "Received no data or error: expecting %d "
718 "got %d", to_read, length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400719 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400720 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400721 break;
722 }
723 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400724 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400725}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400726
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400727int
728cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
729 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400730{
731 struct kvec iov;
732
733 iov.iov_base = buf;
734 iov.iov_len = to_read;
735
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400736 return cifs_readv_from_socket(server, &iov, 1, to_read);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400737}
738
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400739static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400740is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400741{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400742 /*
743 * The first byte big endian of the length field,
744 * is actually not part of the length but the type
745 * with the most common, zero, as regular data.
746 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400747 switch (type) {
748 case RFC1002_SESSION_MESSAGE:
749 /* Regular SMB response */
750 return true;
751 case RFC1002_SESSION_KEEP_ALIVE:
752 cFYI(1, "RFC 1002 session keep alive");
753 break;
754 case RFC1002_POSITIVE_SESSION_RESPONSE:
755 cFYI(1, "RFC 1002 positive session response");
756 break;
757 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400758 /*
759 * We get this from Windows 98 instead of an error on
760 * SMB negprot response.
761 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400762 cFYI(1, "RFC 1002 negative session response");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400763 /* give server a second to clean up */
764 msleep(1000);
765 /*
766 * Always try 445 first on reconnect since we get NACK
767 * on some if we ever connected to port 139 (the NACK
768 * is since we do not begin with RFC1001 session
769 * initialize frame).
770 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400771 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400772 cifs_reconnect(server);
773 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400774 break;
775 default:
776 cERROR(1, "RFC 1002 unknown response type 0x%x", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400777 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400778 }
779
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400780 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400781}
782
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400783static struct mid_q_entry *
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400784find_mid(struct TCP_Server_Info *server, char *buffer)
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400785{
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400786 struct smb_hdr *buf = (struct smb_hdr *)buffer;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400787 struct mid_q_entry *mid;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400788
789 spin_lock(&GlobalMid_Lock);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400790 list_for_each_entry(mid, &server->pending_mid_q, qhead) {
791 if (mid->mid == buf->Mid &&
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400792 mid->mid_state == MID_REQUEST_SUBMITTED &&
793 le16_to_cpu(mid->command) == buf->Command) {
Jeff Laytonea1f4502011-10-19 15:29:05 -0400794 spin_unlock(&GlobalMid_Lock);
795 return mid;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400796 }
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400797 }
798 spin_unlock(&GlobalMid_Lock);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400799 return NULL;
800}
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400801
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400802void
803dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400804{
805#ifdef CONFIG_CIFS_STATS2
806 mid->when_received = jiffies;
807#endif
808 spin_lock(&GlobalMid_Lock);
809 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400810 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400811 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400812 mid->mid_state = MID_RESPONSE_MALFORMED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400813 list_del_init(&mid->qhead);
814 spin_unlock(&GlobalMid_Lock);
815}
816
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400817static void
818handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400819 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400820{
Jeff Laytonffc00e22011-10-19 15:29:13 -0400821 if (malformed == 0 && check2ndT2(buf) > 0) {
822 mid->multiRsp = true;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400823 if (mid->resp_buf) {
824 /* merge response - fix up 1st*/
Jeff Laytonffc00e22011-10-19 15:29:13 -0400825 malformed = coalesce_t2(buf, mid->resp_buf);
826 if (malformed > 0)
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400827 return;
Jeff Laytonffc00e22011-10-19 15:29:13 -0400828
Jeff Laytonea1f4502011-10-19 15:29:05 -0400829 /* All parts received or packet is malformed. */
830 mid->multiEnd = true;
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400831 return dequeue_mid(mid, malformed);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400832 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400833 if (!server->large_buf) {
Jeff Laytonea1f4502011-10-19 15:29:05 -0400834 /*FIXME: switch to already allocated largebuf?*/
835 cERROR(1, "1st trans2 resp needs bigbuf");
836 } else {
837 /* Have first buffer */
838 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400839 mid->large_buf = true;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400840 server->bigbuf = NULL;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400841 }
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400842 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400843 }
844 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400845 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400846 /* Was previous buf put in mpx struct for multi-rsp? */
847 if (!mid->multiRsp) {
848 /* smb buffer will be freed by user thread */
849 if (server->large_buf)
850 server->bigbuf = NULL;
851 else
852 server->smallbuf = NULL;
853 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400854 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400855}
856
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400857static void clean_demultiplex_info(struct TCP_Server_Info *server)
858{
859 int length;
860
861 /* take it off the list, if it's not already */
862 spin_lock(&cifs_tcp_ses_lock);
863 list_del_init(&server->tcp_ses_list);
864 spin_unlock(&cifs_tcp_ses_lock);
865
866 spin_lock(&GlobalMid_Lock);
867 server->tcpStatus = CifsExiting;
868 spin_unlock(&GlobalMid_Lock);
869 wake_up_all(&server->response_q);
870
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400871 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300872 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400873 if (server->credits <= 0)
874 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300875 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400876 /*
877 * Although there should not be any requests blocked on this queue it
878 * can not hurt to be paranoid and try to wake up requests that may
879 * haven been blocked when more than 50 at time were on the wire to the
880 * same server - they now will see the session is in exit state and get
881 * out of SendReceive.
882 */
883 wake_up_all(&server->request_q);
884 /* give those requests time to exit */
885 msleep(125);
886
887 if (server->ssocket) {
888 sock_release(server->ssocket);
889 server->ssocket = NULL;
890 }
891
892 if (!list_empty(&server->pending_mid_q)) {
893 struct list_head dispose_list;
894 struct mid_q_entry *mid_entry;
895 struct list_head *tmp, *tmp2;
896
897 INIT_LIST_HEAD(&dispose_list);
898 spin_lock(&GlobalMid_Lock);
899 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
900 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400901 cFYI(1, "Clearing mid 0x%llx", mid_entry->mid);
902 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400903 list_move(&mid_entry->qhead, &dispose_list);
904 }
905 spin_unlock(&GlobalMid_Lock);
906
907 /* now walk dispose list and issue callbacks */
908 list_for_each_safe(tmp, tmp2, &dispose_list) {
909 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400910 cFYI(1, "Callback mid 0x%llx", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400911 list_del_init(&mid_entry->qhead);
912 mid_entry->callback(mid_entry);
913 }
914 /* 1/8th of sec is more than enough time for them to exit */
915 msleep(125);
916 }
917
918 if (!list_empty(&server->pending_mid_q)) {
919 /*
920 * mpx threads have not exited yet give them at least the smb
921 * send timeout time for long ops.
922 *
923 * Due to delays on oplock break requests, we need to wait at
924 * least 45 seconds before giving up on a request getting a
925 * response and going ahead and killing cifsd.
926 */
927 cFYI(1, "Wait for exit from demultiplex thread");
928 msleep(46000);
929 /*
930 * If threads still have not exited they are probably never
931 * coming home not much else we can do but free the memory.
932 */
933 }
934
935 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400936 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400937 kfree(server);
938
939 length = atomic_dec_return(&tcpSesAllocCount);
940 if (length > 0)
941 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
942 GFP_KERNEL);
943}
944
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400945static int
Jeff Laytone9097ab2011-10-19 15:29:40 -0400946standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
947{
948 int length;
949 char *buf = server->smallbuf;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400950 unsigned int pdu_length = get_rfc1002_length(buf);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400951
952 /* make sure this will fit in a large buffer */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400953 if (pdu_length > CIFSMaxBufSize + max_header_size() - 4) {
Jeff Laytone9097ab2011-10-19 15:29:40 -0400954 cERROR(1, "SMB response too long (%u bytes)",
955 pdu_length);
956 cifs_reconnect(server);
957 wake_up(&server->response_q);
958 return -EAGAIN;
959 }
960
961 /* switch to large buffer if too big for a small one */
962 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
963 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400964 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400965 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400966 }
967
968 /* now read the rest */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400969 length = cifs_read_from_socket(server, buf + header_size() - 1,
970 pdu_length - header_size() + 1 + 4);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400971 if (length < 0)
972 return length;
973 server->total_read += length;
974
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400975 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400976
977 /*
978 * We know that we received enough to get to the MID as we
979 * checked the pdu_length earlier. Now check to see
980 * if the rest of the header is OK. We borrow the length
981 * var for the rest of the loop to avoid a new stack var.
982 *
983 * 48 bytes is enough to display the header and a little bit
984 * into the payload for debugging purposes.
985 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400986 length = checkSMB(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -0400987 if (length != 0)
988 cifs_dump_mem("Bad SMB: ", buf,
989 min_t(unsigned int, server->total_read, 48));
990
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500991 if (!mid)
992 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400993
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400994 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -0500995 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -0400996}
997
998static int
Al Viro7c97c202011-06-21 08:51:28 -0400999cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000{
1001 int length;
Al Viro7c97c202011-06-21 08:51:28 -04001002 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001003 unsigned int pdu_length;
1004 char *buf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 struct task_struct *task_to_wake = NULL;
1006 struct mid_q_entry *mid_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 current->flags |= PF_MEMALLOC;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001009 cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001010
1011 length = atomic_inc_return(&tcpSesAllocCount);
1012 if (length > 1)
Steve French26f57362007-08-30 22:09:15 +00001013 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
1014 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001016 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +00001017 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001018 if (try_to_freeze())
1019 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001020
Jeff Layton2a37ef92011-10-19 15:29:23 -04001021 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001022 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001023
Jeff Layton2a37ef92011-10-19 15:29:23 -04001024 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001025 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001026 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001027
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001028 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001029 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001030 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001031 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001032
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001033 /*
1034 * The right amount was read from socket - 4 bytes,
1035 * so we can now interpret the length field.
1036 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001037 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001038
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001039 cFYI(1, "RFC1002 header 0x%x", pdu_length);
1040 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001041 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001042
Jeff Layton89482a52011-10-19 15:28:57 -04001043 /* make sure we have enough to get to the MID */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001044 if (pdu_length < header_size() - 1 - 4) {
Jeff Layton89482a52011-10-19 15:28:57 -04001045 cERROR(1, "SMB response too short (%u bytes)",
1046 pdu_length);
1047 cifs_reconnect(server);
1048 wake_up(&server->response_q);
1049 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001050 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001051
Jeff Layton89482a52011-10-19 15:28:57 -04001052 /* read down to the MID */
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001053 length = cifs_read_from_socket(server, buf + 4,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001054 header_size() - 1 - 4);
Jeff Layton89482a52011-10-19 15:28:57 -04001055 if (length < 0)
1056 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001057 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001058
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001059 mid_entry = find_mid(server, buf);
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001060
Jeff Layton44d22d82011-10-19 15:29:49 -04001061 if (!mid_entry || !mid_entry->receive)
1062 length = standard_receive3(server, mid_entry);
1063 else
1064 length = mid_entry->receive(server, mid_entry);
1065
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001066 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -07001067 continue;
1068
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001069 if (server->large_buf)
Jeff Laytone9097ab2011-10-19 15:29:40 -04001070 buf = server->bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -07001071
Steve Frenchfda35942011-01-20 18:06:34 +00001072 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -05001073 if (mid_entry != NULL) {
Jeff Layton2a37ef92011-10-19 15:29:23 -04001074 if (!mid_entry->multiRsp || mid_entry->multiEnd)
1075 mid_entry->callback(mid_entry);
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001076 } else if (!is_valid_oplock_break(buf, server)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001077 cERROR(1, "No task to wake, unknown frame received! "
Jeff Layton80975312011-01-11 07:24:02 -05001078 "NumMids %d", atomic_read(&midCount));
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001079 cifs_dump_mem("Received Data is: ", buf, header_size());
Steve French39798772006-05-31 22:40:51 +00001080#ifdef CONFIG_CIFS_DEBUG2
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001081 cifs_dump_detail(buf);
Steve French39798772006-05-31 22:40:51 +00001082 cifs_dump_mids(server);
1083#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +00001084
Steve Frenche4eb2952005-04-28 22:41:09 -07001085 }
1086 } /* end while !EXITING */
1087
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001088 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001089 cifs_buf_release(server->bigbuf);
1090 if (server->smallbuf) /* no sense logging a debug message if NULL */
1091 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001093 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001094 clean_demultiplex_info(server);
Steve French50c2f752007-07-13 00:33:32 +00001095
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04001096 /* if server->tsk was NULL then wait for a signal before exiting */
1097 if (!task_to_wake) {
1098 set_current_state(TASK_INTERRUPTIBLE);
1099 while (!signal_pending(current)) {
1100 schedule();
1101 set_current_state(TASK_INTERRUPTIBLE);
1102 }
1103 set_current_state(TASK_RUNNING);
1104 }
1105
Jeff Layton0468a2c2008-12-01 07:09:35 -05001106 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
1108
Jeff Laytonc359cf32007-11-16 22:22:06 +00001109/* extract the host portion of the UNC string */
1110static char *
1111extract_hostname(const char *unc)
1112{
1113 const char *src;
1114 char *dst, *delim;
1115 unsigned int len;
1116
1117 /* skip double chars at beginning of string */
1118 /* BB: check validity of these bytes? */
1119 src = unc + 2;
1120
1121 /* delimiter between hostname and sharename is always '\\' now */
1122 delim = strchr(src, '\\');
1123 if (!delim)
1124 return ERR_PTR(-EINVAL);
1125
1126 len = delim - src;
1127 dst = kmalloc((len + 1), GFP_KERNEL);
1128 if (dst == NULL)
1129 return ERR_PTR(-ENOMEM);
1130
1131 memcpy(dst, src, len);
1132 dst[len] = '\0';
1133
1134 return dst;
1135}
1136
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001137static int get_option_ul(substring_t args[], unsigned long *option)
1138{
1139 int rc;
1140 char *string;
1141
1142 string = match_strdup(args);
1143 if (string == NULL)
1144 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001145 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001146 kfree(string);
1147
1148 return rc;
1149}
1150
1151
1152static int cifs_parse_security_flavors(char *value,
1153 struct smb_vol *vol)
1154{
1155
1156 substring_t args[MAX_OPT_ARGS];
1157
1158 switch (match_token(value, cifs_secflavor_tokens, args)) {
1159 case Opt_sec_krb5:
1160 vol->secFlg |= CIFSSEC_MAY_KRB5;
1161 break;
1162 case Opt_sec_krb5i:
1163 vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN;
1164 break;
1165 case Opt_sec_krb5p:
1166 /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */
1167 cERROR(1, "Krb5 cifs privacy not supported");
1168 break;
1169 case Opt_sec_ntlmssp:
1170 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
1171 break;
1172 case Opt_sec_ntlmsspi:
1173 vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN;
1174 break;
1175 case Opt_ntlm:
1176 /* ntlm is default so can be turned off too */
1177 vol->secFlg |= CIFSSEC_MAY_NTLM;
1178 break;
1179 case Opt_sec_ntlmi:
1180 vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN;
1181 break;
1182 case Opt_sec_nontlm:
1183 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1184 break;
1185 case Opt_sec_ntlmv2i:
1186 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN;
1187 break;
1188#ifdef CONFIG_CIFS_WEAK_PW_HASH
1189 case Opt_sec_lanman:
1190 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1191 break;
1192#endif
1193 case Opt_sec_none:
1194 vol->nullauth = 1;
1195 break;
1196 default:
1197 cERROR(1, "bad security option: %s", value);
1198 return 1;
1199 }
1200
1201 return 0;
1202}
1203
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001205cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1206{
1207 substring_t args[MAX_OPT_ARGS];
1208
1209 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1210 case Opt_cache_loose:
1211 vol->direct_io = false;
1212 vol->strict_io = false;
1213 break;
1214 case Opt_cache_strict:
1215 vol->direct_io = false;
1216 vol->strict_io = true;
1217 break;
1218 case Opt_cache_none:
1219 vol->direct_io = true;
1220 vol->strict_io = false;
1221 break;
1222 default:
1223 cERROR(1, "bad cache= option: %s", value);
1224 return 1;
1225 }
1226 return 0;
1227}
1228
1229static int
Sean Finneyb9468452011-04-11 13:19:32 +00001230cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +00001231 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001233 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001234 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 unsigned int temp_len, i, j;
1236 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001237 short int override_uid = -1;
1238 short int override_gid = -1;
1239 bool uid_specified = false;
1240 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001241 bool sloppy = false;
1242 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001243 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001244 char *string = NULL;
1245 char *tmp_end, *value;
1246 char delim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
1248 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001249 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001250 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Jeff Layton88463992010-11-22 15:31:03 -05001252 /*
1253 * does not have to be perfect mapping since field is
1254 * informational, only used for servers that do not support
1255 * port 445 and it can be overridden at mount time
1256 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001257 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1258 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001259 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1260
Jeff Layton1397f2e2011-01-07 11:30:28 -05001261 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001262 /* null target name indicates to use *SMBSERVR default called name
1263 if we end up sending RFC1001 session initialize */
1264 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001265 vol->cred_uid = current_uid();
1266 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001267 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001268
1269 /* default to only allowing write access to owner of the mount */
1270 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
1272 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001273 /* default is always to request posix paths. */
1274 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001275 /* default to using server inode numbers where available */
1276 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001277
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301278 vol->actimeo = CIFS_DEF_ACTIMEO;
1279
Sean Finneyb9468452011-04-11 13:19:32 +00001280 if (!mountdata)
1281 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Sean Finneyb9468452011-04-11 13:19:32 +00001283 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1284 if (!mountdata_copy)
1285 goto cifs_parse_mount_err;
1286
1287 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001288 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001289
Steve French50c2f752007-07-13 00:33:32 +00001290 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001291 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 separator[0] = options[4];
1293 options += 5;
1294 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001295 cFYI(1, "Null separator not allowed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 }
1297 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001298 vol->backupuid_specified = false; /* no backup intent for a user */
1299 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001302 substring_t args[MAX_OPT_ARGS];
1303 unsigned long option;
1304 int token;
1305
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 if (!*data)
1307 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001309 token = match_token(data, cifs_mount_option_tokens, args);
1310
1311 switch (token) {
1312
1313 /* Ingnore the following */
1314 case Opt_ignore:
1315 break;
1316
1317 /* Boolean values */
1318 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001320 break;
1321 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001323 break;
1324 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001325 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001326 break;
1327 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001328 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001329 break;
1330 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001331 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001332 break;
1333 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001334 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001335 break;
1336 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001338 break;
1339 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001341 break;
1342 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001344 break;
1345 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001347 break;
1348 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001349 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001350 break;
1351 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001352 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001353 break;
1354 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001355 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001356 break;
1357 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001358 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001359 break;
1360 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001361 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362 break;
1363 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001364 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001365 break;
1366 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001367 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001368 break;
1369 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001370 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371 break;
1372 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001373 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001374 break;
1375 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001376 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001377 break;
1378 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001379 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001380 /*
1381 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001382 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001383 * local vfs will do advisory
1384 */
Steve French50c2f752007-07-13 00:33:32 +00001385 if (vol->file_mode ==
1386 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001387 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001388 break;
1389 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001390 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001391 break;
1392 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001394 break;
1395 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001397 break;
1398 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001399 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001400 break;
1401 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001402 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001403 break;
1404 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001406 break;
1407 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001409 break;
1410 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001412 break;
1413 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001415 break;
1416 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001417 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001418 break;
1419 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001420 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001421 break;
1422 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001424 break;
1425 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001427 break;
1428 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001429 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001430 break;
1431 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001432 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001433 break;
1434 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001435 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001436 break;
1437 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001439 break;
1440 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001442 break;
1443 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001444 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001445 break;
1446 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001447 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001448 break;
1449 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001450 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001451 * is a per tree connection (mount) not a per socket
1452 * or per-smb connection option in the protocol
1453 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1454 */
Steve French95b1cb92008-05-15 16:44:38 +00001455 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001456 break;
1457 case Opt_direct:
Jeff Layton15b6a472012-05-16 07:50:15 -04001458 vol->direct_io = true;
1459 vol->strict_io = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001460 break;
1461 case Opt_strictcache:
Jeff Layton15b6a472012-05-16 07:50:15 -04001462 vol->direct_io = false;
1463 vol->strict_io = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001464 break;
1465 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001466 printk(KERN_WARNING "CIFS: Mount option noac not "
1467 "supported. Instead set "
1468 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001469 break;
1470 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301471#ifndef CONFIG_CIFS_FSCACHE
Jeff Layton83fb0862011-06-08 07:35:24 -04001472 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301473 "kernel config option set");
Sean Finneyb9468452011-04-11 13:19:32 +00001474 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301475#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301476 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001477 break;
1478 case Opt_mfsymlinks:
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001479 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001480 break;
1481 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001482 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001483 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001484 case Opt_sloppy:
1485 sloppy = true;
1486 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001487
1488 /* Numeric Values */
1489 case Opt_backupuid:
1490 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001491 cERROR(1, "%s: Invalid backupuid value",
1492 __func__);
1493 goto cifs_parse_mount_err;
1494 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001495 vol->backupuid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001496 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001497 break;
1498 case Opt_backupgid:
1499 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001500 cERROR(1, "%s: Invalid backupgid value",
1501 __func__);
1502 goto cifs_parse_mount_err;
1503 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001504 vol->backupgid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001505 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001506 break;
1507 case Opt_uid:
1508 if (get_option_ul(args, &option)) {
1509 cERROR(1, "%s: Invalid uid value",
1510 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001511 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001513 vol->linux_uid = option;
1514 uid_specified = true;
1515 break;
1516 case Opt_cruid:
1517 if (get_option_ul(args, &option)) {
1518 cERROR(1, "%s: Invalid cruid value",
1519 __func__);
1520 goto cifs_parse_mount_err;
1521 }
1522 vol->cred_uid = option;
1523 break;
1524 case Opt_gid:
1525 if (get_option_ul(args, &option)) {
1526 cERROR(1, "%s: Invalid gid value",
1527 __func__);
1528 goto cifs_parse_mount_err;
1529 }
1530 vol->linux_gid = option;
1531 gid_specified = true;
1532 break;
1533 case Opt_file_mode:
1534 if (get_option_ul(args, &option)) {
1535 cERROR(1, "%s: Invalid file_mode value",
1536 __func__);
1537 goto cifs_parse_mount_err;
1538 }
1539 vol->file_mode = option;
1540 break;
1541 case Opt_dirmode:
1542 if (get_option_ul(args, &option)) {
1543 cERROR(1, "%s: Invalid dir_mode value",
1544 __func__);
1545 goto cifs_parse_mount_err;
1546 }
1547 vol->dir_mode = option;
1548 break;
1549 case Opt_port:
1550 if (get_option_ul(args, &option)) {
1551 cERROR(1, "%s: Invalid port value",
1552 __func__);
1553 goto cifs_parse_mount_err;
1554 }
1555 vol->port = option;
1556 break;
1557 case Opt_rsize:
1558 if (get_option_ul(args, &option)) {
1559 cERROR(1, "%s: Invalid rsize value",
1560 __func__);
1561 goto cifs_parse_mount_err;
1562 }
1563 vol->rsize = option;
1564 break;
1565 case Opt_wsize:
1566 if (get_option_ul(args, &option)) {
1567 cERROR(1, "%s: Invalid wsize value",
1568 __func__);
1569 goto cifs_parse_mount_err;
1570 }
1571 vol->wsize = option;
1572 break;
1573 case Opt_actimeo:
1574 if (get_option_ul(args, &option)) {
1575 cERROR(1, "%s: Invalid actimeo value",
1576 __func__);
1577 goto cifs_parse_mount_err;
1578 }
1579 vol->actimeo = HZ * option;
1580 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1581 cERROR(1, "CIFS: attribute cache"
1582 "timeout too large");
1583 goto cifs_parse_mount_err;
1584 }
1585 break;
1586
1587 /* String Arguments */
1588
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001589 case Opt_blank_user:
1590 /* null user, ie. anonymous authentication */
1591 vol->nullauth = 1;
1592 vol->username = NULL;
1593 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001594 case Opt_user:
1595 string = match_strdup(args);
1596 if (string == NULL)
1597 goto out_nomem;
1598
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001599 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001600 MAX_USERNAME_SIZE) {
1601 printk(KERN_WARNING "CIFS: username too long\n");
1602 goto cifs_parse_mount_err;
1603 }
1604 vol->username = kstrdup(string, GFP_KERNEL);
1605 if (!vol->username) {
1606 printk(KERN_WARNING "CIFS: no memory "
1607 "for username\n");
1608 goto cifs_parse_mount_err;
1609 }
1610 break;
1611 case Opt_blank_pass:
1612 vol->password = NULL;
1613 break;
1614 case Opt_pass:
1615 /* passwords have to be handled differently
1616 * to allow the character used for deliminator
1617 * to be passed within them
1618 */
1619
1620 /* Obtain the value string */
1621 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001622 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001623
1624 /* Set tmp_end to end of the string */
1625 tmp_end = (char *) value + strlen(value);
1626
1627 /* Check if following character is the deliminator
1628 * If yes, we have encountered a double deliminator
1629 * reset the NULL character to the deliminator
1630 */
1631 if (tmp_end < end && tmp_end[1] == delim)
1632 tmp_end[0] = delim;
1633
1634 /* Keep iterating until we get to a single deliminator
1635 * OR the end
1636 */
1637 while ((tmp_end = strchr(tmp_end, delim)) != NULL &&
1638 (tmp_end[1] == delim)) {
1639 tmp_end = (char *) &tmp_end[2];
1640 }
1641
1642 /* Reset var options to point to next element */
1643 if (tmp_end) {
1644 tmp_end[0] = '\0';
1645 options = (char *) &tmp_end[1];
1646 } else
1647 /* Reached the end of the mount option string */
1648 options = end;
1649
1650 /* Now build new password string */
1651 temp_len = strlen(value);
1652 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1653 if (vol->password == NULL) {
1654 printk(KERN_WARNING "CIFS: no memory "
1655 "for password\n");
1656 goto cifs_parse_mount_err;
1657 }
1658
1659 for (i = 0, j = 0; i < temp_len; i++, j++) {
1660 vol->password[j] = value[i];
1661 if ((value[i] == delim) &&
1662 value[i+1] == delim)
1663 /* skip the second deliminator */
1664 i++;
1665 }
1666 vol->password[j] = '\0';
1667 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001668 case Opt_blank_ip:
1669 vol->UNCip = NULL;
1670 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001671 case Opt_ip:
1672 string = match_strdup(args);
1673 if (string == NULL)
1674 goto out_nomem;
1675
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001676 if (strnlen(string, INET6_ADDRSTRLEN) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001677 INET6_ADDRSTRLEN) {
1678 printk(KERN_WARNING "CIFS: ip address "
1679 "too long\n");
1680 goto cifs_parse_mount_err;
1681 }
1682 vol->UNCip = kstrdup(string, GFP_KERNEL);
1683 if (!vol->UNCip) {
1684 printk(KERN_WARNING "CIFS: no memory "
1685 "for UNC IP\n");
1686 goto cifs_parse_mount_err;
1687 }
1688 break;
1689 case Opt_unc:
1690 string = match_strdup(args);
1691 if (string == NULL)
1692 goto out_nomem;
1693
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001694 temp_len = strnlen(string, 300);
1695 if (temp_len == 300) {
1696 printk(KERN_WARNING "CIFS: UNC name too long\n");
1697 goto cifs_parse_mount_err;
1698 }
1699
Sachin Prabhue4b41fb2012-04-04 01:58:56 +01001700 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1701 if (vol->UNC == NULL) {
1702 printk(KERN_WARNING "CIFS: no memory for UNC\n");
1703 goto cifs_parse_mount_err;
1704 }
1705 strcpy(vol->UNC, string);
1706
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001707 if (strncmp(string, "//", 2) == 0) {
1708 vol->UNC[0] = '\\';
1709 vol->UNC[1] = '\\';
1710 } else if (strncmp(string, "\\\\", 2) != 0) {
1711 printk(KERN_WARNING "CIFS: UNC Path does not "
1712 "begin with // or \\\\\n");
1713 goto cifs_parse_mount_err;
1714 }
1715
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001716 break;
1717 case Opt_domain:
1718 string = match_strdup(args);
1719 if (string == NULL)
1720 goto out_nomem;
1721
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001722 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001723 printk(KERN_WARNING "CIFS: domain name too"
1724 " long\n");
1725 goto cifs_parse_mount_err;
1726 }
1727
1728 vol->domainname = kstrdup(string, GFP_KERNEL);
1729 if (!vol->domainname) {
1730 printk(KERN_WARNING "CIFS: no memory "
1731 "for domainname\n");
1732 goto cifs_parse_mount_err;
1733 }
1734 cFYI(1, "Domain name set");
1735 break;
1736 case Opt_srcaddr:
1737 string = match_strdup(args);
1738 if (string == NULL)
1739 goto out_nomem;
1740
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001741 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001742 (struct sockaddr *)&vol->srcaddr,
1743 string, strlen(string))) {
1744 printk(KERN_WARNING "CIFS: Could not parse"
1745 " srcaddr: %s\n", string);
1746 goto cifs_parse_mount_err;
1747 }
1748 break;
1749 case Opt_prefixpath:
1750 string = match_strdup(args);
1751 if (string == NULL)
1752 goto out_nomem;
1753
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001754 temp_len = strnlen(string, 1024);
1755 if (string[0] != '/')
1756 temp_len++; /* missing leading slash */
1757 if (temp_len > 1024) {
1758 printk(KERN_WARNING "CIFS: prefix too long\n");
1759 goto cifs_parse_mount_err;
1760 }
1761
1762 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1763 if (vol->prepath == NULL) {
1764 printk(KERN_WARNING "CIFS: no memory "
1765 "for path prefix\n");
1766 goto cifs_parse_mount_err;
1767 }
1768
1769 if (string[0] != '/') {
1770 vol->prepath[0] = '/';
1771 strcpy(vol->prepath+1, string);
1772 } else
1773 strcpy(vol->prepath, string);
1774
1775 break;
1776 case Opt_iocharset:
1777 string = match_strdup(args);
1778 if (string == NULL)
1779 goto out_nomem;
1780
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001781 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001782 printk(KERN_WARNING "CIFS: iocharset name "
1783 "too long.\n");
1784 goto cifs_parse_mount_err;
1785 }
1786
1787 if (strnicmp(string, "default", 7) != 0) {
1788 vol->iocharset = kstrdup(string,
1789 GFP_KERNEL);
1790 if (!vol->iocharset) {
1791 printk(KERN_WARNING "CIFS: no memory"
1792 "for charset\n");
1793 goto cifs_parse_mount_err;
1794 }
1795 }
1796 /* if iocharset not set then load_nls_default
1797 * is used by caller
1798 */
1799 cFYI(1, "iocharset set to %s", string);
1800 break;
1801 case Opt_sockopt:
1802 string = match_strdup(args);
1803 if (string == NULL)
1804 goto out_nomem;
1805
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001806 if (strnicmp(string, "TCP_NODELAY", 11) == 0)
1807 vol->sockopt_tcp_nodelay = 1;
1808 break;
1809 case Opt_netbiosname:
1810 string = match_strdup(args);
1811 if (string == NULL)
1812 goto out_nomem;
1813
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001814 memset(vol->source_rfc1001_name, 0x20,
1815 RFC1001_NAME_LEN);
1816 /*
1817 * FIXME: are there cases in which a comma can
1818 * be valid in workstation netbios name (and
1819 * need special handling)?
1820 */
1821 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1822 /* don't ucase netbiosname for user */
1823 if (string[i] == 0)
1824 break;
1825 vol->source_rfc1001_name[i] = string[i];
1826 }
1827 /* The string has 16th byte zero still from
1828 * set at top of the function
1829 */
1830 if (i == RFC1001_NAME_LEN && string[i] != 0)
1831 printk(KERN_WARNING "CIFS: netbiosname"
1832 " longer than 15 truncated.\n");
1833
1834 break;
1835 case Opt_servern:
1836 /* servernetbiosname specified override *SMBSERVER */
1837 string = match_strdup(args);
1838 if (string == NULL)
1839 goto out_nomem;
1840
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001841 /* last byte, type, is 0x20 for servr type */
1842 memset(vol->target_rfc1001_name, 0x20,
1843 RFC1001_NAME_LEN_WITH_NULL);
1844
1845 /* BB are there cases in which a comma can be
1846 valid in this workstation netbios name
1847 (and need special handling)? */
1848
1849 /* user or mount helper must uppercase the
1850 netbios name */
1851 for (i = 0; i < 15; i++) {
1852 if (string[i] == 0)
1853 break;
1854 vol->target_rfc1001_name[i] = string[i];
1855 }
1856 /* The string has 16th byte zero still from
1857 set at top of the function */
1858 if (i == RFC1001_NAME_LEN && string[i] != 0)
1859 printk(KERN_WARNING "CIFS: server net"
1860 "biosname longer than 15 truncated.\n");
1861 break;
1862 case Opt_ver:
1863 string = match_strdup(args);
1864 if (string == NULL)
1865 goto out_nomem;
1866
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001867 if (strnicmp(string, "cifs", 4) == 0 ||
1868 strnicmp(string, "1", 1) == 0) {
1869 /* This is the default */
1870 break;
1871 }
1872 /* For all other value, error */
1873 printk(KERN_WARNING "CIFS: Invalid version"
1874 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001875 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001876 case Opt_sec:
1877 string = match_strdup(args);
1878 if (string == NULL)
1879 goto out_nomem;
1880
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001881 if (cifs_parse_security_flavors(string, vol) != 0)
1882 goto cifs_parse_mount_err;
1883 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001884 case Opt_cache:
1885 string = match_strdup(args);
1886 if (string == NULL)
1887 goto out_nomem;
1888
1889 if (cifs_parse_cache_flavor(string, vol) != 0)
1890 goto cifs_parse_mount_err;
1891 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001892 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001893 /*
1894 * An option we don't recognize. Save it off for later
1895 * if we haven't already found one
1896 */
1897 if (!invalid)
1898 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001901 /* Free up any allocated string */
1902 kfree(string);
1903 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001905
Jeff Laytond8162552012-03-23 14:40:56 -04001906 if (!sloppy && invalid) {
1907 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1908 goto cifs_parse_mount_err;
1909 }
1910
Jeff Layton8a8798a2012-01-17 16:09:15 -05001911#ifndef CONFIG_KEYS
1912 /* Muliuser mounts require CONFIG_KEYS support */
1913 if (vol->multiuser) {
1914 cERROR(1, "Multiuser mounts require kernels with "
1915 "CONFIG_KEYS enabled.");
Sean Finneyb9468452011-04-11 13:19:32 +00001916 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001917 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001918#endif
Jeff Layton0eb8a132010-10-06 19:51:12 -04001919
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001920 if (vol->UNCip == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 vol->UNCip = &vol->UNC[2];
1922
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001923 if (uid_specified)
1924 vol->override_uid = override_uid;
1925 else if (override_uid == 1)
1926 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1927 "specified with no uid= option.\n");
1928
1929 if (gid_specified)
1930 vol->override_gid = override_gid;
1931 else if (override_gid == 1)
1932 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1933 "specified with no gid= option.\n");
1934
Sean Finneyb9468452011-04-11 13:19:32 +00001935 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001937
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001938out_nomem:
1939 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001940cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001941 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001942 kfree(mountdata_copy);
1943 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944}
1945
Ben Greear3eb9a882010-09-01 17:06:02 -07001946/** Returns true if srcaddr isn't specified and rhs isn't
1947 * specified, or if srcaddr is specified and
1948 * matches the IP address of the rhs argument.
1949 */
Jeff Layton45151482010-07-06 20:43:02 -04001950static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001951srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1952{
1953 switch (srcaddr->sa_family) {
1954 case AF_UNSPEC:
1955 return (rhs->sa_family == AF_UNSPEC);
1956 case AF_INET: {
1957 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1958 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1959 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1960 }
1961 case AF_INET6: {
1962 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
1963 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
1964 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1965 }
1966 default:
1967 WARN_ON(1);
1968 return false; /* don't expect to be here */
1969 }
1970}
1971
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001972/*
1973 * If no port is specified in addr structure, we try to match with 445 port
1974 * and if it fails - with 139 ports. It should be called only if address
1975 * families of server and addr are equal.
1976 */
1977static bool
1978match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1979{
Steve French6da97912011-03-13 18:55:55 +00001980 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001981
1982 switch (addr->sa_family) {
1983 case AF_INET:
1984 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1985 port = ((struct sockaddr_in *) addr)->sin_port;
1986 break;
1987 case AF_INET6:
1988 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1989 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1990 break;
1991 default:
1992 WARN_ON(1);
1993 return false;
1994 }
1995
1996 if (!port) {
1997 port = htons(CIFS_PORT);
1998 if (port == *sport)
1999 return true;
2000
2001 port = htons(RFC1001_PORT);
2002 }
2003
2004 return port == *sport;
2005}
Ben Greear3eb9a882010-09-01 17:06:02 -07002006
2007static bool
2008match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2009 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010{
Jeff Layton45151482010-07-06 20:43:02 -04002011 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002012 case AF_INET: {
2013 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2014 struct sockaddr_in *srv_addr4 =
2015 (struct sockaddr_in *)&server->dstaddr;
2016
2017 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002018 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002019 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002020 }
2021 case AF_INET6: {
2022 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2023 struct sockaddr_in6 *srv_addr6 =
2024 (struct sockaddr_in6 *)&server->dstaddr;
2025
Jeff Layton45151482010-07-06 20:43:02 -04002026 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002027 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002028 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002029 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002030 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002031 break;
2032 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002033 default:
2034 WARN_ON(1);
2035 return false; /* don't expect to be here */
2036 }
Jeff Layton45151482010-07-06 20:43:02 -04002037
Ben Greear3eb9a882010-09-01 17:06:02 -07002038 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2039 return false;
2040
Jeff Layton45151482010-07-06 20:43:02 -04002041 return true;
2042}
2043
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002044static bool
2045match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2046{
2047 unsigned int secFlags;
2048
2049 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
2050 secFlags = vol->secFlg;
2051 else
2052 secFlags = global_secflags | vol->secFlg;
2053
2054 switch (server->secType) {
2055 case LANMAN:
2056 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
2057 return false;
2058 break;
2059 case NTLMv2:
2060 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
2061 return false;
2062 break;
2063 case NTLM:
2064 if (!(secFlags & CIFSSEC_MAY_NTLM))
2065 return false;
2066 break;
2067 case Kerberos:
2068 if (!(secFlags & CIFSSEC_MAY_KRB5))
2069 return false;
2070 break;
2071 case RawNTLMSSP:
2072 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2073 return false;
2074 break;
2075 default:
2076 /* shouldn't happen */
2077 return false;
2078 }
2079
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002080 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002081 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002082 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002083 return false;
2084 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002085 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002086 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2087 return false;
2088
2089 return true;
2090}
2091
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002092static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
2093 struct smb_vol *vol)
2094{
2095 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2096 return 0;
2097
2098 if (!match_address(server, addr,
2099 (struct sockaddr *)&vol->srcaddr))
2100 return 0;
2101
2102 if (!match_port(server, addr))
2103 return 0;
2104
2105 if (!match_security(server, vol))
2106 return 0;
2107
2108 return 1;
2109}
2110
Jeff Layton45151482010-07-06 20:43:02 -04002111static struct TCP_Server_Info *
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002112cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002113{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002114 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302116 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002117 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002118 if (!match_server(server, addr, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002119 continue;
2120
Jeff Laytone7ddee92008-11-14 13:44:38 -05002121 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302122 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002123 cFYI(1, "Existing tcp session with server found");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002124 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302126 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 return NULL;
2128}
2129
Jeff Layton14fbf502008-11-14 13:53:46 -05002130static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002131cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002133 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302135 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002136 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302137 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002138 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002140
Rob Landleyf1d0c992011-01-22 15:44:05 -06002141 put_net(cifs_net_ns(server));
2142
Jeff Laytone7ddee92008-11-14 13:44:38 -05002143 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302144 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002145
Jeff Laytonc74093b2011-01-11 07:24:23 -05002146 cancel_delayed_work_sync(&server->echo);
2147
Jeff Laytone7ddee92008-11-14 13:44:38 -05002148 spin_lock(&GlobalMid_Lock);
2149 server->tcpStatus = CifsExiting;
2150 spin_unlock(&GlobalMid_Lock);
2151
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002152 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302153 cifs_fscache_release_client_cookie(server);
2154
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002155 kfree(server->session_key.response);
2156 server->session_key.response = NULL;
2157 server->session_key.len = 0;
2158
Jeff Laytone7ddee92008-11-14 13:44:38 -05002159 task = xchg(&server->tsk, NULL);
2160 if (task)
2161 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162}
2163
Jeff Layton63c038c2008-12-01 18:41:46 -05002164static struct TCP_Server_Info *
2165cifs_get_tcp_session(struct smb_vol *volume_info)
2166{
2167 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002168 struct sockaddr_storage addr;
Jeff Layton63c038c2008-12-01 18:41:46 -05002169 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2170 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2171 int rc;
2172
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002173 memset(&addr, 0, sizeof(struct sockaddr_storage));
Jeff Layton63c038c2008-12-01 18:41:46 -05002174
Joe Perchesb6b38f72010-04-21 03:50:45 +00002175 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002176
Jeff Layton63c038c2008-12-01 18:41:46 -05002177 if (volume_info->UNCip && volume_info->UNC) {
Jeff Layton50d97162010-07-06 20:43:01 -04002178 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2179 volume_info->UNCip,
David Howells67b76262010-07-22 18:33:01 +01002180 strlen(volume_info->UNCip),
Jeff Layton50d97162010-07-06 20:43:01 -04002181 volume_info->port);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002182 if (!rc) {
Jeff Layton63c038c2008-12-01 18:41:46 -05002183 /* we failed translating address */
2184 rc = -EINVAL;
2185 goto out_err;
2186 }
Jeff Layton63c038c2008-12-01 18:41:46 -05002187 } else if (volume_info->UNCip) {
2188 /* BB using ip addr as tcp_ses name to connect to the
2189 DFS root below */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002190 cERROR(1, "Connecting to DFS root not implemented yet");
Jeff Layton63c038c2008-12-01 18:41:46 -05002191 rc = -EINVAL;
2192 goto out_err;
2193 } else /* which tcp_sess DFS root would we conect to */ {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002194 cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
2195 "unc=//192.168.1.100/public) specified");
Jeff Layton63c038c2008-12-01 18:41:46 -05002196 rc = -EINVAL;
2197 goto out_err;
2198 }
2199
2200 /* see if we already have a matching tcp_ses */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002201 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002202 if (tcp_ses)
2203 return tcp_ses;
2204
2205 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2206 if (!tcp_ses) {
2207 rc = -ENOMEM;
2208 goto out_err;
2209 }
2210
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002211 rc = cifs_crypto_shash_allocate(tcp_ses);
2212 if (rc) {
2213 cERROR(1, "could not setup hash structures rc %d", rc);
2214 goto out_err;
2215 }
2216
Rob Landleyf1d0c992011-01-22 15:44:05 -06002217 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002218 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2219 if (IS_ERR(tcp_ses->hostname)) {
2220 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002221 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002222 }
2223
2224 tcp_ses->noblocksnd = volume_info->noblocksnd;
2225 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002226 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002227 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002228 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002229 init_waitqueue_head(&tcp_ses->response_q);
2230 init_waitqueue_head(&tcp_ses->request_q);
2231 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2232 mutex_init(&tcp_ses->srv_mutex);
2233 memcpy(tcp_ses->workstation_RFC1001_name,
2234 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2235 memcpy(tcp_ses->server_RFC1001_name,
2236 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002237 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002238 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002239 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002240 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002241 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2242 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002243 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton63c038c2008-12-01 18:41:46 -05002244
2245 /*
2246 * at this point we are the only ones with the pointer
2247 * to the struct since the kernel thread not created yet
2248 * no need to spinlock this init of tcpStatus or srv_count
2249 */
2250 tcp_ses->tcpStatus = CifsNew;
Ben Greear3eb9a882010-09-01 17:06:02 -07002251 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2252 sizeof(tcp_ses->srcaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002253 ++tcp_ses->srv_count;
2254
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002255 if (addr.ss_family == AF_INET6) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002256 cFYI(1, "attempting ipv6 connect");
Jeff Layton63c038c2008-12-01 18:41:46 -05002257 /* BB should we allow ipv6 on port 139? */
2258 /* other OS never observed in Wild doing 139 with v6 */
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002259 memcpy(&tcp_ses->dstaddr, sin_server6,
2260 sizeof(struct sockaddr_in6));
2261 } else
2262 memcpy(&tcp_ses->dstaddr, sin_server,
2263 sizeof(struct sockaddr_in));
2264
2265 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002266 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002267 cERROR(1, "Error connecting to socket. Aborting operation");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002268 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002269 }
2270
2271 /*
2272 * since we're in a cifs function already, we know that
2273 * this will succeed. No need for try_module_get().
2274 */
2275 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002276 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002277 tcp_ses, "cifsd");
2278 if (IS_ERR(tcp_ses->tsk)) {
2279 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002280 cERROR(1, "error %d create cifsd thread", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002281 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002282 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002283 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002284 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002285
2286 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302287 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002288 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302289 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002290
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302291 cifs_fscache_get_client_cookie(tcp_ses);
2292
Jeff Laytonc74093b2011-01-11 07:24:23 -05002293 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002294 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002295
Jeff Layton63c038c2008-12-01 18:41:46 -05002296 return tcp_ses;
2297
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05002298out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002299 cifs_crypto_shash_release(tcp_ses);
2300
Rob Landleyf1d0c992011-01-22 15:44:05 -06002301 put_net(cifs_net_ns(tcp_ses));
2302
Jeff Layton63c038c2008-12-01 18:41:46 -05002303out_err:
2304 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002305 if (!IS_ERR(tcp_ses->hostname))
2306 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002307 if (tcp_ses->ssocket)
2308 sock_release(tcp_ses->ssocket);
2309 kfree(tcp_ses);
2310 }
2311 return ERR_PTR(rc);
2312}
2313
Steve French96daf2b2011-05-27 04:34:02 +00002314static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002315{
2316 switch (ses->server->secType) {
2317 case Kerberos:
2318 if (vol->cred_uid != ses->cred_uid)
2319 return 0;
2320 break;
2321 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002322 /* NULL username means anonymous session */
2323 if (ses->user_name == NULL) {
2324 if (!vol->nullauth)
2325 return 0;
2326 break;
2327 }
2328
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002329 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002330 if (strncmp(ses->user_name,
2331 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002332 MAX_USERNAME_SIZE))
2333 return 0;
2334 if (strlen(vol->username) != 0 &&
2335 ses->password != NULL &&
2336 strncmp(ses->password,
2337 vol->password ? vol->password : "",
2338 MAX_PASSWORD_SIZE))
2339 return 0;
2340 }
2341 return 1;
2342}
2343
Steve French96daf2b2011-05-27 04:34:02 +00002344static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002345cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346{
Steve French96daf2b2011-05-27 04:34:02 +00002347 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302349 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002350 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002351 if (!match_session(ses, vol))
2352 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002353 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302354 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002355 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302357 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 return NULL;
2359}
2360
Jeff Layton14fbf502008-11-14 13:53:46 -05002361static void
Steve French96daf2b2011-05-27 04:34:02 +00002362cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002363{
2364 int xid;
2365 struct TCP_Server_Info *server = ses->server;
2366
Jeff Layton36988c72010-04-24 07:57:43 -04002367 cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302368 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002369 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302370 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002371 return;
2372 }
2373
2374 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302375 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002376
2377 if (ses->status == CifsGood) {
2378 xid = GetXid();
2379 CIFSSMBLogoff(xid, ses);
2380 _FreeXid(xid);
2381 }
2382 sesInfoFree(ses);
2383 cifs_put_tcp_session(server);
2384}
2385
Jeff Layton8a8798a2012-01-17 16:09:15 -05002386#ifdef CONFIG_KEYS
2387
2388/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2389#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2390
2391/* Populate username and pw fields from keyring if possible */
2392static int
2393cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2394{
2395 int rc = 0;
2396 char *desc, *delim, *payload;
2397 ssize_t len;
2398 struct key *key;
2399 struct TCP_Server_Info *server = ses->server;
2400 struct sockaddr_in *sa;
2401 struct sockaddr_in6 *sa6;
2402 struct user_key_payload *upayload;
2403
2404 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2405 if (!desc)
2406 return -ENOMEM;
2407
2408 /* try to find an address key first */
2409 switch (server->dstaddr.ss_family) {
2410 case AF_INET:
2411 sa = (struct sockaddr_in *)&server->dstaddr;
2412 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2413 break;
2414 case AF_INET6:
2415 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2416 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2417 break;
2418 default:
2419 cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
2420 rc = -EINVAL;
2421 goto out_err;
2422 }
2423
2424 cFYI(1, "%s: desc=%s", __func__, desc);
2425 key = request_key(&key_type_logon, desc, "");
2426 if (IS_ERR(key)) {
2427 if (!ses->domainName) {
2428 cFYI(1, "domainName is NULL");
2429 rc = PTR_ERR(key);
2430 goto out_err;
2431 }
2432
2433 /* didn't work, try to find a domain key */
2434 sprintf(desc, "cifs:d:%s", ses->domainName);
2435 cFYI(1, "%s: desc=%s", __func__, desc);
2436 key = request_key(&key_type_logon, desc, "");
2437 if (IS_ERR(key)) {
2438 rc = PTR_ERR(key);
2439 goto out_err;
2440 }
2441 }
2442
2443 down_read(&key->sem);
2444 upayload = key->payload.data;
2445 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002446 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002447 goto out_key_put;
2448 }
2449
2450 /* find first : in payload */
2451 payload = (char *)upayload->data;
2452 delim = strnchr(payload, upayload->datalen, ':');
2453 cFYI(1, "payload=%s", payload);
2454 if (!delim) {
2455 cFYI(1, "Unable to find ':' in payload (datalen=%d)",
2456 upayload->datalen);
2457 rc = -EINVAL;
2458 goto out_key_put;
2459 }
2460
2461 len = delim - payload;
2462 if (len > MAX_USERNAME_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002463 cFYI(1, "Bad value from username search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002464 rc = -EINVAL;
2465 goto out_key_put;
2466 }
2467
2468 vol->username = kstrndup(payload, len, GFP_KERNEL);
2469 if (!vol->username) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002470 cFYI(1, "Unable to allocate %zd bytes for username", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002471 rc = -ENOMEM;
2472 goto out_key_put;
2473 }
2474 cFYI(1, "%s: username=%s", __func__, vol->username);
2475
2476 len = key->datalen - (len + 1);
2477 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002478 cFYI(1, "Bad len for password search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002479 rc = -EINVAL;
2480 kfree(vol->username);
2481 vol->username = NULL;
2482 goto out_key_put;
2483 }
2484
2485 ++delim;
2486 vol->password = kstrndup(delim, len, GFP_KERNEL);
2487 if (!vol->password) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002488 cFYI(1, "Unable to allocate %zd bytes for password", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002489 rc = -ENOMEM;
2490 kfree(vol->username);
2491 vol->username = NULL;
2492 goto out_key_put;
2493 }
2494
2495out_key_put:
2496 up_read(&key->sem);
2497 key_put(key);
2498out_err:
2499 kfree(desc);
2500 cFYI(1, "%s: returning %d", __func__, rc);
2501 return rc;
2502}
2503#else /* ! CONFIG_KEYS */
2504static inline int
2505cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2506 struct cifs_ses *ses __attribute__((unused)))
2507{
2508 return -ENOSYS;
2509}
2510#endif /* CONFIG_KEYS */
2511
Steve Frenchd9b94202011-04-12 01:24:57 +00002512static bool warned_on_ntlm; /* globals init to false automatically */
2513
Steve French96daf2b2011-05-27 04:34:02 +00002514static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002515cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2516{
2517 int rc = -ENOMEM, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002518 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002519 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2520 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002521
2522 xid = GetXid();
2523
Jeff Layton4ff67b72010-07-06 20:43:02 -04002524 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002525 if (ses) {
2526 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
2527
Jeff Layton36988c72010-04-24 07:57:43 -04002528 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002529 rc = cifs_negotiate_protocol(xid, ses);
2530 if (rc) {
2531 mutex_unlock(&ses->session_mutex);
2532 /* problem -- put our ses reference */
2533 cifs_put_smb_ses(ses);
2534 FreeXid(xid);
2535 return ERR_PTR(rc);
2536 }
Jeff Layton36988c72010-04-24 07:57:43 -04002537 if (ses->need_reconnect) {
2538 cFYI(1, "Session needs reconnect");
2539 rc = cifs_setup_session(xid, ses,
2540 volume_info->local_nls);
2541 if (rc) {
2542 mutex_unlock(&ses->session_mutex);
2543 /* problem -- put our reference */
2544 cifs_put_smb_ses(ses);
2545 FreeXid(xid);
2546 return ERR_PTR(rc);
2547 }
2548 }
2549 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002550
2551 /* existing SMB ses has a server reference already */
2552 cifs_put_tcp_session(server);
Jeff Layton36988c72010-04-24 07:57:43 -04002553 FreeXid(xid);
2554 return ses;
2555 }
2556
2557 cFYI(1, "Existing smb sess not found");
2558 ses = sesInfoAlloc();
2559 if (ses == NULL)
2560 goto get_ses_fail;
2561
2562 /* new SMB session uses our server ref */
2563 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002564 if (server->dstaddr.ss_family == AF_INET6)
2565 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002566 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002567 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002568
Steve French8727c8a2011-02-25 01:11:56 -06002569 if (volume_info->username) {
2570 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2571 if (!ses->user_name)
2572 goto get_ses_fail;
2573 }
Jeff Layton36988c72010-04-24 07:57:43 -04002574
2575 /* volume_info->password freed at unmount */
2576 if (volume_info->password) {
2577 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2578 if (!ses->password)
2579 goto get_ses_fail;
2580 }
2581 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002582 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2583 if (!ses->domainName)
2584 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002585 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002586 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002587 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002588
2589 /* ntlmv2 is much stronger than ntlm security, and has been broadly
2590 supported for many years, time to update default security mechanism */
2591 if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
2592 warned_on_ntlm = true;
2593 cERROR(1, "default security mechanism requested. The default "
2594 "security mechanism will be upgraded from ntlm to "
Steve French225de112012-01-03 23:08:24 -06002595 "ntlmv2 in kernel release 3.3");
Steve Frenchd9b94202011-04-12 01:24:57 +00002596 }
Jeff Layton36988c72010-04-24 07:57:43 -04002597 ses->overrideSecFlg = volume_info->secFlg;
2598
2599 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002600 rc = cifs_negotiate_protocol(xid, ses);
2601 if (!rc)
2602 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002603 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002604 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002605 goto get_ses_fail;
2606
2607 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302608 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002609 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302610 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002611
2612 FreeXid(xid);
2613 return ses;
2614
2615get_ses_fail:
2616 sesInfoFree(ses);
2617 FreeXid(xid);
2618 return ERR_PTR(rc);
2619}
2620
Steve French96daf2b2011-05-27 04:34:02 +00002621static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002622{
2623 if (tcon->tidStatus == CifsExiting)
2624 return 0;
2625 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2626 return 0;
2627 return 1;
2628}
2629
Steve French96daf2b2011-05-27 04:34:02 +00002630static struct cifs_tcon *
2631cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632{
2633 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002634 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302636 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002637 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002638 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002639 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002640 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002641 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302642 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 return tcon;
2644 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302645 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 return NULL;
2647}
2648
Jeff Laytonf1987b42008-11-15 11:12:47 -05002649static void
Steve French96daf2b2011-05-27 04:34:02 +00002650cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002651{
2652 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002653 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002654
Jeff Laytond00c28d2010-04-24 07:57:44 -04002655 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302656 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002657 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302658 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002659 return;
2660 }
2661
2662 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302663 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002664
2665 xid = GetXid();
2666 CIFSSMBTDis(xid, tcon);
2667 _FreeXid(xid);
2668
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302669 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002670 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002671 cifs_put_smb_ses(ses);
2672}
2673
Steve French96daf2b2011-05-27 04:34:02 +00002674static struct cifs_tcon *
2675cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002676{
2677 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002678 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002679
2680 tcon = cifs_find_tcon(ses, volume_info->UNC);
2681 if (tcon) {
2682 cFYI(1, "Found match on UNC path");
2683 /* existing tcon already has a reference */
2684 cifs_put_smb_ses(ses);
2685 if (tcon->seal != volume_info->seal)
2686 cERROR(1, "transport encryption setting "
2687 "conflicts with existing tid");
2688 return tcon;
2689 }
2690
2691 tcon = tconInfoAlloc();
2692 if (tcon == NULL) {
2693 rc = -ENOMEM;
2694 goto out_fail;
2695 }
2696
2697 tcon->ses = ses;
2698 if (volume_info->password) {
2699 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2700 if (!tcon->password) {
2701 rc = -ENOMEM;
2702 goto out_fail;
2703 }
2704 }
2705
2706 if (strchr(volume_info->UNC + 3, '\\') == NULL
2707 && strchr(volume_info->UNC + 3, '/') == NULL) {
2708 cERROR(1, "Missing share name");
2709 rc = -ENODEV;
2710 goto out_fail;
2711 }
2712
2713 /* BB Do we need to wrap session_mutex around
2714 * this TCon call and Unix SetFS as
2715 * we do on SessSetup and reconnect? */
2716 xid = GetXid();
2717 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
2718 FreeXid(xid);
2719 cFYI(1, "CIFS Tcon rc = %d", rc);
2720 if (rc)
2721 goto out_fail;
2722
2723 if (volume_info->nodfs) {
2724 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2725 cFYI(1, "DFS disabled (%d)", tcon->Flags);
2726 }
2727 tcon->seal = volume_info->seal;
2728 /* we can have only one retry value for a connection
2729 to a share so for resources mounted more than once
2730 to the same server share the last value passed in
2731 for the retry flag is used */
2732 tcon->retry = volume_info->retry;
2733 tcon->nocase = volume_info->nocase;
2734 tcon->local_lease = volume_info->local_lease;
2735
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302736 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002737 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302738 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002739
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302740 cifs_fscache_get_super_cookie(tcon);
2741
Jeff Laytond00c28d2010-04-24 07:57:44 -04002742 return tcon;
2743
2744out_fail:
2745 tconInfoFree(tcon);
2746 return ERR_PTR(rc);
2747}
2748
Jeff Layton9d002df2010-10-06 19:51:11 -04002749void
2750cifs_put_tlink(struct tcon_link *tlink)
2751{
2752 if (!tlink || IS_ERR(tlink))
2753 return;
2754
2755 if (!atomic_dec_and_test(&tlink->tl_count) ||
2756 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2757 tlink->tl_time = jiffies;
2758 return;
2759 }
2760
2761 if (!IS_ERR(tlink_tcon(tlink)))
2762 cifs_put_tcon(tlink_tcon(tlink));
2763 kfree(tlink);
2764 return;
2765}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002766
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002767static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002768cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2769{
2770 return cifs_sb->master_tlink;
2771}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002772
2773static int
2774compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2775{
2776 struct cifs_sb_info *old = CIFS_SB(sb);
2777 struct cifs_sb_info *new = mnt_data->cifs_sb;
2778
2779 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2780 return 0;
2781
2782 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2783 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2784 return 0;
2785
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002786 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002787 * We want to share sb only if we don't specify an r/wsize or
2788 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002789 */
2790 if (new->wsize && new->wsize < old->wsize)
2791 return 0;
2792
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002793 if (new->rsize && new->rsize < old->rsize)
2794 return 0;
2795
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002796 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2797 return 0;
2798
2799 if (old->mnt_file_mode != new->mnt_file_mode ||
2800 old->mnt_dir_mode != new->mnt_dir_mode)
2801 return 0;
2802
2803 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2804 return 0;
2805
2806 if (old->actimeo != new->actimeo)
2807 return 0;
2808
2809 return 1;
2810}
2811
2812int
2813cifs_match_super(struct super_block *sb, void *data)
2814{
2815 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2816 struct smb_vol *volume_info;
2817 struct cifs_sb_info *cifs_sb;
2818 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002819 struct cifs_ses *ses;
2820 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002821 struct tcon_link *tlink;
2822 struct sockaddr_storage addr;
2823 int rc = 0;
2824
2825 memset(&addr, 0, sizeof(struct sockaddr_storage));
2826
2827 spin_lock(&cifs_tcp_ses_lock);
2828 cifs_sb = CIFS_SB(sb);
2829 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2830 if (IS_ERR(tlink)) {
2831 spin_unlock(&cifs_tcp_ses_lock);
2832 return rc;
2833 }
2834 tcon = tlink_tcon(tlink);
2835 ses = tcon->ses;
2836 tcp_srv = ses->server;
2837
2838 volume_info = mnt_data->vol;
2839
2840 if (!volume_info->UNCip || !volume_info->UNC)
2841 goto out;
2842
2843 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2844 volume_info->UNCip,
2845 strlen(volume_info->UNCip),
2846 volume_info->port);
2847 if (!rc)
2848 goto out;
2849
2850 if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
2851 !match_session(ses, volume_info) ||
2852 !match_tcon(tcon, volume_info->UNC)) {
2853 rc = 0;
2854 goto out;
2855 }
2856
2857 rc = compare_mount_options(sb, mnt_data);
2858out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002859 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002860 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002861 return rc;
2862}
2863
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864int
Steve French96daf2b2011-05-27 04:34:02 +00002865get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
Steve French50c2f752007-07-13 00:33:32 +00002866 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
Steve French366781c2008-01-25 10:12:41 +00002867 struct dfs_info3_param **preferrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868{
2869 char *temp_unc;
2870 int rc = 0;
2871
2872 *pnum_referrals = 0;
Steve French366781c2008-01-25 10:12:41 +00002873 *preferrals = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
2875 if (pSesInfo->ipc_tid == 0) {
2876 temp_unc = kmalloc(2 /* for slashes */ +
Steve French50c2f752007-07-13 00:33:32 +00002877 strnlen(pSesInfo->serverName,
2878 SERVER_NAME_LEN_WITH_NULL * 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 + 1 + 4 /* slash IPC$ */ + 2,
2880 GFP_KERNEL);
2881 if (temp_unc == NULL)
2882 return -ENOMEM;
2883 temp_unc[0] = '\\';
2884 temp_unc[1] = '\\';
2885 strcpy(temp_unc + 2, pSesInfo->serverName);
2886 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
2887 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002888 cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889 kfree(temp_unc);
2890 }
2891 if (rc == 0)
Steve Frenchc2cf07d2008-05-15 06:20:02 +00002892 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
Steve French737b7582005-04-28 22:41:06 -07002893 pnum_referrals, nls_codepage, remap);
Steve French366781c2008-01-25 10:12:41 +00002894 /* BB map targetUNCs to dfs_info3 structures, here or
2895 in CIFSGetDFSRefer BB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896
2897 return rc;
2898}
2899
Jeff Layton09e50d52008-07-23 10:11:19 -04002900#ifdef CONFIG_DEBUG_LOCK_ALLOC
2901static struct lock_class_key cifs_key[2];
2902static struct lock_class_key cifs_slock_key[2];
2903
2904static inline void
2905cifs_reclassify_socket4(struct socket *sock)
2906{
2907 struct sock *sk = sock->sk;
2908 BUG_ON(sock_owned_by_user(sk));
2909 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2910 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2911}
2912
2913static inline void
2914cifs_reclassify_socket6(struct socket *sock)
2915{
2916 struct sock *sk = sock->sk;
2917 BUG_ON(sock_owned_by_user(sk));
2918 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2919 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2920}
2921#else
2922static inline void
2923cifs_reclassify_socket4(struct socket *sock)
2924{
2925}
2926
2927static inline void
2928cifs_reclassify_socket6(struct socket *sock)
2929{
2930}
2931#endif
2932
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002934static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935{
Steve French50c2f752007-07-13 00:33:32 +00002936 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937
Steve French50c2f752007-07-13 00:33:32 +00002938 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 /* mask a nibble at a time and encode */
2940 target[j] = 'A' + (0x0F & (source[i] >> 4));
2941 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002942 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 }
2944
2945}
2946
Ben Greear3eb9a882010-09-01 17:06:02 -07002947static int
2948bind_socket(struct TCP_Server_Info *server)
2949{
2950 int rc = 0;
2951 if (server->srcaddr.ss_family != AF_UNSPEC) {
2952 /* Bind to the specified local IP address */
2953 struct socket *socket = server->ssocket;
2954 rc = socket->ops->bind(socket,
2955 (struct sockaddr *) &server->srcaddr,
2956 sizeof(server->srcaddr));
2957 if (rc < 0) {
2958 struct sockaddr_in *saddr4;
2959 struct sockaddr_in6 *saddr6;
2960 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2961 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2962 if (saddr6->sin6_family == AF_INET6)
2963 cERROR(1, "cifs: "
2964 "Failed to bind to: %pI6c, error: %d\n",
2965 &saddr6->sin6_addr, rc);
2966 else
2967 cERROR(1, "cifs: "
2968 "Failed to bind to: %pI4, error: %d\n",
2969 &saddr4->sin_addr.s_addr, rc);
2970 }
2971 }
2972 return rc;
2973}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974
2975static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002976ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977{
2978 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002979 /*
2980 * some servers require RFC1001 sessinit before sending
2981 * negprot - BB check reconnection in case where second
2982 * sessinit is sent but no second negprot
2983 */
2984 struct rfc1002_session_packet *ses_init_buf;
2985 struct smb_hdr *smb_buf;
2986 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2987 GFP_KERNEL);
2988 if (ses_init_buf) {
2989 ses_init_buf->trailer.session_req.called_len = 32;
2990
2991 if (server->server_RFC1001_name &&
2992 server->server_RFC1001_name[0] != 0)
2993 rfc1002mangle(ses_init_buf->trailer.
2994 session_req.called_name,
2995 server->server_RFC1001_name,
2996 RFC1001_NAME_LEN_WITH_NULL);
2997 else
2998 rfc1002mangle(ses_init_buf->trailer.
2999 session_req.called_name,
3000 DEFAULT_CIFS_CALLED_NAME,
3001 RFC1001_NAME_LEN_WITH_NULL);
3002
3003 ses_init_buf->trailer.session_req.calling_len = 32;
3004
3005 /*
3006 * calling name ends in null (byte 16) from old smb
3007 * convention.
3008 */
3009 if (server->workstation_RFC1001_name &&
3010 server->workstation_RFC1001_name[0] != 0)
3011 rfc1002mangle(ses_init_buf->trailer.
3012 session_req.calling_name,
3013 server->workstation_RFC1001_name,
3014 RFC1001_NAME_LEN_WITH_NULL);
3015 else
3016 rfc1002mangle(ses_init_buf->trailer.
3017 session_req.calling_name,
3018 "LINUX_CIFS_CLNT",
3019 RFC1001_NAME_LEN_WITH_NULL);
3020
3021 ses_init_buf->trailer.session_req.scope1 = 0;
3022 ses_init_buf->trailer.session_req.scope2 = 0;
3023 smb_buf = (struct smb_hdr *)ses_init_buf;
3024
3025 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003026 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003027 rc = smb_send(server, smb_buf, 0x44);
3028 kfree(ses_init_buf);
3029 /*
3030 * RFC1001 layer in at least one server
3031 * requires very short break before negprot
3032 * presumably because not expecting negprot
3033 * to follow so fast. This is a simple
3034 * solution that works without
3035 * complicating the code and causes no
3036 * significant slowing down on mount
3037 * for everyone else
3038 */
3039 usleep_range(1000, 2000);
3040 }
3041 /*
3042 * else the negprot may still work without this
3043 * even though malloc failed
3044 */
3045
3046 return rc;
3047}
3048
3049static int
3050generic_ip_connect(struct TCP_Server_Info *server)
3051{
3052 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003053 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003054 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003055 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003056 struct sockaddr *saddr;
3057
3058 saddr = (struct sockaddr *) &server->dstaddr;
3059
3060 if (server->dstaddr.ss_family == AF_INET6) {
3061 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3062 slen = sizeof(struct sockaddr_in6);
3063 sfamily = AF_INET6;
3064 } else {
3065 sport = ((struct sockaddr_in *) saddr)->sin_port;
3066 slen = sizeof(struct sockaddr_in);
3067 sfamily = AF_INET;
3068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003070 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003071 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3072 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003074 cERROR(1, "Error %d creating socket", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003075 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003078
3079 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003080 cFYI(1, "Socket created");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003081 server->ssocket = socket;
3082 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003083 if (sfamily == AF_INET6)
3084 cifs_reclassify_socket6(socket);
3085 else
3086 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 }
3088
Ben Greear3eb9a882010-09-01 17:06:02 -07003089 rc = bind_socket(server);
3090 if (rc < 0)
3091 return rc;
3092
Jeff Laytond5c56052008-12-01 18:42:33 -05003093 /*
3094 * Eventually check for other socket options to change from
3095 * the default. sock_setsockopt not used because it expects
3096 * user space buffer
3097 */
3098 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003099 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003100
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003101 /* make the bufsizes depend on wsize/rsize and max requests */
3102 if (server->noautotune) {
3103 if (socket->sk->sk_sndbuf < (200 * 1024))
3104 socket->sk->sk_sndbuf = 200 * 1024;
3105 if (socket->sk->sk_rcvbuf < (140 * 1024))
3106 socket->sk->sk_rcvbuf = 140 * 1024;
3107 }
3108
Steve French6a5fa2362010-01-01 01:28:43 +00003109 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003110 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003111 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3112 (char *)&val, sizeof(val));
3113 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003114 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003115 }
3116
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003117 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
3118 socket->sk->sk_sndbuf,
3119 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3120
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003121 rc = socket->ops->connect(socket, saddr, slen, 0);
3122 if (rc < 0) {
3123 cFYI(1, "Error %d connecting to server", rc);
3124 sock_release(socket);
3125 server->ssocket = NULL;
3126 return rc;
3127 }
3128
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003129 if (sport == htons(RFC1001_PORT))
3130 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003131
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 return rc;
3133}
3134
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003135static int
3136ip_connect(struct TCP_Server_Info *server)
3137{
Steve French6da97912011-03-13 18:55:55 +00003138 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003139 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3140 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3141
3142 if (server->dstaddr.ss_family == AF_INET6)
3143 sport = &addr6->sin6_port;
3144 else
3145 sport = &addr->sin_port;
3146
3147 if (*sport == 0) {
3148 int rc;
3149
3150 /* try with 445 port at first */
3151 *sport = htons(CIFS_PORT);
3152
3153 rc = generic_ip_connect(server);
3154 if (rc >= 0)
3155 return rc;
3156
3157 /* if it failed, try with 139 port */
3158 *sport = htons(RFC1001_PORT);
3159 }
3160
3161 return generic_ip_connect(server);
3162}
3163
Steve French96daf2b2011-05-27 04:34:02 +00003164void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003165 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003166{
3167 /* if we are reconnecting then should we check to see if
3168 * any requested capabilities changed locally e.g. via
3169 * remount but we can not do much about it here
3170 * if they have (even if we could detect it by the following)
3171 * Perhaps we could add a backpointer to array of sb from tcon
3172 * or if we change to make all sb to same share the same
3173 * sb as NFS - then we only have one backpointer to sb.
3174 * What if we wanted to mount the server share twice once with
3175 * and once without posixacls or posix paths? */
3176 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003177
Steve Frenchc18c8422007-07-18 23:21:09 +00003178 if (vol_info && vol_info->no_linux_ext) {
3179 tcon->fsUnixInfo.Capability = 0;
3180 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003181 cFYI(1, "Linux protocol extensions disabled");
Steve Frenchc18c8422007-07-18 23:21:09 +00003182 return;
3183 } else if (vol_info)
3184 tcon->unix_ext = 1; /* Unix Extensions supported */
3185
3186 if (tcon->unix_ext == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003187 cFYI(1, "Unix extensions disabled so not set on reconnect");
Steve Frenchc18c8422007-07-18 23:21:09 +00003188 return;
3189 }
Steve French50c2f752007-07-13 00:33:32 +00003190
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003191 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003192 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French6848b732011-05-26 18:38:54 +00003193 cFYI(1, "unix caps which server supports %lld", cap);
Steve French8af18972007-02-14 04:42:51 +00003194 /* check for reconnect case in which we do not
3195 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003196 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003197 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003198 originally at mount time */
3199 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3200 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003201 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3202 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003203 cERROR(1, "POSIXPATH support change");
Steve French8af18972007-02-14 04:42:51 +00003204 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003205 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003206 cERROR(1, "possible reconnect error");
3207 cERROR(1, "server disabled POSIX path support");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003208 }
Steve French8af18972007-02-14 04:42:51 +00003209 }
Steve French50c2f752007-07-13 00:33:32 +00003210
Steve French6848b732011-05-26 18:38:54 +00003211 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3212 cERROR(1, "per-share encryption not supported yet");
3213
Steve French8af18972007-02-14 04:42:51 +00003214 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003215 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003216 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003217 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003218 cFYI(1, "negotiated posix acl support");
Al Viro2c6292a2011-06-17 09:05:48 -04003219 if (cifs_sb)
3220 cifs_sb->mnt_cifs_flags |=
3221 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003222 }
3223
Steve French75865f8c2007-06-24 18:30:48 +00003224 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003225 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003226 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003227 cFYI(1, "negotiate posix pathnames");
Al Viro2c6292a2011-06-17 09:05:48 -04003228 if (cifs_sb)
3229 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003230 CIFS_MOUNT_POSIX_PATHS;
3231 }
Steve French50c2f752007-07-13 00:33:32 +00003232
Joe Perchesb6b38f72010-04-21 03:50:45 +00003233 cFYI(1, "Negotiate caps 0x%x", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003234#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003235 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003236 cFYI(1, "FCNTL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003237 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003238 cFYI(1, "EXTATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003239 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003240 cFYI(1, "POSIX path cap");
Steve French75865f8c2007-06-24 18:30:48 +00003241 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003242 cFYI(1, "XATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003243 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003244 cFYI(1, "POSIX ACL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003245 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003246 cFYI(1, "very large read cap");
Steve French75865f8c2007-06-24 18:30:48 +00003247 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003248 cFYI(1, "very large write cap");
Steve French6848b732011-05-26 18:38:54 +00003249 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3250 cFYI(1, "transport encryption cap");
3251 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3252 cFYI(1, "mandatory transport encryption cap");
Steve French8af18972007-02-14 04:42:51 +00003253#endif /* CIFS_DEBUG2 */
3254 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003255 if (vol_info == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003256 cFYI(1, "resetting capabilities failed");
Steve French442aa312007-09-24 20:25:46 +00003257 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003258 cERROR(1, "Negotiating Unix capabilities "
Steve French5a44b312007-09-20 15:16:24 +00003259 "with the server failed. Consider "
3260 "mounting with the Unix Extensions\n"
3261 "disabled, if problems are found, "
3262 "by specifying the nounix mount "
Joe Perchesb6b38f72010-04-21 03:50:45 +00003263 "option.");
Steve French5a44b312007-09-20 15:16:24 +00003264
Steve French8af18972007-02-14 04:42:51 +00003265 }
3266 }
3267}
3268
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003269void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3270 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003271{
Jeff Layton2de970f2010-10-06 19:51:12 -04003272 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3273
Al Viro2ced6f62011-06-17 09:20:04 -04003274 spin_lock_init(&cifs_sb->tlink_tree_lock);
3275 cifs_sb->tlink_tree = RB_ROOT;
3276
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003277 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003278 * Temporarily set r/wsize for matching superblock. If we end up using
3279 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003280 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003281 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003282 cifs_sb->wsize = pvolume_info->wsize;
3283
Steve French3b795212008-11-13 19:45:32 +00003284 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3285 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3286 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3287 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Al Viro5206efd2011-07-26 03:22:14 -04003288 cFYI(1, "file mode: 0x%hx dir mode: 0x%hx",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003289 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003290
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303291 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003292 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303293
Steve French3b795212008-11-13 19:45:32 +00003294 if (pvolume_info->noperm)
3295 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3296 if (pvolume_info->setuids)
3297 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3298 if (pvolume_info->server_ino)
3299 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3300 if (pvolume_info->remap)
3301 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3302 if (pvolume_info->no_xattr)
3303 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3304 if (pvolume_info->sfu_emul)
3305 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3306 if (pvolume_info->nobrl)
3307 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003308 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003309 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003310 if (pvolume_info->mand_lock)
3311 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003312 if (pvolume_info->rwpidforward)
3313 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003314 if (pvolume_info->cifs_acl)
3315 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003316 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003317 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003318 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3319 }
3320 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003321 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003322 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3323 }
Steve French3b795212008-11-13 19:45:32 +00003324 if (pvolume_info->override_uid)
3325 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3326 if (pvolume_info->override_gid)
3327 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3328 if (pvolume_info->dynperm)
3329 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303330 if (pvolume_info->fsc)
3331 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003332 if (pvolume_info->multiuser)
3333 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3334 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003335 if (pvolume_info->strict_io)
3336 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003337 if (pvolume_info->direct_io) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003338 cFYI(1, "mounting share using direct i/o");
Steve French3b795212008-11-13 19:45:32 +00003339 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3340 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02003341 if (pvolume_info->mfsymlinks) {
3342 if (pvolume_info->sfu_emul) {
3343 cERROR(1, "mount option mfsymlinks ignored if sfu "
3344 "mount option is used");
3345 } else {
3346 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3347 }
3348 }
Steve French3b795212008-11-13 19:45:32 +00003349
3350 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesb6b38f72010-04-21 03:50:45 +00003351 cERROR(1, "mount option dynperm ignored if cifsacl "
3352 "mount option supported");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003353}
3354
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003355/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003356 * When the server supports very large reads and writes via POSIX extensions,
3357 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
3358 * including the RFC1001 length.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003359 *
3360 * Note that this might make for "interesting" allocation problems during
Jeff Layton1190f6a2011-06-22 17:33:57 -04003361 * writeback however as we have to allocate an array of pointers for the
3362 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003363 *
3364 * For reads, there is a similar problem as we need to allocate an array
3365 * of kvecs to handle the receive, though that should only need to be done
3366 * once.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003367 */
Jeff Layton1190f6a2011-06-22 17:33:57 -04003368#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003369#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003370
3371/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003372 * When the server doesn't allow large posix writes, only allow a rsize/wsize
3373 * of 2^17-1 minus the size of the call header. That allows for a read or
3374 * write up to the maximum size described by RFC1002.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003375 */
Pavel Shilovsky94443f42011-10-07 18:57:45 +04003376#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003377#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003378
3379/*
3380 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
3381 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
3382 * a single wsize request with a single call.
3383 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003384#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
3385
3386/*
Jeff Laytonce91acb2012-01-17 16:08:51 -05003387 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
3388 * those values when posix extensions aren't in force. In actuality here, we
3389 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
3390 * to be ok with the extra byte even though Windows doesn't send writes that
3391 * are that large.
3392 *
3393 * Citation:
3394 *
3395 * 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 -04003396 */
3397#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
Jeff Laytonce91acb2012-01-17 16:08:51 -05003398#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003399
3400static unsigned int
Steve French96daf2b2011-05-27 04:34:02 +00003401cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003402{
3403 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3404 struct TCP_Server_Info *server = tcon->ses->server;
Jeff Laytonce91acb2012-01-17 16:08:51 -05003405 unsigned int wsize;
3406
3407 /* start with specified wsize, or default */
3408 if (pvolume_info->wsize)
3409 wsize = pvolume_info->wsize;
3410 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3411 wsize = CIFS_DEFAULT_IOSIZE;
3412 else
3413 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003414
3415 /* can server support 24-bit write sizes? (via UNIX extensions) */
3416 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
Jeff Layton1190f6a2011-06-22 17:33:57 -04003417 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003418
Jeff Layton1190f6a2011-06-22 17:33:57 -04003419 /*
3420 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
3421 * Limit it to max buffer offered by the server, minus the size of the
3422 * WRITEX header, not including the 4 byte RFC1001 length.
3423 */
3424 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
3425 (!(server->capabilities & CAP_UNIX) &&
3426 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
3427 wsize = min_t(unsigned int, wsize,
3428 server->maxBuf - sizeof(WRITE_REQ) + 4);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003429
3430 /* hard limit of CIFS_MAX_WSIZE */
3431 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3432
3433 return wsize;
3434}
3435
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003436static unsigned int
3437cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3438{
3439 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3440 struct TCP_Server_Info *server = tcon->ses->server;
3441 unsigned int rsize, defsize;
3442
3443 /*
3444 * Set default value...
3445 *
3446 * HACK alert! Ancient servers have very small buffers. Even though
3447 * MS-CIFS indicates that servers are only limited by the client's
3448 * bufsize for reads, testing against win98se shows that it throws
3449 * INVALID_PARAMETER errors if you try to request too large a read.
3450 *
3451 * If the server advertises a MaxBufferSize of less than one page,
3452 * assume that it also can't satisfy reads larger than that either.
3453 *
3454 * FIXME: Is there a better heuristic for this?
3455 */
3456 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
3457 defsize = CIFS_DEFAULT_IOSIZE;
3458 else if (server->capabilities & CAP_LARGE_READ_X)
3459 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
3460 else if (server->maxBuf >= PAGE_CACHE_SIZE)
3461 defsize = CIFSMaxBufSize;
3462 else
3463 defsize = server->maxBuf - sizeof(READ_RSP);
3464
3465 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
3466
3467 /*
3468 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
3469 * the client's MaxBufferSize.
3470 */
3471 if (!(server->capabilities & CAP_LARGE_READ_X))
3472 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3473
3474 /* hard limit of CIFS_MAX_RSIZE */
3475 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3476
3477 return rsize;
3478}
3479
Igor Mammedove4cce942009-02-10 14:10:26 +03003480static int
Steve French96daf2b2011-05-27 04:34:02 +00003481is_path_accessible(int xid, struct cifs_tcon *tcon,
Igor Mammedove4cce942009-02-10 14:10:26 +03003482 struct cifs_sb_info *cifs_sb, const char *full_path)
3483{
3484 int rc;
Igor Mammedove4cce942009-02-10 14:10:26 +03003485 FILE_ALL_INFO *pfile_info;
3486
Igor Mammedove4cce942009-02-10 14:10:26 +03003487 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
3488 if (pfile_info == NULL)
3489 return -ENOMEM;
3490
3491 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
3492 0 /* not legacy */, cifs_sb->local_nls,
3493 cifs_sb->mnt_cifs_flags &
3494 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton221d1d72011-05-17 06:40:30 -04003495
3496 if (rc == -EOPNOTSUPP || rc == -EINVAL)
3497 rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
3498 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
3499 CIFS_MOUNT_MAP_SPECIAL_CHR);
Igor Mammedove4cce942009-02-10 14:10:26 +03003500 kfree(pfile_info);
3501 return rc;
3502}
3503
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003504static void
3505cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003506{
Sean Finneyb9468452011-04-11 13:19:32 +00003507 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003508 kzfree(volume_info->password);
Steve French13589c42011-08-18 04:41:55 +00003509 if (volume_info->UNCip != volume_info->UNC + 2)
3510 kfree(volume_info->UNCip);
Jesper Juhl95c75452011-08-27 18:58:34 +02003511 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003512 kfree(volume_info->domainname);
3513 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003514 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003515}
3516
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003517void
3518cifs_cleanup_volume_info(struct smb_vol *volume_info)
3519{
3520 if (!volume_info)
3521 return;
3522 cleanup_volume_info_contents(volume_info);
3523 kfree(volume_info);
3524}
3525
3526
Steve French2d6d5892009-04-09 00:36:44 +00003527#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003528/* build_path_to_root returns full path to root when
3529 * we do not have an exiting connection (tcon) */
3530static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003531build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003532 const struct cifs_sb_info *cifs_sb)
3533{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003534 char *full_path, *pos;
3535 unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
3536 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003537
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003538 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003539 if (full_path == NULL)
3540 return ERR_PTR(-ENOMEM);
3541
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003542 strncpy(full_path, vol->UNC, unc_len);
3543 pos = full_path + unc_len;
3544
3545 if (pplen) {
3546 strncpy(pos, vol->prepath, pplen);
3547 pos += pplen;
3548 }
3549
3550 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003551 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003552 cFYI(1, "%s: full_path=%s", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003553 return full_path;
3554}
Sean Finneydd613942011-04-11 13:19:30 +00003555
3556/*
3557 * Perform a dfs referral query for a share and (optionally) prefix
3558 *
Sean Finney046462a2011-04-11 13:19:33 +00003559 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3560 * to a string containing updated options for the submount. Otherwise it
3561 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003562 *
3563 * Returns the rc from get_dfs_path to the caller, which can be used to
3564 * determine whether there were referrals.
3565 */
3566static int
Steve French96daf2b2011-05-27 04:34:02 +00003567expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
Sean Finneydd613942011-04-11 13:19:30 +00003568 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003569 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003570{
3571 int rc;
3572 unsigned int num_referrals = 0;
3573 struct dfs_info3_param *referrals = NULL;
3574 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3575
3576 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3577 if (IS_ERR(full_path))
3578 return PTR_ERR(full_path);
3579
3580 /* For DFS paths, skip the first '\' of the UNC */
3581 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3582
3583 rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
3584 &num_referrals, &referrals,
3585 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3586
3587 if (!rc && num_referrals > 0) {
3588 char *fake_devname = NULL;
3589
3590 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3591 full_path + 1, referrals,
3592 &fake_devname);
3593
3594 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003595
Sean Finneydd613942011-04-11 13:19:30 +00003596 if (IS_ERR(mdata)) {
3597 rc = PTR_ERR(mdata);
3598 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003599 } else {
3600 cleanup_volume_info_contents(volume_info);
3601 memset(volume_info, '\0', sizeof(*volume_info));
3602 rc = cifs_setup_volume_info(volume_info, mdata,
3603 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003604 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003605 kfree(fake_devname);
3606 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003607 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003608 }
3609 kfree(full_path);
3610 return rc;
3611}
Steve French2d6d5892009-04-09 00:36:44 +00003612#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003613
Jeff Layton04db79b2011-07-06 08:10:38 -04003614static int
3615cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3616 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003618 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003619
Jeff Layton04db79b2011-07-06 08:10:38 -04003620 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3621 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
Jeff Layton7586b762008-12-01 18:41:49 -05003623 if (volume_info->nullauth) {
Jeff Layton04febab2012-01-17 16:09:15 -05003624 cFYI(1, "Anonymous login");
3625 kfree(volume_info->username);
3626 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003627 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 /* BB fixme parse for domain name here */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003629 cFYI(1, "Username: %s", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 } else {
Steve Frenchbf820672005-12-01 22:32:42 -08003631 cifserror("No username specified");
Steve French50c2f752007-07-13 00:33:32 +00003632 /* In userspace mount helper we can get user name from alternate
3633 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003634 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 }
3636
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003638 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003639 /* load_nls_default cannot return null */
3640 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003642 volume_info->local_nls = load_nls(volume_info->iocharset);
3643 if (volume_info->local_nls == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003644 cERROR(1, "CIFS mount error: iocharset %s not found",
3645 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003646 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 }
3648 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003649
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003650 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003651}
3652
3653struct smb_vol *
3654cifs_get_volume_info(char *mount_data, const char *devname)
3655{
3656 int rc;
3657 struct smb_vol *volume_info;
3658
3659 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
3660 if (!volume_info)
3661 return ERR_PTR(-ENOMEM);
3662
3663 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3664 if (rc) {
3665 cifs_cleanup_volume_info(volume_info);
3666 volume_info = ERR_PTR(rc);
3667 }
3668
3669 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003670}
3671
3672int
Al Viro2c6292a2011-06-17 09:05:48 -04003673cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003674{
Jeff Layton1daaae82012-03-21 06:30:40 -04003675 int rc;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003676 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003677 struct cifs_ses *pSesInfo;
3678 struct cifs_tcon *tcon;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003679 struct TCP_Server_Info *srvTcp;
3680 char *full_path;
3681 struct tcon_link *tlink;
3682#ifdef CONFIG_CIFS_DFS_UPCALL
3683 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003684#endif
Al Virodd854462011-06-17 08:24:42 -04003685
3686 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3687 if (rc)
3688 return rc;
3689
Jeff Layton20547492011-07-09 12:21:07 -04003690#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003691try_mount_again:
3692 /* cleanup activities if we're chasing a referral */
3693 if (referral_walks_count) {
3694 if (tcon)
3695 cifs_put_tcon(tcon);
3696 else if (pSesInfo)
3697 cifs_put_smb_ses(pSesInfo);
3698
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003699 FreeXid(xid);
3700 }
3701#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003702 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003703 tcon = NULL;
3704 pSesInfo = NULL;
3705 srvTcp = NULL;
3706 full_path = NULL;
3707 tlink = NULL;
3708
3709 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
Jeff Layton63c038c2008-12-01 18:41:46 -05003711 /* get a reference to a tcp session */
Jeff Layton7586b762008-12-01 18:41:49 -05003712 srvTcp = cifs_get_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05003713 if (IS_ERR(srvTcp)) {
3714 rc = PTR_ERR(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003715 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003716 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 }
3718
Jeff Layton36988c72010-04-24 07:57:43 -04003719 /* get a reference to a SMB session */
3720 pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
3721 if (IS_ERR(pSesInfo)) {
3722 rc = PTR_ERR(pSesInfo);
3723 pSesInfo = NULL;
3724 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 }
Steve French50c2f752007-07-13 00:33:32 +00003726
Jeff Laytond00c28d2010-04-24 07:57:44 -04003727 /* search for existing tcon to this server share */
3728 tcon = cifs_get_tcon(pSesInfo, volume_info);
3729 if (IS_ERR(tcon)) {
3730 rc = PTR_ERR(tcon);
3731 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003732 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003733 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003734
Steve French6848b732011-05-26 18:38:54 +00003735 /* tell server which Unix caps we support */
3736 if (tcon->ses->capabilities & CAP_UNIX) {
3737 /* reset of caps checks mount to see if unix extensions
3738 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003739 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003740 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3741 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3742 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3743 rc = -EACCES;
3744 goto mount_fail_check;
3745 }
3746 } else
3747 tcon->unix_ext = 0; /* server does not support them */
3748
Steve Frenchd82c2df2008-11-15 00:07:26 +00003749 /* do not care if following two calls succeed - informational */
3750 if (!tcon->ipc) {
3751 CIFSSMBQFSDeviceInfo(xid, tcon);
3752 CIFSSMBQFSAttributeInfo(xid, tcon);
3753 }
3754
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003755 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003756 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003757
Jeff Layton66bfaad2011-10-19 15:30:35 -04003758 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003759 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003760
Igor Mammedove4cce942009-02-10 14:10:26 +03003761remote_path_check:
3762#ifdef CONFIG_CIFS_DFS_UPCALL
3763 /*
3764 * Perform an unconditional check for whether there are DFS
3765 * referrals for this path without prefix, to provide support
3766 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003767 * with PATH_NOT_COVERED to requests that include the prefix.
3768 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003769 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003770 if (referral_walks_count == 0) {
3771 int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
3772 cifs_sb, false);
3773 if (!refrc) {
3774 referral_walks_count++;
3775 goto try_mount_again;
3776 }
3777 }
3778#endif
3779
Steve Frenchf87d39d2011-05-27 03:50:55 +00003780 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 if (!rc && tcon) {
3782 /* build_path_to_root works only when we have a valid tcon */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003783 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Steve French7c7b25b2006-06-01 19:20:10 +00003784 if (full_path == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 rc = -ENOMEM;
3786 goto mount_fail_check;
3787 }
3788 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
3789 if (rc != 0 && rc != -EREMOTE) {
3790 kfree(full_path);
3791 goto mount_fail_check;
3792 }
3793 kfree(full_path);
3794 }
3795
3796 /* get referral if needed */
3797 if (rc == -EREMOTE) {
3798#ifdef CONFIG_CIFS_DFS_UPCALL
3799 if (referral_walks_count > MAX_NESTED_LINKS) {
3800 /*
Steve Frencheeac8042006-01-13 21:34:58 -08003801 * BB: when we implement proper loop detection,
Steve French4523cc32007-04-30 20:13:06 +00003802 * we will remove this check. But now we need it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 * to prevent an indefinite loop if 'DFS tree' is
3804 * misconfigured (i.e. has loops).
3805 */
3806 rc = -ELOOP;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003807 goto mount_fail_check;
3808 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003809
Sean Finneydd613942011-04-11 13:19:30 +00003810 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003811 true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003812
Sean Finneydd613942011-04-11 13:19:30 +00003813 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003814 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003815 goto try_mount_again;
3816 }
Sean Finneydd613942011-04-11 13:19:30 +00003817 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003818#else /* No DFS support, return error on mount */
3819 rc = -EOPNOTSUPP;
3820#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003821 }
3822
Jeff Layton9d002df2010-10-06 19:51:11 -04003823 if (rc)
3824 goto mount_fail_check;
3825
3826 /* now, hang the tcon off of the superblock */
3827 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3828 if (tlink == NULL) {
3829 rc = -ENOMEM;
3830 goto mount_fail_check;
3831 }
3832
Jeff Laytonb647c352010-10-28 11:16:44 -04003833 tlink->tl_uid = pSesInfo->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003834 tlink->tl_tcon = tcon;
3835 tlink->tl_time = jiffies;
3836 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3837 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3838
Jeff Layton413e6612010-10-28 13:33:38 -04003839 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003840 spin_lock(&cifs_sb->tlink_tree_lock);
3841 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3842 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003843
Jeff Laytonda472fc2012-03-23 14:40:53 -04003844 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003845 TLINK_IDLE_EXPIRE);
3846
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003847mount_fail_check:
3848 /* on error free sesinfo and tcon struct if needed */
3849 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003850 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003851 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003852 if (tcon)
3853 cifs_put_tcon(tcon);
3854 else if (pSesInfo)
3855 cifs_put_smb_ses(pSesInfo);
3856 else
3857 cifs_put_tcp_session(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003858 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003859 }
3860
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 FreeXid(xid);
3863 return rc;
3864}
3865
Jeff Layton8d1bca32011-06-11 21:17:10 -04003866/*
3867 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3868 * pointer may be NULL.
3869 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870int
Steve French96daf2b2011-05-27 04:34:02 +00003871CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3872 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 const struct nls_table *nls_codepage)
3874{
3875 struct smb_hdr *smb_buffer;
3876 struct smb_hdr *smb_buffer_response;
3877 TCONX_REQ *pSMB;
3878 TCONX_RSP *pSMBr;
3879 unsigned char *bcc_ptr;
3880 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003881 int length;
3882 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
3884 if (ses == NULL)
3885 return -EIO;
3886
3887 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003888 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003890
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 smb_buffer_response = smb_buffer;
3892
3893 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3894 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003895
3896 smb_buffer->Mid = GetNextMid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 smb_buffer->Uid = ses->Suid;
3898 pSMB = (TCONX_REQ *) smb_buffer;
3899 pSMBr = (TCONX_RSP *) smb_buffer_response;
3900
3901 pSMB->AndXCommand = 0xFF;
3902 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003904 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003905 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003906 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003907 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003908 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003909 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003910 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003911 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3912 specified as required (when that support is added to
3913 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003914 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003915 by Samba (not sure whether other servers allow
3916 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003917#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003918 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003919 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003920 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003921 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003922 SECMODE_PW_ENCRYPT ? true : false,
3923 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003924 else
3925#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003926 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003927 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003928
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003929 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003930 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003931 /* must align unicode strings */
3932 *bcc_ptr = 0; /* null byte password */
3933 bcc_ptr++;
3934 }
Steve Frencheeac8042006-01-13 21:34:58 -08003935 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936
Steve French96daf2b2011-05-27 04:34:02 +00003937 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003938 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3940
3941 if (ses->capabilities & CAP_STATUS32) {
3942 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3943 }
3944 if (ses->capabilities & CAP_DFS) {
3945 smb_buffer->Flags2 |= SMBFLG2_DFS;
3946 }
3947 if (ses->capabilities & CAP_UNICODE) {
3948 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3949 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003950 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003951 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003952 (/* server len*/ + 256 /* share len */), nls_codepage);
3953 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 bcc_ptr += 2; /* skip trailing null */
3955 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 strcpy(bcc_ptr, tree);
3957 bcc_ptr += strlen(tree) + 1;
3958 }
3959 strcpy(bcc_ptr, "?????");
3960 bcc_ptr += strlen("?????");
3961 bcc_ptr += 1;
3962 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003963 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3964 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 pSMB->ByteCount = cpu_to_le16(count);
3966
Steve French133672e2007-11-13 22:41:37 +00003967 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003968 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970 /* above now done in SendReceive */
3971 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003972 bool is_unicode;
3973
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003975 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 tcon->tid = smb_buffer_response->Tid;
3977 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003978 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003979 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003980 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
3981 is_unicode = true;
3982 else
3983 is_unicode = false;
3984
Jeff Laytoncc20c032009-04-30 07:16:21 -04003985
Steve French50c2f752007-07-13 00:33:32 +00003986 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00003987 if (length == 3) {
3988 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3989 (bcc_ptr[2] == 'C')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003990 cFYI(1, "IPC connection");
Steve French7f8ed422007-09-28 22:28:55 +00003991 tcon->ipc = 1;
3992 }
3993 } else if (length == 2) {
3994 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3995 /* the most common case */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003996 cFYI(1, "disk share connection");
Steve French7f8ed422007-09-28 22:28:55 +00003997 }
3998 }
Steve French50c2f752007-07-13 00:33:32 +00003999 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004000 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004002
4003 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004004 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004005 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004006 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004007 nls_codepage);
4008
Joe Perchesb6b38f72010-04-21 03:50:45 +00004009 cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004010
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004011 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004012 (smb_buffer_response->WordCount == 7))
4013 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004014 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4015 else
4016 tcon->Flags = 0;
Joe Perchesb6b38f72010-04-21 03:50:45 +00004017 cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004019 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 ses->ipc_tid = smb_buffer_response->Tid;
4021 }
4022
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004023 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024 return rc;
4025}
4026
Al Viro2a9b9952011-06-17 09:27:16 -04004027void
4028cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029{
Jeff Laytonb647c352010-10-28 11:16:44 -04004030 struct rb_root *root = &cifs_sb->tlink_tree;
4031 struct rb_node *node;
4032 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Jeff Layton2de970f2010-10-06 19:51:12 -04004034 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4035
Jeff Laytonb647c352010-10-28 11:16:44 -04004036 spin_lock(&cifs_sb->tlink_tree_lock);
4037 while ((node = rb_first(root))) {
4038 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4039 cifs_get_tlink(tlink);
4040 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4041 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004042
Jeff Laytonb647c352010-10-28 11:16:44 -04004043 spin_unlock(&cifs_sb->tlink_tree_lock);
4044 cifs_put_tlink(tlink);
4045 spin_lock(&cifs_sb->tlink_tree_lock);
4046 }
4047 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004048
Al Virodd854462011-06-17 08:24:42 -04004049 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004050 kfree(cifs_sb->mountdata);
4051 unload_nls(cifs_sb->local_nls);
4052 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00004053}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054
Steve French96daf2b2011-05-27 04:34:02 +00004055int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056{
4057 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004058 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059
Jeff Layton198b5682010-04-24 07:57:48 -04004060 /* only send once per connect */
4061 if (server->maxBuf != 0)
4062 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004064 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004065 rc = CIFSSMBNegotiate(xid, ses);
4066 if (rc == -EAGAIN) {
4067 /* retry only once on 1st time connection */
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004068 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004069 rc = CIFSSMBNegotiate(xid, ses);
4070 if (rc == -EAGAIN)
4071 rc = -EHOSTDOWN;
4072 }
4073 if (rc == 0) {
4074 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004075 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004076 server->tcpStatus = CifsGood;
4077 else
4078 rc = -EHOSTDOWN;
4079 spin_unlock(&GlobalMid_Lock);
4080
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 }
Steve French26b994f2008-08-06 05:11:33 +00004082
Jeff Layton198b5682010-04-24 07:57:48 -04004083 return rc;
4084}
Steve French26b994f2008-08-06 05:11:33 +00004085
Jeff Layton198b5682010-04-24 07:57:48 -04004086
Steve French96daf2b2011-05-27 04:34:02 +00004087int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
Jeff Layton198b5682010-04-24 07:57:48 -04004088 struct nls_table *nls_info)
4089{
4090 int rc = 0;
4091 struct TCP_Server_Info *server = ses->server;
4092
4093 ses->flags = 0;
4094 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004095 if (linuxExtEnabled == 0)
Jeff Layton198b5682010-04-24 07:57:48 -04004096 ses->capabilities &= (~CAP_UNIX);
Steve French20418ac2009-04-30 16:13:32 +00004097
Joe Perchesb6b38f72010-04-21 03:50:45 +00004098 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
Steve French96daf2b2011-05-27 04:34:02 +00004099 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004100
Jeff Layton198b5682010-04-24 07:57:48 -04004101 rc = CIFS_SessSetup(xid, ses, nls_info);
Steve French26b994f2008-08-06 05:11:33 +00004102 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004103 cERROR(1, "Send error in SessSetup = %d", rc);
Steve French26b994f2008-08-06 05:11:33 +00004104 } else {
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004105 mutex_lock(&ses->server->srv_mutex);
4106 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004107 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004108 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004109 server->sequence_number = 0x2;
4110 server->session_estab = true;
4111 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004112 }
4113 mutex_unlock(&server->srv_mutex);
4114
Joe Perchesb6b38f72010-04-21 03:50:45 +00004115 cFYI(1, "CIFS Session Established successfully");
Steve French20418ac2009-04-30 16:13:32 +00004116 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04004117 ses->status = CifsGood;
4118 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00004119 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00004120 }
4121
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004122 kfree(ses->auth_key.response);
4123 ses->auth_key.response = NULL;
4124 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05004125 kfree(ses->ntlmssp);
4126 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004127
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 return rc;
4129}
4130
Jeff Layton8a8798a2012-01-17 16:09:15 -05004131static int
4132cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4133{
4134 switch (ses->server->secType) {
4135 case Kerberos:
4136 vol->secFlg = CIFSSEC_MUST_KRB5;
4137 return 0;
4138 case NTLMv2:
4139 vol->secFlg = CIFSSEC_MUST_NTLMV2;
4140 break;
4141 case NTLM:
4142 vol->secFlg = CIFSSEC_MUST_NTLM;
4143 break;
4144 case RawNTLMSSP:
4145 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
4146 break;
4147 case LANMAN:
4148 vol->secFlg = CIFSSEC_MUST_LANMAN;
4149 break;
4150 }
4151
4152 return cifs_set_cifscreds(vol, ses);
4153}
4154
Steve French96daf2b2011-05-27 04:34:02 +00004155static struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004156cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
4157{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004158 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004159 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4160 struct cifs_ses *ses;
4161 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004162 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004163
4164 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004165 if (vol_info == NULL)
4166 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004167
Jeff Layton9d002df2010-10-06 19:51:11 -04004168 vol_info->local_nls = cifs_sb->local_nls;
4169 vol_info->linux_uid = fsuid;
4170 vol_info->cred_uid = fsuid;
4171 vol_info->UNC = master_tcon->treeName;
4172 vol_info->retry = master_tcon->retry;
4173 vol_info->nocase = master_tcon->nocase;
4174 vol_info->local_lease = master_tcon->local_lease;
4175 vol_info->no_linux_ext = !master_tcon->unix_ext;
4176
Jeff Layton8a8798a2012-01-17 16:09:15 -05004177 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4178 if (rc) {
4179 tcon = ERR_PTR(rc);
4180 goto out;
4181 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004182
4183 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304184 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004185 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304186 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004187
4188 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4189 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004190 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004191 cifs_put_tcp_session(master_tcon->ses->server);
4192 goto out;
4193 }
4194
4195 tcon = cifs_get_tcon(ses, vol_info);
4196 if (IS_ERR(tcon)) {
4197 cifs_put_smb_ses(ses);
4198 goto out;
4199 }
4200
4201 if (ses->capabilities & CAP_UNIX)
4202 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4203out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004204 kfree(vol_info->username);
4205 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004206 kfree(vol_info);
4207
4208 return tcon;
4209}
4210
Steve French96daf2b2011-05-27 04:34:02 +00004211struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004212cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4213{
4214 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4215}
4216
4217static int
4218cifs_sb_tcon_pending_wait(void *unused)
4219{
4220 schedule();
4221 return signal_pending(current) ? -ERESTARTSYS : 0;
4222}
4223
Jeff Laytonb647c352010-10-28 11:16:44 -04004224/* find and return a tlink with given uid */
4225static struct tcon_link *
4226tlink_rb_search(struct rb_root *root, uid_t uid)
4227{
4228 struct rb_node *node = root->rb_node;
4229 struct tcon_link *tlink;
4230
4231 while (node) {
4232 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4233
4234 if (tlink->tl_uid > uid)
4235 node = node->rb_left;
4236 else if (tlink->tl_uid < uid)
4237 node = node->rb_right;
4238 else
4239 return tlink;
4240 }
4241 return NULL;
4242}
4243
4244/* insert a tcon_link into the tree */
4245static void
4246tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4247{
4248 struct rb_node **new = &(root->rb_node), *parent = NULL;
4249 struct tcon_link *tlink;
4250
4251 while (*new) {
4252 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4253 parent = *new;
4254
4255 if (tlink->tl_uid > new_tlink->tl_uid)
4256 new = &((*new)->rb_left);
4257 else
4258 new = &((*new)->rb_right);
4259 }
4260
4261 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4262 rb_insert_color(&new_tlink->tl_rbnode, root);
4263}
4264
Jeff Layton9d002df2010-10-06 19:51:11 -04004265/*
4266 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4267 * current task.
4268 *
4269 * If the superblock doesn't refer to a multiuser mount, then just return
4270 * the master tcon for the mount.
4271 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304272 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004273 * exists, then check to see if it's pending construction. If it is then wait
4274 * for construction to complete. Once it's no longer pending, check to see if
4275 * it failed and either return an error or retry construction, depending on
4276 * the timeout.
4277 *
4278 * If one doesn't exist then insert a new tcon_link struct into the tree and
4279 * try to construct a new one.
4280 */
4281struct tcon_link *
4282cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4283{
4284 int ret;
Jeff Laytonb647c352010-10-28 11:16:44 -04004285 uid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004286 struct tcon_link *tlink, *newtlink;
4287
4288 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4289 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4290
4291 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004292 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004293 if (tlink)
4294 cifs_get_tlink(tlink);
4295 spin_unlock(&cifs_sb->tlink_tree_lock);
4296
4297 if (tlink == NULL) {
4298 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4299 if (newtlink == NULL)
4300 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004301 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004302 newtlink->tl_tcon = ERR_PTR(-EACCES);
4303 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4304 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4305 cifs_get_tlink(newtlink);
4306
Jeff Layton9d002df2010-10-06 19:51:11 -04004307 spin_lock(&cifs_sb->tlink_tree_lock);
4308 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004309 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004310 if (tlink) {
4311 cifs_get_tlink(tlink);
4312 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004313 kfree(newtlink);
4314 goto wait_for_construction;
4315 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004316 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004317 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4318 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004319 } else {
4320wait_for_construction:
4321 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4322 cifs_sb_tcon_pending_wait,
4323 TASK_INTERRUPTIBLE);
4324 if (ret) {
4325 cifs_put_tlink(tlink);
4326 return ERR_PTR(ret);
4327 }
4328
4329 /* if it's good, return it */
4330 if (!IS_ERR(tlink->tl_tcon))
4331 return tlink;
4332
4333 /* return error if we tried this already recently */
4334 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4335 cifs_put_tlink(tlink);
4336 return ERR_PTR(-EACCES);
4337 }
4338
4339 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4340 goto wait_for_construction;
4341 }
4342
4343 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4344 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4345 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4346
4347 if (IS_ERR(tlink->tl_tcon)) {
4348 cifs_put_tlink(tlink);
4349 return ERR_PTR(-EACCES);
4350 }
4351
4352 return tlink;
4353}
Jeff Layton2de970f2010-10-06 19:51:12 -04004354
4355/*
4356 * periodic workqueue job that scans tcon_tree for a superblock and closes
4357 * out tcons.
4358 */
4359static void
4360cifs_prune_tlinks(struct work_struct *work)
4361{
4362 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4363 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004364 struct rb_root *root = &cifs_sb->tlink_tree;
4365 struct rb_node *node = rb_first(root);
4366 struct rb_node *tmp;
4367 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004368
Jeff Laytonb647c352010-10-28 11:16:44 -04004369 /*
4370 * Because we drop the spinlock in the loop in order to put the tlink
4371 * it's not guarded against removal of links from the tree. The only
4372 * places that remove entries from the tree are this function and
4373 * umounts. Because this function is non-reentrant and is canceled
4374 * before umount can proceed, this is safe.
4375 */
4376 spin_lock(&cifs_sb->tlink_tree_lock);
4377 node = rb_first(root);
4378 while (node != NULL) {
4379 tmp = node;
4380 node = rb_next(tmp);
4381 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4382
4383 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4384 atomic_read(&tlink->tl_count) != 0 ||
4385 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4386 continue;
4387
4388 cifs_get_tlink(tlink);
4389 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4390 rb_erase(tmp, root);
4391
Jeff Layton2de970f2010-10-06 19:51:12 -04004392 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004393 cifs_put_tlink(tlink);
4394 spin_lock(&cifs_sb->tlink_tree_lock);
4395 }
4396 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004397
Jeff Laytonda472fc2012-03-23 14:40:53 -04004398 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004399 TLINK_IDLE_EXPIRE);
4400}