blob: c49d49438c52ce677ca2cd67d3863afc5c694300 [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;
Jeff Layton296838b2012-05-16 07:53:01 -04001247 bool cache_specified = false;
1248 static bool cache_warned = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
1250 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001251 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001252 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
Jeff Layton88463992010-11-22 15:31:03 -05001254 /*
1255 * does not have to be perfect mapping since field is
1256 * informational, only used for servers that do not support
1257 * port 445 and it can be overridden at mount time
1258 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001259 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1260 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001261 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1262
Jeff Layton1397f2e2011-01-07 11:30:28 -05001263 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001264 /* null target name indicates to use *SMBSERVR default called name
1265 if we end up sending RFC1001 session initialize */
1266 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001267 vol->cred_uid = current_uid();
1268 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001269 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001270
1271 /* default to only allowing write access to owner of the mount */
1272 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001275 /* default is always to request posix paths. */
1276 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001277 /* default to using server inode numbers where available */
1278 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001279
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301280 vol->actimeo = CIFS_DEF_ACTIMEO;
1281
Sean Finneyb9468452011-04-11 13:19:32 +00001282 if (!mountdata)
1283 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Sean Finneyb9468452011-04-11 13:19:32 +00001285 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1286 if (!mountdata_copy)
1287 goto cifs_parse_mount_err;
1288
1289 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001290 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001291
Steve French50c2f752007-07-13 00:33:32 +00001292 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001293 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 separator[0] = options[4];
1295 options += 5;
1296 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001297 cFYI(1, "Null separator not allowed");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 }
1299 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001300 vol->backupuid_specified = false; /* no backup intent for a user */
1301 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001302
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001304 substring_t args[MAX_OPT_ARGS];
1305 unsigned long option;
1306 int token;
1307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (!*data)
1309 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001311 token = match_token(data, cifs_mount_option_tokens, args);
1312
1313 switch (token) {
1314
1315 /* Ingnore the following */
1316 case Opt_ignore:
1317 break;
1318
1319 /* Boolean values */
1320 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001322 break;
1323 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001325 break;
1326 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001327 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001328 break;
1329 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001330 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001331 break;
1332 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001333 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001334 break;
1335 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001336 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001337 break;
1338 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001340 break;
1341 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001343 break;
1344 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001346 break;
1347 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001349 break;
1350 case Opt_mapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001351 vol->remap = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001352 break;
1353 case Opt_nomapchars:
Steve French6a0b4822005-04-28 22:41:05 -07001354 vol->remap = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001355 break;
1356 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001357 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001358 break;
1359 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001360 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001361 break;
1362 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001363 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001364 break;
1365 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001366 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001367 break;
1368 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001369 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001370 break;
1371 case Opt_nounix:
Steve Frenchc18c8422007-07-18 23:21:09 +00001372 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001373 break;
1374 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001375 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001376 break;
1377 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001378 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001379 break;
1380 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001381 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001382 /*
1383 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001384 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001385 * local vfs will do advisory
1386 */
Steve French50c2f752007-07-13 00:33:32 +00001387 if (vol->file_mode ==
1388 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001389 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001390 break;
1391 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001392 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001393 break;
1394 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001396 break;
1397 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001399 break;
1400 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001401 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001402 break;
1403 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001404 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001405 break;
1406 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001408 break;
1409 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001411 break;
1412 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001414 break;
1415 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001417 break;
1418 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001419 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001420 break;
1421 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001422 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001423 break;
1424 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001426 break;
1427 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001429 break;
1430 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001431 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001432 break;
1433 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001434 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001435 break;
1436 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001437 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001438 break;
1439 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001441 break;
1442 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001444 break;
1445 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001446 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001447 break;
1448 case Opt_sign:
Steve French750d1152006-06-27 06:28:30 +00001449 vol->secFlg |= CIFSSEC_MUST_SIGN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001450 break;
1451 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001452 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001453 * is a per tree connection (mount) not a per socket
1454 * or per-smb connection option in the protocol
1455 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1456 */
Steve French95b1cb92008-05-15 16:44:38 +00001457 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001458 break;
1459 case Opt_direct:
Jeff Layton296838b2012-05-16 07:53:01 -04001460 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001461 vol->direct_io = true;
1462 vol->strict_io = false;
Jeff Layton09983b22012-05-16 07:53:00 -04001463 cERROR(1, "The \"directio\" option will be removed in "
1464 "3.7. Please switch to the \"cache=none\" "
1465 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001466 break;
1467 case Opt_strictcache:
Jeff Layton296838b2012-05-16 07:53:01 -04001468 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001469 vol->direct_io = false;
1470 vol->strict_io = true;
Jeff Layton09983b22012-05-16 07:53:00 -04001471 cERROR(1, "The \"strictcache\" option will be removed "
1472 "in 3.7. Please switch to the \"cache=strict\" "
1473 "option.");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001474 break;
1475 case Opt_noac:
Steve French50c2f752007-07-13 00:33:32 +00001476 printk(KERN_WARNING "CIFS: Mount option noac not "
1477 "supported. Instead set "
1478 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001479 break;
1480 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301481#ifndef CONFIG_CIFS_FSCACHE
Jeff Layton83fb0862011-06-08 07:35:24 -04001482 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301483 "kernel config option set");
Sean Finneyb9468452011-04-11 13:19:32 +00001484 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301485#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301486 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001487 break;
1488 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001489 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001490 break;
1491 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001492 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001493 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001494 case Opt_sloppy:
1495 sloppy = true;
1496 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001497
1498 /* Numeric Values */
1499 case Opt_backupuid:
1500 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001501 cERROR(1, "%s: Invalid backupuid value",
1502 __func__);
1503 goto cifs_parse_mount_err;
1504 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001505 vol->backupuid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001506 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001507 break;
1508 case Opt_backupgid:
1509 if (get_option_ul(args, &option)) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001510 cERROR(1, "%s: Invalid backupgid value",
1511 __func__);
1512 goto cifs_parse_mount_err;
1513 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001514 vol->backupgid = option;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001515 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001516 break;
1517 case Opt_uid:
1518 if (get_option_ul(args, &option)) {
1519 cERROR(1, "%s: Invalid uid value",
1520 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001521 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001523 vol->linux_uid = option;
1524 uid_specified = true;
1525 break;
1526 case Opt_cruid:
1527 if (get_option_ul(args, &option)) {
1528 cERROR(1, "%s: Invalid cruid value",
1529 __func__);
1530 goto cifs_parse_mount_err;
1531 }
1532 vol->cred_uid = option;
1533 break;
1534 case Opt_gid:
1535 if (get_option_ul(args, &option)) {
1536 cERROR(1, "%s: Invalid gid value",
1537 __func__);
1538 goto cifs_parse_mount_err;
1539 }
1540 vol->linux_gid = option;
1541 gid_specified = true;
1542 break;
1543 case Opt_file_mode:
1544 if (get_option_ul(args, &option)) {
1545 cERROR(1, "%s: Invalid file_mode value",
1546 __func__);
1547 goto cifs_parse_mount_err;
1548 }
1549 vol->file_mode = option;
1550 break;
1551 case Opt_dirmode:
1552 if (get_option_ul(args, &option)) {
1553 cERROR(1, "%s: Invalid dir_mode value",
1554 __func__);
1555 goto cifs_parse_mount_err;
1556 }
1557 vol->dir_mode = option;
1558 break;
1559 case Opt_port:
1560 if (get_option_ul(args, &option)) {
1561 cERROR(1, "%s: Invalid port value",
1562 __func__);
1563 goto cifs_parse_mount_err;
1564 }
1565 vol->port = option;
1566 break;
1567 case Opt_rsize:
1568 if (get_option_ul(args, &option)) {
1569 cERROR(1, "%s: Invalid rsize value",
1570 __func__);
1571 goto cifs_parse_mount_err;
1572 }
1573 vol->rsize = option;
1574 break;
1575 case Opt_wsize:
1576 if (get_option_ul(args, &option)) {
1577 cERROR(1, "%s: Invalid wsize value",
1578 __func__);
1579 goto cifs_parse_mount_err;
1580 }
1581 vol->wsize = option;
1582 break;
1583 case Opt_actimeo:
1584 if (get_option_ul(args, &option)) {
1585 cERROR(1, "%s: Invalid actimeo value",
1586 __func__);
1587 goto cifs_parse_mount_err;
1588 }
1589 vol->actimeo = HZ * option;
1590 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1591 cERROR(1, "CIFS: attribute cache"
1592 "timeout too large");
1593 goto cifs_parse_mount_err;
1594 }
1595 break;
1596
1597 /* String Arguments */
1598
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001599 case Opt_blank_user:
1600 /* null user, ie. anonymous authentication */
1601 vol->nullauth = 1;
1602 vol->username = NULL;
1603 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001604 case Opt_user:
1605 string = match_strdup(args);
1606 if (string == NULL)
1607 goto out_nomem;
1608
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001609 if (strnlen(string, MAX_USERNAME_SIZE) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001610 MAX_USERNAME_SIZE) {
1611 printk(KERN_WARNING "CIFS: username too long\n");
1612 goto cifs_parse_mount_err;
1613 }
1614 vol->username = kstrdup(string, GFP_KERNEL);
1615 if (!vol->username) {
1616 printk(KERN_WARNING "CIFS: no memory "
1617 "for username\n");
1618 goto cifs_parse_mount_err;
1619 }
1620 break;
1621 case Opt_blank_pass:
1622 vol->password = NULL;
1623 break;
1624 case Opt_pass:
1625 /* passwords have to be handled differently
1626 * to allow the character used for deliminator
1627 * to be passed within them
1628 */
1629
1630 /* Obtain the value string */
1631 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01001632 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001633
1634 /* Set tmp_end to end of the string */
1635 tmp_end = (char *) value + strlen(value);
1636
1637 /* Check if following character is the deliminator
1638 * If yes, we have encountered a double deliminator
1639 * reset the NULL character to the deliminator
1640 */
1641 if (tmp_end < end && tmp_end[1] == delim)
1642 tmp_end[0] = delim;
1643
1644 /* Keep iterating until we get to a single deliminator
1645 * OR the end
1646 */
1647 while ((tmp_end = strchr(tmp_end, delim)) != NULL &&
1648 (tmp_end[1] == delim)) {
1649 tmp_end = (char *) &tmp_end[2];
1650 }
1651
1652 /* Reset var options to point to next element */
1653 if (tmp_end) {
1654 tmp_end[0] = '\0';
1655 options = (char *) &tmp_end[1];
1656 } else
1657 /* Reached the end of the mount option string */
1658 options = end;
1659
1660 /* Now build new password string */
1661 temp_len = strlen(value);
1662 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
1663 if (vol->password == NULL) {
1664 printk(KERN_WARNING "CIFS: no memory "
1665 "for password\n");
1666 goto cifs_parse_mount_err;
1667 }
1668
1669 for (i = 0, j = 0; i < temp_len; i++, j++) {
1670 vol->password[j] = value[i];
1671 if ((value[i] == delim) &&
1672 value[i+1] == delim)
1673 /* skip the second deliminator */
1674 i++;
1675 }
1676 vol->password[j] = '\0';
1677 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001678 case Opt_blank_ip:
1679 vol->UNCip = NULL;
1680 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001681 case Opt_ip:
1682 string = match_strdup(args);
1683 if (string == NULL)
1684 goto out_nomem;
1685
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001686 if (strnlen(string, INET6_ADDRSTRLEN) >
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001687 INET6_ADDRSTRLEN) {
1688 printk(KERN_WARNING "CIFS: ip address "
1689 "too long\n");
1690 goto cifs_parse_mount_err;
1691 }
1692 vol->UNCip = kstrdup(string, GFP_KERNEL);
1693 if (!vol->UNCip) {
1694 printk(KERN_WARNING "CIFS: no memory "
1695 "for UNC IP\n");
1696 goto cifs_parse_mount_err;
1697 }
1698 break;
1699 case Opt_unc:
1700 string = match_strdup(args);
1701 if (string == NULL)
1702 goto out_nomem;
1703
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001704 temp_len = strnlen(string, 300);
1705 if (temp_len == 300) {
1706 printk(KERN_WARNING "CIFS: UNC name too long\n");
1707 goto cifs_parse_mount_err;
1708 }
1709
Sachin Prabhue4b41fb2012-04-04 01:58:56 +01001710 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1711 if (vol->UNC == NULL) {
1712 printk(KERN_WARNING "CIFS: no memory for UNC\n");
1713 goto cifs_parse_mount_err;
1714 }
1715 strcpy(vol->UNC, string);
1716
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001717 if (strncmp(string, "//", 2) == 0) {
1718 vol->UNC[0] = '\\';
1719 vol->UNC[1] = '\\';
1720 } else if (strncmp(string, "\\\\", 2) != 0) {
1721 printk(KERN_WARNING "CIFS: UNC Path does not "
1722 "begin with // or \\\\\n");
1723 goto cifs_parse_mount_err;
1724 }
1725
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001726 break;
1727 case Opt_domain:
1728 string = match_strdup(args);
1729 if (string == NULL)
1730 goto out_nomem;
1731
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001732 if (strnlen(string, 256) == 256) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001733 printk(KERN_WARNING "CIFS: domain name too"
1734 " long\n");
1735 goto cifs_parse_mount_err;
1736 }
1737
1738 vol->domainname = kstrdup(string, GFP_KERNEL);
1739 if (!vol->domainname) {
1740 printk(KERN_WARNING "CIFS: no memory "
1741 "for domainname\n");
1742 goto cifs_parse_mount_err;
1743 }
1744 cFYI(1, "Domain name set");
1745 break;
1746 case Opt_srcaddr:
1747 string = match_strdup(args);
1748 if (string == NULL)
1749 goto out_nomem;
1750
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001751 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001752 (struct sockaddr *)&vol->srcaddr,
1753 string, strlen(string))) {
1754 printk(KERN_WARNING "CIFS: Could not parse"
1755 " srcaddr: %s\n", string);
1756 goto cifs_parse_mount_err;
1757 }
1758 break;
1759 case Opt_prefixpath:
1760 string = match_strdup(args);
1761 if (string == NULL)
1762 goto out_nomem;
1763
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001764 temp_len = strnlen(string, 1024);
1765 if (string[0] != '/')
1766 temp_len++; /* missing leading slash */
1767 if (temp_len > 1024) {
1768 printk(KERN_WARNING "CIFS: prefix too long\n");
1769 goto cifs_parse_mount_err;
1770 }
1771
1772 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1773 if (vol->prepath == NULL) {
1774 printk(KERN_WARNING "CIFS: no memory "
1775 "for path prefix\n");
1776 goto cifs_parse_mount_err;
1777 }
1778
1779 if (string[0] != '/') {
1780 vol->prepath[0] = '/';
1781 strcpy(vol->prepath+1, string);
1782 } else
1783 strcpy(vol->prepath, string);
1784
1785 break;
1786 case Opt_iocharset:
1787 string = match_strdup(args);
1788 if (string == NULL)
1789 goto out_nomem;
1790
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01001791 if (strnlen(string, 1024) >= 65) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001792 printk(KERN_WARNING "CIFS: iocharset name "
1793 "too long.\n");
1794 goto cifs_parse_mount_err;
1795 }
1796
1797 if (strnicmp(string, "default", 7) != 0) {
1798 vol->iocharset = kstrdup(string,
1799 GFP_KERNEL);
1800 if (!vol->iocharset) {
1801 printk(KERN_WARNING "CIFS: no memory"
1802 "for charset\n");
1803 goto cifs_parse_mount_err;
1804 }
1805 }
1806 /* if iocharset not set then load_nls_default
1807 * is used by caller
1808 */
1809 cFYI(1, "iocharset set to %s", string);
1810 break;
1811 case Opt_sockopt:
1812 string = match_strdup(args);
1813 if (string == NULL)
1814 goto out_nomem;
1815
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001816 if (strnicmp(string, "TCP_NODELAY", 11) == 0)
1817 vol->sockopt_tcp_nodelay = 1;
1818 break;
1819 case Opt_netbiosname:
1820 string = match_strdup(args);
1821 if (string == NULL)
1822 goto out_nomem;
1823
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001824 memset(vol->source_rfc1001_name, 0x20,
1825 RFC1001_NAME_LEN);
1826 /*
1827 * FIXME: are there cases in which a comma can
1828 * be valid in workstation netbios name (and
1829 * need special handling)?
1830 */
1831 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1832 /* don't ucase netbiosname for user */
1833 if (string[i] == 0)
1834 break;
1835 vol->source_rfc1001_name[i] = string[i];
1836 }
1837 /* The string has 16th byte zero still from
1838 * set at top of the function
1839 */
1840 if (i == RFC1001_NAME_LEN && string[i] != 0)
1841 printk(KERN_WARNING "CIFS: netbiosname"
1842 " longer than 15 truncated.\n");
1843
1844 break;
1845 case Opt_servern:
1846 /* servernetbiosname specified override *SMBSERVER */
1847 string = match_strdup(args);
1848 if (string == NULL)
1849 goto out_nomem;
1850
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001851 /* last byte, type, is 0x20 for servr type */
1852 memset(vol->target_rfc1001_name, 0x20,
1853 RFC1001_NAME_LEN_WITH_NULL);
1854
1855 /* BB are there cases in which a comma can be
1856 valid in this workstation netbios name
1857 (and need special handling)? */
1858
1859 /* user or mount helper must uppercase the
1860 netbios name */
1861 for (i = 0; i < 15; i++) {
1862 if (string[i] == 0)
1863 break;
1864 vol->target_rfc1001_name[i] = string[i];
1865 }
1866 /* The string has 16th byte zero still from
1867 set at top of the function */
1868 if (i == RFC1001_NAME_LEN && string[i] != 0)
1869 printk(KERN_WARNING "CIFS: server net"
1870 "biosname longer than 15 truncated.\n");
1871 break;
1872 case Opt_ver:
1873 string = match_strdup(args);
1874 if (string == NULL)
1875 goto out_nomem;
1876
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001877 if (strnicmp(string, "cifs", 4) == 0 ||
1878 strnicmp(string, "1", 1) == 0) {
1879 /* This is the default */
1880 break;
1881 }
1882 /* For all other value, error */
1883 printk(KERN_WARNING "CIFS: Invalid version"
1884 " specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001885 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001886 case Opt_sec:
1887 string = match_strdup(args);
1888 if (string == NULL)
1889 goto out_nomem;
1890
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001891 if (cifs_parse_security_flavors(string, vol) != 0)
1892 goto cifs_parse_mount_err;
1893 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04001894 case Opt_cache:
Jeff Layton296838b2012-05-16 07:53:01 -04001895 cache_specified = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001896 string = match_strdup(args);
1897 if (string == NULL)
1898 goto out_nomem;
1899
1900 if (cifs_parse_cache_flavor(string, vol) != 0)
1901 goto cifs_parse_mount_err;
1902 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001903 default:
Jeff Laytond8162552012-03-23 14:40:56 -04001904 /*
1905 * An option we don't recognize. Save it off for later
1906 * if we haven't already found one
1907 */
1908 if (!invalid)
1909 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001910 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001912 /* Free up any allocated string */
1913 kfree(string);
1914 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001916
Jeff Laytond8162552012-03-23 14:40:56 -04001917 if (!sloppy && invalid) {
1918 printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid);
1919 goto cifs_parse_mount_err;
1920 }
1921
Jeff Layton8a8798a2012-01-17 16:09:15 -05001922#ifndef CONFIG_KEYS
1923 /* Muliuser mounts require CONFIG_KEYS support */
1924 if (vol->multiuser) {
1925 cERROR(1, "Multiuser mounts require kernels with "
1926 "CONFIG_KEYS enabled.");
Sean Finneyb9468452011-04-11 13:19:32 +00001927 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001928 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05001929#endif
Jeff Layton0eb8a132010-10-06 19:51:12 -04001930
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001931 if (vol->UNCip == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 vol->UNCip = &vol->UNC[2];
1933
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001934 if (uid_specified)
1935 vol->override_uid = override_uid;
1936 else if (override_uid == 1)
1937 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1938 "specified with no uid= option.\n");
1939
1940 if (gid_specified)
1941 vol->override_gid = override_gid;
1942 else if (override_gid == 1)
1943 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1944 "specified with no gid= option.\n");
1945
Jeff Layton296838b2012-05-16 07:53:01 -04001946 /* FIXME: remove this block in 3.7 */
1947 if (!cache_specified && !cache_warned) {
1948 cache_warned = true;
1949 printk(KERN_NOTICE "CIFS: no cache= option specified, using "
1950 "\"cache=loose\". This default will change "
1951 "to \"cache=strict\" in 3.7.\n");
1952 }
1953
Sean Finneyb9468452011-04-11 13:19:32 +00001954 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001956
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001957out_nomem:
1958 printk(KERN_WARNING "Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001959cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001960 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00001961 kfree(mountdata_copy);
1962 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963}
1964
Ben Greear3eb9a882010-09-01 17:06:02 -07001965/** Returns true if srcaddr isn't specified and rhs isn't
1966 * specified, or if srcaddr is specified and
1967 * matches the IP address of the rhs argument.
1968 */
Jeff Layton45151482010-07-06 20:43:02 -04001969static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001970srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1971{
1972 switch (srcaddr->sa_family) {
1973 case AF_UNSPEC:
1974 return (rhs->sa_family == AF_UNSPEC);
1975 case AF_INET: {
1976 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1977 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1978 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1979 }
1980 case AF_INET6: {
1981 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
1982 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
1983 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1984 }
1985 default:
1986 WARN_ON(1);
1987 return false; /* don't expect to be here */
1988 }
1989}
1990
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001991/*
1992 * If no port is specified in addr structure, we try to match with 445 port
1993 * and if it fails - with 139 ports. It should be called only if address
1994 * families of server and addr are equal.
1995 */
1996static bool
1997match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1998{
Steve French6da97912011-03-13 18:55:55 +00001999 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002000
2001 switch (addr->sa_family) {
2002 case AF_INET:
2003 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2004 port = ((struct sockaddr_in *) addr)->sin_port;
2005 break;
2006 case AF_INET6:
2007 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2008 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2009 break;
2010 default:
2011 WARN_ON(1);
2012 return false;
2013 }
2014
2015 if (!port) {
2016 port = htons(CIFS_PORT);
2017 if (port == *sport)
2018 return true;
2019
2020 port = htons(RFC1001_PORT);
2021 }
2022
2023 return port == *sport;
2024}
Ben Greear3eb9a882010-09-01 17:06:02 -07002025
2026static bool
2027match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2028 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029{
Jeff Layton45151482010-07-06 20:43:02 -04002030 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002031 case AF_INET: {
2032 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2033 struct sockaddr_in *srv_addr4 =
2034 (struct sockaddr_in *)&server->dstaddr;
2035
2036 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002037 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002038 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002039 }
2040 case AF_INET6: {
2041 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2042 struct sockaddr_in6 *srv_addr6 =
2043 (struct sockaddr_in6 *)&server->dstaddr;
2044
Jeff Layton45151482010-07-06 20:43:02 -04002045 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002046 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002047 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002048 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002049 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002050 break;
2051 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002052 default:
2053 WARN_ON(1);
2054 return false; /* don't expect to be here */
2055 }
Jeff Layton45151482010-07-06 20:43:02 -04002056
Ben Greear3eb9a882010-09-01 17:06:02 -07002057 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2058 return false;
2059
Jeff Layton45151482010-07-06 20:43:02 -04002060 return true;
2061}
2062
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002063static bool
2064match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2065{
2066 unsigned int secFlags;
2067
2068 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
2069 secFlags = vol->secFlg;
2070 else
2071 secFlags = global_secflags | vol->secFlg;
2072
2073 switch (server->secType) {
2074 case LANMAN:
2075 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
2076 return false;
2077 break;
2078 case NTLMv2:
2079 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
2080 return false;
2081 break;
2082 case NTLM:
2083 if (!(secFlags & CIFSSEC_MAY_NTLM))
2084 return false;
2085 break;
2086 case Kerberos:
2087 if (!(secFlags & CIFSSEC_MAY_KRB5))
2088 return false;
2089 break;
2090 case RawNTLMSSP:
2091 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
2092 return false;
2093 break;
2094 default:
2095 /* shouldn't happen */
2096 return false;
2097 }
2098
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002099 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002100 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00002101 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002102 return false;
2103 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00002104 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002105 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
2106 return false;
2107
2108 return true;
2109}
2110
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002111static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
2112 struct smb_vol *vol)
2113{
2114 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2115 return 0;
2116
2117 if (!match_address(server, addr,
2118 (struct sockaddr *)&vol->srcaddr))
2119 return 0;
2120
2121 if (!match_port(server, addr))
2122 return 0;
2123
2124 if (!match_security(server, vol))
2125 return 0;
2126
2127 return 1;
2128}
2129
Jeff Layton45151482010-07-06 20:43:02 -04002130static struct TCP_Server_Info *
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002131cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002132{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002133 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302135 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002136 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002137 if (!match_server(server, addr, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002138 continue;
2139
Jeff Laytone7ddee92008-11-14 13:44:38 -05002140 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302141 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002142 cFYI(1, "Existing tcp session with server found");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002143 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302145 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 return NULL;
2147}
2148
Jeff Layton14fbf502008-11-14 13:53:46 -05002149static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05002150cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002152 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302154 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002155 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302156 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002157 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002159
Rob Landleyf1d0c992011-01-22 15:44:05 -06002160 put_net(cifs_net_ns(server));
2161
Jeff Laytone7ddee92008-11-14 13:44:38 -05002162 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302163 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002164
Jeff Laytonc74093b2011-01-11 07:24:23 -05002165 cancel_delayed_work_sync(&server->echo);
2166
Jeff Laytone7ddee92008-11-14 13:44:38 -05002167 spin_lock(&GlobalMid_Lock);
2168 server->tcpStatus = CifsExiting;
2169 spin_unlock(&GlobalMid_Lock);
2170
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002171 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302172 cifs_fscache_release_client_cookie(server);
2173
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002174 kfree(server->session_key.response);
2175 server->session_key.response = NULL;
2176 server->session_key.len = 0;
2177
Jeff Laytone7ddee92008-11-14 13:44:38 -05002178 task = xchg(&server->tsk, NULL);
2179 if (task)
2180 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181}
2182
Jeff Layton63c038c2008-12-01 18:41:46 -05002183static struct TCP_Server_Info *
2184cifs_get_tcp_session(struct smb_vol *volume_info)
2185{
2186 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002187 struct sockaddr_storage addr;
Jeff Layton63c038c2008-12-01 18:41:46 -05002188 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2189 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2190 int rc;
2191
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002192 memset(&addr, 0, sizeof(struct sockaddr_storage));
Jeff Layton63c038c2008-12-01 18:41:46 -05002193
Joe Perchesb6b38f72010-04-21 03:50:45 +00002194 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002195
Jeff Layton63c038c2008-12-01 18:41:46 -05002196 if (volume_info->UNCip && volume_info->UNC) {
Jeff Layton50d97162010-07-06 20:43:01 -04002197 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2198 volume_info->UNCip,
David Howells67b76262010-07-22 18:33:01 +01002199 strlen(volume_info->UNCip),
Jeff Layton50d97162010-07-06 20:43:01 -04002200 volume_info->port);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04002201 if (!rc) {
Jeff Layton63c038c2008-12-01 18:41:46 -05002202 /* we failed translating address */
2203 rc = -EINVAL;
2204 goto out_err;
2205 }
Jeff Layton63c038c2008-12-01 18:41:46 -05002206 } else if (volume_info->UNCip) {
2207 /* BB using ip addr as tcp_ses name to connect to the
2208 DFS root below */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002209 cERROR(1, "Connecting to DFS root not implemented yet");
Jeff Layton63c038c2008-12-01 18:41:46 -05002210 rc = -EINVAL;
2211 goto out_err;
2212 } else /* which tcp_sess DFS root would we conect to */ {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002213 cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
2214 "unc=//192.168.1.100/public) specified");
Jeff Layton63c038c2008-12-01 18:41:46 -05002215 rc = -EINVAL;
2216 goto out_err;
2217 }
2218
2219 /* see if we already have a matching tcp_ses */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002220 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002221 if (tcp_ses)
2222 return tcp_ses;
2223
2224 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2225 if (!tcp_ses) {
2226 rc = -ENOMEM;
2227 goto out_err;
2228 }
2229
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002230 rc = cifs_crypto_shash_allocate(tcp_ses);
2231 if (rc) {
2232 cERROR(1, "could not setup hash structures rc %d", rc);
2233 goto out_err;
2234 }
2235
Rob Landleyf1d0c992011-01-22 15:44:05 -06002236 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002237 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2238 if (IS_ERR(tcp_ses->hostname)) {
2239 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002240 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002241 }
2242
2243 tcp_ses->noblocksnd = volume_info->noblocksnd;
2244 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002245 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002246 tcp_ses->in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002247 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002248 init_waitqueue_head(&tcp_ses->response_q);
2249 init_waitqueue_head(&tcp_ses->request_q);
2250 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2251 mutex_init(&tcp_ses->srv_mutex);
2252 memcpy(tcp_ses->workstation_RFC1001_name,
2253 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2254 memcpy(tcp_ses->server_RFC1001_name,
2255 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002256 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002257 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00002258 tcp_ses->lstrp = jiffies;
Jeff Layton58fa0152012-05-01 17:41:16 -04002259 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002260 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2261 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002262 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton63c038c2008-12-01 18:41:46 -05002263
2264 /*
2265 * at this point we are the only ones with the pointer
2266 * to the struct since the kernel thread not created yet
2267 * no need to spinlock this init of tcpStatus or srv_count
2268 */
2269 tcp_ses->tcpStatus = CifsNew;
Ben Greear3eb9a882010-09-01 17:06:02 -07002270 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2271 sizeof(tcp_ses->srcaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05002272 ++tcp_ses->srv_count;
2273
Jeff Laytona9ac49d2009-01-22 14:43:21 -05002274 if (addr.ss_family == AF_INET6) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002275 cFYI(1, "attempting ipv6 connect");
Jeff Layton63c038c2008-12-01 18:41:46 -05002276 /* BB should we allow ipv6 on port 139? */
2277 /* other OS never observed in Wild doing 139 with v6 */
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002278 memcpy(&tcp_ses->dstaddr, sin_server6,
2279 sizeof(struct sockaddr_in6));
2280 } else
2281 memcpy(&tcp_ses->dstaddr, sin_server,
2282 sizeof(struct sockaddr_in));
2283
2284 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002285 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002286 cERROR(1, "Error connecting to socket. Aborting operation");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002287 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002288 }
2289
2290 /*
2291 * since we're in a cifs function already, we know that
2292 * this will succeed. No need for try_module_get().
2293 */
2294 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002295 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002296 tcp_ses, "cifsd");
2297 if (IS_ERR(tcp_ses->tsk)) {
2298 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002299 cERROR(1, "error %d create cifsd thread", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002300 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002301 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002302 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00002303 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002304
2305 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302306 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002307 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302308 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002309
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302310 cifs_fscache_get_client_cookie(tcp_ses);
2311
Jeff Laytonc74093b2011-01-11 07:24:23 -05002312 /* queue echo request delayed work */
Jeff Laytonda472fc2012-03-23 14:40:53 -04002313 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002314
Jeff Layton63c038c2008-12-01 18:41:46 -05002315 return tcp_ses;
2316
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002317out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002318 cifs_crypto_shash_release(tcp_ses);
2319
Rob Landleyf1d0c992011-01-22 15:44:05 -06002320 put_net(cifs_net_ns(tcp_ses));
2321
Jeff Layton63c038c2008-12-01 18:41:46 -05002322out_err:
2323 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002324 if (!IS_ERR(tcp_ses->hostname))
2325 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002326 if (tcp_ses->ssocket)
2327 sock_release(tcp_ses->ssocket);
2328 kfree(tcp_ses);
2329 }
2330 return ERR_PTR(rc);
2331}
2332
Steve French96daf2b2011-05-27 04:34:02 +00002333static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002334{
2335 switch (ses->server->secType) {
2336 case Kerberos:
2337 if (vol->cred_uid != ses->cred_uid)
2338 return 0;
2339 break;
2340 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002341 /* NULL username means anonymous session */
2342 if (ses->user_name == NULL) {
2343 if (!vol->nullauth)
2344 return 0;
2345 break;
2346 }
2347
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002348 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002349 if (strncmp(ses->user_name,
2350 vol->username ? vol->username : "",
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002351 MAX_USERNAME_SIZE))
2352 return 0;
2353 if (strlen(vol->username) != 0 &&
2354 ses->password != NULL &&
2355 strncmp(ses->password,
2356 vol->password ? vol->password : "",
2357 MAX_PASSWORD_SIZE))
2358 return 0;
2359 }
2360 return 1;
2361}
2362
Steve French96daf2b2011-05-27 04:34:02 +00002363static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002364cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
Steve French96daf2b2011-05-27 04:34:02 +00002366 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302368 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002369 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002370 if (!match_session(ses, vol))
2371 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002372 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302373 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002374 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302376 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 return NULL;
2378}
2379
Jeff Layton14fbf502008-11-14 13:53:46 -05002380static void
Steve French96daf2b2011-05-27 04:34:02 +00002381cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002382{
2383 int xid;
2384 struct TCP_Server_Info *server = ses->server;
2385
Jeff Layton36988c72010-04-24 07:57:43 -04002386 cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302387 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002388 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302389 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002390 return;
2391 }
2392
2393 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302394 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002395
2396 if (ses->status == CifsGood) {
2397 xid = GetXid();
2398 CIFSSMBLogoff(xid, ses);
2399 _FreeXid(xid);
2400 }
2401 sesInfoFree(ses);
2402 cifs_put_tcp_session(server);
2403}
2404
Jeff Layton8a8798a2012-01-17 16:09:15 -05002405#ifdef CONFIG_KEYS
2406
2407/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
2408#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
2409
2410/* Populate username and pw fields from keyring if possible */
2411static int
2412cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
2413{
2414 int rc = 0;
2415 char *desc, *delim, *payload;
2416 ssize_t len;
2417 struct key *key;
2418 struct TCP_Server_Info *server = ses->server;
2419 struct sockaddr_in *sa;
2420 struct sockaddr_in6 *sa6;
2421 struct user_key_payload *upayload;
2422
2423 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
2424 if (!desc)
2425 return -ENOMEM;
2426
2427 /* try to find an address key first */
2428 switch (server->dstaddr.ss_family) {
2429 case AF_INET:
2430 sa = (struct sockaddr_in *)&server->dstaddr;
2431 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
2432 break;
2433 case AF_INET6:
2434 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
2435 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
2436 break;
2437 default:
2438 cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
2439 rc = -EINVAL;
2440 goto out_err;
2441 }
2442
2443 cFYI(1, "%s: desc=%s", __func__, desc);
2444 key = request_key(&key_type_logon, desc, "");
2445 if (IS_ERR(key)) {
2446 if (!ses->domainName) {
2447 cFYI(1, "domainName is NULL");
2448 rc = PTR_ERR(key);
2449 goto out_err;
2450 }
2451
2452 /* didn't work, try to find a domain key */
2453 sprintf(desc, "cifs:d:%s", ses->domainName);
2454 cFYI(1, "%s: desc=%s", __func__, desc);
2455 key = request_key(&key_type_logon, desc, "");
2456 if (IS_ERR(key)) {
2457 rc = PTR_ERR(key);
2458 goto out_err;
2459 }
2460 }
2461
2462 down_read(&key->sem);
2463 upayload = key->payload.data;
2464 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05002465 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05002466 goto out_key_put;
2467 }
2468
2469 /* find first : in payload */
2470 payload = (char *)upayload->data;
2471 delim = strnchr(payload, upayload->datalen, ':');
2472 cFYI(1, "payload=%s", payload);
2473 if (!delim) {
2474 cFYI(1, "Unable to find ':' in payload (datalen=%d)",
2475 upayload->datalen);
2476 rc = -EINVAL;
2477 goto out_key_put;
2478 }
2479
2480 len = delim - payload;
2481 if (len > MAX_USERNAME_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002482 cFYI(1, "Bad value from username search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002483 rc = -EINVAL;
2484 goto out_key_put;
2485 }
2486
2487 vol->username = kstrndup(payload, len, GFP_KERNEL);
2488 if (!vol->username) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002489 cFYI(1, "Unable to allocate %zd bytes for username", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002490 rc = -ENOMEM;
2491 goto out_key_put;
2492 }
2493 cFYI(1, "%s: username=%s", __func__, vol->username);
2494
2495 len = key->datalen - (len + 1);
2496 if (len > MAX_PASSWORD_SIZE || len <= 0) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002497 cFYI(1, "Bad len for password search (len=%zd)", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002498 rc = -EINVAL;
2499 kfree(vol->username);
2500 vol->username = NULL;
2501 goto out_key_put;
2502 }
2503
2504 ++delim;
2505 vol->password = kstrndup(delim, len, GFP_KERNEL);
2506 if (!vol->password) {
Randy Dunlap000f9bb2012-01-30 19:50:01 -08002507 cFYI(1, "Unable to allocate %zd bytes for password", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05002508 rc = -ENOMEM;
2509 kfree(vol->username);
2510 vol->username = NULL;
2511 goto out_key_put;
2512 }
2513
2514out_key_put:
2515 up_read(&key->sem);
2516 key_put(key);
2517out_err:
2518 kfree(desc);
2519 cFYI(1, "%s: returning %d", __func__, rc);
2520 return rc;
2521}
2522#else /* ! CONFIG_KEYS */
2523static inline int
2524cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
2525 struct cifs_ses *ses __attribute__((unused)))
2526{
2527 return -ENOSYS;
2528}
2529#endif /* CONFIG_KEYS */
2530
Steve Frenchd9b94202011-04-12 01:24:57 +00002531static bool warned_on_ntlm; /* globals init to false automatically */
2532
Steve French96daf2b2011-05-27 04:34:02 +00002533static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002534cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2535{
2536 int rc = -ENOMEM, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002537 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002538 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2539 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002540
2541 xid = GetXid();
2542
Jeff Layton4ff67b72010-07-06 20:43:02 -04002543 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002544 if (ses) {
2545 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
2546
Jeff Layton36988c72010-04-24 07:57:43 -04002547 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002548 rc = cifs_negotiate_protocol(xid, ses);
2549 if (rc) {
2550 mutex_unlock(&ses->session_mutex);
2551 /* problem -- put our ses reference */
2552 cifs_put_smb_ses(ses);
2553 FreeXid(xid);
2554 return ERR_PTR(rc);
2555 }
Jeff Layton36988c72010-04-24 07:57:43 -04002556 if (ses->need_reconnect) {
2557 cFYI(1, "Session needs reconnect");
2558 rc = cifs_setup_session(xid, ses,
2559 volume_info->local_nls);
2560 if (rc) {
2561 mutex_unlock(&ses->session_mutex);
2562 /* problem -- put our reference */
2563 cifs_put_smb_ses(ses);
2564 FreeXid(xid);
2565 return ERR_PTR(rc);
2566 }
2567 }
2568 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002569
2570 /* existing SMB ses has a server reference already */
2571 cifs_put_tcp_session(server);
Jeff Layton36988c72010-04-24 07:57:43 -04002572 FreeXid(xid);
2573 return ses;
2574 }
2575
2576 cFYI(1, "Existing smb sess not found");
2577 ses = sesInfoAlloc();
2578 if (ses == NULL)
2579 goto get_ses_fail;
2580
2581 /* new SMB session uses our server ref */
2582 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002583 if (server->dstaddr.ss_family == AF_INET6)
2584 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002585 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002586 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002587
Steve French8727c8a2011-02-25 01:11:56 -06002588 if (volume_info->username) {
2589 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2590 if (!ses->user_name)
2591 goto get_ses_fail;
2592 }
Jeff Layton36988c72010-04-24 07:57:43 -04002593
2594 /* volume_info->password freed at unmount */
2595 if (volume_info->password) {
2596 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2597 if (!ses->password)
2598 goto get_ses_fail;
2599 }
2600 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002601 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2602 if (!ses->domainName)
2603 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002604 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002605 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002606 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002607
2608 /* ntlmv2 is much stronger than ntlm security, and has been broadly
2609 supported for many years, time to update default security mechanism */
2610 if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
2611 warned_on_ntlm = true;
2612 cERROR(1, "default security mechanism requested. The default "
2613 "security mechanism will be upgraded from ntlm to "
Steve French225de112012-01-03 23:08:24 -06002614 "ntlmv2 in kernel release 3.3");
Steve Frenchd9b94202011-04-12 01:24:57 +00002615 }
Jeff Layton36988c72010-04-24 07:57:43 -04002616 ses->overrideSecFlg = volume_info->secFlg;
2617
2618 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002619 rc = cifs_negotiate_protocol(xid, ses);
2620 if (!rc)
2621 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002622 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002623 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002624 goto get_ses_fail;
2625
2626 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302627 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002628 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302629 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002630
2631 FreeXid(xid);
2632 return ses;
2633
2634get_ses_fail:
2635 sesInfoFree(ses);
2636 FreeXid(xid);
2637 return ERR_PTR(rc);
2638}
2639
Steve French96daf2b2011-05-27 04:34:02 +00002640static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002641{
2642 if (tcon->tidStatus == CifsExiting)
2643 return 0;
2644 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2645 return 0;
2646 return 1;
2647}
2648
Steve French96daf2b2011-05-27 04:34:02 +00002649static struct cifs_tcon *
2650cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651{
2652 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002653 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302655 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002656 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002657 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002658 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002659 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002660 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302661 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 return tcon;
2663 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302664 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 return NULL;
2666}
2667
Jeff Laytonf1987b42008-11-15 11:12:47 -05002668static void
Steve French96daf2b2011-05-27 04:34:02 +00002669cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002670{
2671 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002672 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002673
Jeff Laytond00c28d2010-04-24 07:57:44 -04002674 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302675 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002676 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302677 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002678 return;
2679 }
2680
2681 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302682 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002683
2684 xid = GetXid();
2685 CIFSSMBTDis(xid, tcon);
2686 _FreeXid(xid);
2687
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302688 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002689 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002690 cifs_put_smb_ses(ses);
2691}
2692
Steve French96daf2b2011-05-27 04:34:02 +00002693static struct cifs_tcon *
2694cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002695{
2696 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002697 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002698
2699 tcon = cifs_find_tcon(ses, volume_info->UNC);
2700 if (tcon) {
2701 cFYI(1, "Found match on UNC path");
2702 /* existing tcon already has a reference */
2703 cifs_put_smb_ses(ses);
2704 if (tcon->seal != volume_info->seal)
2705 cERROR(1, "transport encryption setting "
2706 "conflicts with existing tid");
2707 return tcon;
2708 }
2709
2710 tcon = tconInfoAlloc();
2711 if (tcon == NULL) {
2712 rc = -ENOMEM;
2713 goto out_fail;
2714 }
2715
2716 tcon->ses = ses;
2717 if (volume_info->password) {
2718 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2719 if (!tcon->password) {
2720 rc = -ENOMEM;
2721 goto out_fail;
2722 }
2723 }
2724
2725 if (strchr(volume_info->UNC + 3, '\\') == NULL
2726 && strchr(volume_info->UNC + 3, '/') == NULL) {
2727 cERROR(1, "Missing share name");
2728 rc = -ENODEV;
2729 goto out_fail;
2730 }
2731
2732 /* BB Do we need to wrap session_mutex around
2733 * this TCon call and Unix SetFS as
2734 * we do on SessSetup and reconnect? */
2735 xid = GetXid();
2736 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
2737 FreeXid(xid);
2738 cFYI(1, "CIFS Tcon rc = %d", rc);
2739 if (rc)
2740 goto out_fail;
2741
2742 if (volume_info->nodfs) {
2743 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2744 cFYI(1, "DFS disabled (%d)", tcon->Flags);
2745 }
2746 tcon->seal = volume_info->seal;
2747 /* we can have only one retry value for a connection
2748 to a share so for resources mounted more than once
2749 to the same server share the last value passed in
2750 for the retry flag is used */
2751 tcon->retry = volume_info->retry;
2752 tcon->nocase = volume_info->nocase;
2753 tcon->local_lease = volume_info->local_lease;
2754
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302755 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002756 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302757 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002758
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302759 cifs_fscache_get_super_cookie(tcon);
2760
Jeff Laytond00c28d2010-04-24 07:57:44 -04002761 return tcon;
2762
2763out_fail:
2764 tconInfoFree(tcon);
2765 return ERR_PTR(rc);
2766}
2767
Jeff Layton9d002df2010-10-06 19:51:11 -04002768void
2769cifs_put_tlink(struct tcon_link *tlink)
2770{
2771 if (!tlink || IS_ERR(tlink))
2772 return;
2773
2774 if (!atomic_dec_and_test(&tlink->tl_count) ||
2775 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2776 tlink->tl_time = jiffies;
2777 return;
2778 }
2779
2780 if (!IS_ERR(tlink_tcon(tlink)))
2781 cifs_put_tcon(tlink_tcon(tlink));
2782 kfree(tlink);
2783 return;
2784}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002785
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002786static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002787cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2788{
2789 return cifs_sb->master_tlink;
2790}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002791
2792static int
2793compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2794{
2795 struct cifs_sb_info *old = CIFS_SB(sb);
2796 struct cifs_sb_info *new = mnt_data->cifs_sb;
2797
2798 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2799 return 0;
2800
2801 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2802 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2803 return 0;
2804
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002805 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002806 * We want to share sb only if we don't specify an r/wsize or
2807 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002808 */
2809 if (new->wsize && new->wsize < old->wsize)
2810 return 0;
2811
Jeff Layton5eba8ab2011-10-19 15:30:26 -04002812 if (new->rsize && new->rsize < old->rsize)
2813 return 0;
2814
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002815 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2816 return 0;
2817
2818 if (old->mnt_file_mode != new->mnt_file_mode ||
2819 old->mnt_dir_mode != new->mnt_dir_mode)
2820 return 0;
2821
2822 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2823 return 0;
2824
2825 if (old->actimeo != new->actimeo)
2826 return 0;
2827
2828 return 1;
2829}
2830
2831int
2832cifs_match_super(struct super_block *sb, void *data)
2833{
2834 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2835 struct smb_vol *volume_info;
2836 struct cifs_sb_info *cifs_sb;
2837 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002838 struct cifs_ses *ses;
2839 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002840 struct tcon_link *tlink;
2841 struct sockaddr_storage addr;
2842 int rc = 0;
2843
2844 memset(&addr, 0, sizeof(struct sockaddr_storage));
2845
2846 spin_lock(&cifs_tcp_ses_lock);
2847 cifs_sb = CIFS_SB(sb);
2848 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2849 if (IS_ERR(tlink)) {
2850 spin_unlock(&cifs_tcp_ses_lock);
2851 return rc;
2852 }
2853 tcon = tlink_tcon(tlink);
2854 ses = tcon->ses;
2855 tcp_srv = ses->server;
2856
2857 volume_info = mnt_data->vol;
2858
2859 if (!volume_info->UNCip || !volume_info->UNC)
2860 goto out;
2861
2862 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2863 volume_info->UNCip,
2864 strlen(volume_info->UNCip),
2865 volume_info->port);
2866 if (!rc)
2867 goto out;
2868
2869 if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
2870 !match_session(ses, volume_info) ||
2871 !match_tcon(tcon, volume_info->UNC)) {
2872 rc = 0;
2873 goto out;
2874 }
2875
2876 rc = compare_mount_options(sb, mnt_data);
2877out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002878 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002879 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002880 return rc;
2881}
2882
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883int
Steve French96daf2b2011-05-27 04:34:02 +00002884get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
Steve French50c2f752007-07-13 00:33:32 +00002885 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
Steve French366781c2008-01-25 10:12:41 +00002886 struct dfs_info3_param **preferrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887{
2888 char *temp_unc;
2889 int rc = 0;
2890
2891 *pnum_referrals = 0;
Steve French366781c2008-01-25 10:12:41 +00002892 *preferrals = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893
2894 if (pSesInfo->ipc_tid == 0) {
2895 temp_unc = kmalloc(2 /* for slashes */ +
Steve French50c2f752007-07-13 00:33:32 +00002896 strnlen(pSesInfo->serverName,
2897 SERVER_NAME_LEN_WITH_NULL * 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 + 1 + 4 /* slash IPC$ */ + 2,
2899 GFP_KERNEL);
2900 if (temp_unc == NULL)
2901 return -ENOMEM;
2902 temp_unc[0] = '\\';
2903 temp_unc[1] = '\\';
2904 strcpy(temp_unc + 2, pSesInfo->serverName);
2905 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
2906 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002907 cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 kfree(temp_unc);
2909 }
2910 if (rc == 0)
Steve Frenchc2cf07d2008-05-15 06:20:02 +00002911 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
Steve French737b7582005-04-28 22:41:06 -07002912 pnum_referrals, nls_codepage, remap);
Steve French366781c2008-01-25 10:12:41 +00002913 /* BB map targetUNCs to dfs_info3 structures, here or
2914 in CIFSGetDFSRefer BB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
2916 return rc;
2917}
2918
Jeff Layton09e50d52008-07-23 10:11:19 -04002919#ifdef CONFIG_DEBUG_LOCK_ALLOC
2920static struct lock_class_key cifs_key[2];
2921static struct lock_class_key cifs_slock_key[2];
2922
2923static inline void
2924cifs_reclassify_socket4(struct socket *sock)
2925{
2926 struct sock *sk = sock->sk;
2927 BUG_ON(sock_owned_by_user(sk));
2928 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2929 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2930}
2931
2932static inline void
2933cifs_reclassify_socket6(struct socket *sock)
2934{
2935 struct sock *sk = sock->sk;
2936 BUG_ON(sock_owned_by_user(sk));
2937 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2938 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2939}
2940#else
2941static inline void
2942cifs_reclassify_socket4(struct socket *sock)
2943{
2944}
2945
2946static inline void
2947cifs_reclassify_socket6(struct socket *sock)
2948{
2949}
2950#endif
2951
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002953static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954{
Steve French50c2f752007-07-13 00:33:32 +00002955 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
Steve French50c2f752007-07-13 00:33:32 +00002957 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 /* mask a nibble at a time and encode */
2959 target[j] = 'A' + (0x0F & (source[i] >> 4));
2960 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002961 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 }
2963
2964}
2965
Ben Greear3eb9a882010-09-01 17:06:02 -07002966static int
2967bind_socket(struct TCP_Server_Info *server)
2968{
2969 int rc = 0;
2970 if (server->srcaddr.ss_family != AF_UNSPEC) {
2971 /* Bind to the specified local IP address */
2972 struct socket *socket = server->ssocket;
2973 rc = socket->ops->bind(socket,
2974 (struct sockaddr *) &server->srcaddr,
2975 sizeof(server->srcaddr));
2976 if (rc < 0) {
2977 struct sockaddr_in *saddr4;
2978 struct sockaddr_in6 *saddr6;
2979 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2980 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2981 if (saddr6->sin6_family == AF_INET6)
2982 cERROR(1, "cifs: "
2983 "Failed to bind to: %pI6c, error: %d\n",
2984 &saddr6->sin6_addr, rc);
2985 else
2986 cERROR(1, "cifs: "
2987 "Failed to bind to: %pI4, error: %d\n",
2988 &saddr4->sin_addr.s_addr, rc);
2989 }
2990 }
2991 return rc;
2992}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993
2994static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002995ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996{
2997 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002998 /*
2999 * some servers require RFC1001 sessinit before sending
3000 * negprot - BB check reconnection in case where second
3001 * sessinit is sent but no second negprot
3002 */
3003 struct rfc1002_session_packet *ses_init_buf;
3004 struct smb_hdr *smb_buf;
3005 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3006 GFP_KERNEL);
3007 if (ses_init_buf) {
3008 ses_init_buf->trailer.session_req.called_len = 32;
3009
3010 if (server->server_RFC1001_name &&
3011 server->server_RFC1001_name[0] != 0)
3012 rfc1002mangle(ses_init_buf->trailer.
3013 session_req.called_name,
3014 server->server_RFC1001_name,
3015 RFC1001_NAME_LEN_WITH_NULL);
3016 else
3017 rfc1002mangle(ses_init_buf->trailer.
3018 session_req.called_name,
3019 DEFAULT_CIFS_CALLED_NAME,
3020 RFC1001_NAME_LEN_WITH_NULL);
3021
3022 ses_init_buf->trailer.session_req.calling_len = 32;
3023
3024 /*
3025 * calling name ends in null (byte 16) from old smb
3026 * convention.
3027 */
3028 if (server->workstation_RFC1001_name &&
3029 server->workstation_RFC1001_name[0] != 0)
3030 rfc1002mangle(ses_init_buf->trailer.
3031 session_req.calling_name,
3032 server->workstation_RFC1001_name,
3033 RFC1001_NAME_LEN_WITH_NULL);
3034 else
3035 rfc1002mangle(ses_init_buf->trailer.
3036 session_req.calling_name,
3037 "LINUX_CIFS_CLNT",
3038 RFC1001_NAME_LEN_WITH_NULL);
3039
3040 ses_init_buf->trailer.session_req.scope1 = 0;
3041 ses_init_buf->trailer.session_req.scope2 = 0;
3042 smb_buf = (struct smb_hdr *)ses_init_buf;
3043
3044 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003045 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003046 rc = smb_send(server, smb_buf, 0x44);
3047 kfree(ses_init_buf);
3048 /*
3049 * RFC1001 layer in at least one server
3050 * requires very short break before negprot
3051 * presumably because not expecting negprot
3052 * to follow so fast. This is a simple
3053 * solution that works without
3054 * complicating the code and causes no
3055 * significant slowing down on mount
3056 * for everyone else
3057 */
3058 usleep_range(1000, 2000);
3059 }
3060 /*
3061 * else the negprot may still work without this
3062 * even though malloc failed
3063 */
3064
3065 return rc;
3066}
3067
3068static int
3069generic_ip_connect(struct TCP_Server_Info *server)
3070{
3071 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003072 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003073 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003074 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003075 struct sockaddr *saddr;
3076
3077 saddr = (struct sockaddr *) &server->dstaddr;
3078
3079 if (server->dstaddr.ss_family == AF_INET6) {
3080 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3081 slen = sizeof(struct sockaddr_in6);
3082 sfamily = AF_INET6;
3083 } else {
3084 sport = ((struct sockaddr_in *) saddr)->sin_port;
3085 slen = sizeof(struct sockaddr_in);
3086 sfamily = AF_INET;
3087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003089 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003090 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3091 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003093 cERROR(1, "Error %d creating socket", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003094 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003097
3098 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003099 cFYI(1, "Socket created");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003100 server->ssocket = socket;
3101 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003102 if (sfamily == AF_INET6)
3103 cifs_reclassify_socket6(socket);
3104 else
3105 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106 }
3107
Ben Greear3eb9a882010-09-01 17:06:02 -07003108 rc = bind_socket(server);
3109 if (rc < 0)
3110 return rc;
3111
Jeff Laytond5c56052008-12-01 18:42:33 -05003112 /*
3113 * Eventually check for other socket options to change from
3114 * the default. sock_setsockopt not used because it expects
3115 * user space buffer
3116 */
3117 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003118 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003119
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003120 /* make the bufsizes depend on wsize/rsize and max requests */
3121 if (server->noautotune) {
3122 if (socket->sk->sk_sndbuf < (200 * 1024))
3123 socket->sk->sk_sndbuf = 200 * 1024;
3124 if (socket->sk->sk_rcvbuf < (140 * 1024))
3125 socket->sk->sk_rcvbuf = 140 * 1024;
3126 }
3127
Steve French6a5fa2362010-01-01 01:28:43 +00003128 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003129 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003130 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3131 (char *)&val, sizeof(val));
3132 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003133 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003134 }
3135
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003136 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
3137 socket->sk->sk_sndbuf,
3138 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3139
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003140 rc = socket->ops->connect(socket, saddr, slen, 0);
3141 if (rc < 0) {
3142 cFYI(1, "Error %d connecting to server", rc);
3143 sock_release(socket);
3144 server->ssocket = NULL;
3145 return rc;
3146 }
3147
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003148 if (sport == htons(RFC1001_PORT))
3149 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003150
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 return rc;
3152}
3153
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003154static int
3155ip_connect(struct TCP_Server_Info *server)
3156{
Steve French6da97912011-03-13 18:55:55 +00003157 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003158 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3159 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3160
3161 if (server->dstaddr.ss_family == AF_INET6)
3162 sport = &addr6->sin6_port;
3163 else
3164 sport = &addr->sin_port;
3165
3166 if (*sport == 0) {
3167 int rc;
3168
3169 /* try with 445 port at first */
3170 *sport = htons(CIFS_PORT);
3171
3172 rc = generic_ip_connect(server);
3173 if (rc >= 0)
3174 return rc;
3175
3176 /* if it failed, try with 139 port */
3177 *sport = htons(RFC1001_PORT);
3178 }
3179
3180 return generic_ip_connect(server);
3181}
3182
Steve French96daf2b2011-05-27 04:34:02 +00003183void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003184 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003185{
3186 /* if we are reconnecting then should we check to see if
3187 * any requested capabilities changed locally e.g. via
3188 * remount but we can not do much about it here
3189 * if they have (even if we could detect it by the following)
3190 * Perhaps we could add a backpointer to array of sb from tcon
3191 * or if we change to make all sb to same share the same
3192 * sb as NFS - then we only have one backpointer to sb.
3193 * What if we wanted to mount the server share twice once with
3194 * and once without posixacls or posix paths? */
3195 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003196
Steve Frenchc18c8422007-07-18 23:21:09 +00003197 if (vol_info && vol_info->no_linux_ext) {
3198 tcon->fsUnixInfo.Capability = 0;
3199 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003200 cFYI(1, "Linux protocol extensions disabled");
Steve Frenchc18c8422007-07-18 23:21:09 +00003201 return;
3202 } else if (vol_info)
3203 tcon->unix_ext = 1; /* Unix Extensions supported */
3204
3205 if (tcon->unix_ext == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003206 cFYI(1, "Unix extensions disabled so not set on reconnect");
Steve Frenchc18c8422007-07-18 23:21:09 +00003207 return;
3208 }
Steve French50c2f752007-07-13 00:33:32 +00003209
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003210 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003211 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French6848b732011-05-26 18:38:54 +00003212 cFYI(1, "unix caps which server supports %lld", cap);
Steve French8af18972007-02-14 04:42:51 +00003213 /* check for reconnect case in which we do not
3214 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003215 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003216 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003217 originally at mount time */
3218 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3219 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003220 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3221 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003222 cERROR(1, "POSIXPATH support change");
Steve French8af18972007-02-14 04:42:51 +00003223 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003224 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003225 cERROR(1, "possible reconnect error");
3226 cERROR(1, "server disabled POSIX path support");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003227 }
Steve French8af18972007-02-14 04:42:51 +00003228 }
Steve French50c2f752007-07-13 00:33:32 +00003229
Steve French6848b732011-05-26 18:38:54 +00003230 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3231 cERROR(1, "per-share encryption not supported yet");
3232
Steve French8af18972007-02-14 04:42:51 +00003233 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003234 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003235 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003236 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003237 cFYI(1, "negotiated posix acl support");
Al Viro2c6292a2011-06-17 09:05:48 -04003238 if (cifs_sb)
3239 cifs_sb->mnt_cifs_flags |=
3240 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003241 }
3242
Steve French75865f8c2007-06-24 18:30:48 +00003243 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003244 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003245 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003246 cFYI(1, "negotiate posix pathnames");
Al Viro2c6292a2011-06-17 09:05:48 -04003247 if (cifs_sb)
3248 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003249 CIFS_MOUNT_POSIX_PATHS;
3250 }
Steve French50c2f752007-07-13 00:33:32 +00003251
Joe Perchesb6b38f72010-04-21 03:50:45 +00003252 cFYI(1, "Negotiate caps 0x%x", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003253#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003254 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003255 cFYI(1, "FCNTL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003256 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003257 cFYI(1, "EXTATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003258 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003259 cFYI(1, "POSIX path cap");
Steve French75865f8c2007-06-24 18:30:48 +00003260 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003261 cFYI(1, "XATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00003262 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003263 cFYI(1, "POSIX ACL cap");
Steve French75865f8c2007-06-24 18:30:48 +00003264 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003265 cFYI(1, "very large read cap");
Steve French75865f8c2007-06-24 18:30:48 +00003266 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00003267 cFYI(1, "very large write cap");
Steve French6848b732011-05-26 18:38:54 +00003268 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3269 cFYI(1, "transport encryption cap");
3270 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3271 cFYI(1, "mandatory transport encryption cap");
Steve French8af18972007-02-14 04:42:51 +00003272#endif /* CIFS_DEBUG2 */
3273 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00003274 if (vol_info == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003275 cFYI(1, "resetting capabilities failed");
Steve French442aa312007-09-24 20:25:46 +00003276 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00003277 cERROR(1, "Negotiating Unix capabilities "
Steve French5a44b312007-09-20 15:16:24 +00003278 "with the server failed. Consider "
3279 "mounting with the Unix Extensions\n"
3280 "disabled, if problems are found, "
3281 "by specifying the nounix mount "
Joe Perchesb6b38f72010-04-21 03:50:45 +00003282 "option.");
Steve French5a44b312007-09-20 15:16:24 +00003283
Steve French8af18972007-02-14 04:42:51 +00003284 }
3285 }
3286}
3287
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003288void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3289 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003290{
Jeff Layton2de970f2010-10-06 19:51:12 -04003291 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
3292
Al Viro2ced6f62011-06-17 09:20:04 -04003293 spin_lock_init(&cifs_sb->tlink_tree_lock);
3294 cifs_sb->tlink_tree = RB_ROOT;
3295
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003296 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003297 * Temporarily set r/wsize for matching superblock. If we end up using
3298 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003299 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003300 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003301 cifs_sb->wsize = pvolume_info->wsize;
3302
Steve French3b795212008-11-13 19:45:32 +00003303 cifs_sb->mnt_uid = pvolume_info->linux_uid;
3304 cifs_sb->mnt_gid = pvolume_info->linux_gid;
3305 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
3306 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Al Viro5206efd2011-07-26 03:22:14 -04003307 cFYI(1, "file mode: 0x%hx dir mode: 0x%hx",
Joe Perchesb6b38f72010-04-21 03:50:45 +00003308 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00003309
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303310 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003311 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05303312
Steve French3b795212008-11-13 19:45:32 +00003313 if (pvolume_info->noperm)
3314 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3315 if (pvolume_info->setuids)
3316 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3317 if (pvolume_info->server_ino)
3318 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3319 if (pvolume_info->remap)
3320 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3321 if (pvolume_info->no_xattr)
3322 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3323 if (pvolume_info->sfu_emul)
3324 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3325 if (pvolume_info->nobrl)
3326 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00003327 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00003328 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00003329 if (pvolume_info->mand_lock)
3330 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00003331 if (pvolume_info->rwpidforward)
3332 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00003333 if (pvolume_info->cifs_acl)
3334 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003335 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003336 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003337 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
3338 }
3339 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05003340 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01003341 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
3342 }
Steve French3b795212008-11-13 19:45:32 +00003343 if (pvolume_info->override_uid)
3344 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3345 if (pvolume_info->override_gid)
3346 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3347 if (pvolume_info->dynperm)
3348 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05303349 if (pvolume_info->fsc)
3350 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04003351 if (pvolume_info->multiuser)
3352 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
3353 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05003354 if (pvolume_info->strict_io)
3355 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00003356 if (pvolume_info->direct_io) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003357 cFYI(1, "mounting share using direct i/o");
Steve French3b795212008-11-13 19:45:32 +00003358 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
3359 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02003360 if (pvolume_info->mfsymlinks) {
3361 if (pvolume_info->sfu_emul) {
3362 cERROR(1, "mount option mfsymlinks ignored if sfu "
3363 "mount option is used");
3364 } else {
3365 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3366 }
3367 }
Steve French3b795212008-11-13 19:45:32 +00003368
3369 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesb6b38f72010-04-21 03:50:45 +00003370 cERROR(1, "mount option dynperm ignored if cifsacl "
3371 "mount option supported");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04003372}
3373
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003374/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003375 * When the server supports very large reads and writes via POSIX extensions,
3376 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
3377 * including the RFC1001 length.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003378 *
3379 * Note that this might make for "interesting" allocation problems during
Jeff Layton1190f6a2011-06-22 17:33:57 -04003380 * writeback however as we have to allocate an array of pointers for the
3381 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003382 *
3383 * For reads, there is a similar problem as we need to allocate an array
3384 * of kvecs to handle the receive, though that should only need to be done
3385 * once.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003386 */
Jeff Layton1190f6a2011-06-22 17:33:57 -04003387#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003388#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003389
3390/*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003391 * When the server doesn't allow large posix writes, only allow a rsize/wsize
3392 * of 2^17-1 minus the size of the call header. That allows for a read or
3393 * write up to the maximum size described by RFC1002.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003394 */
Pavel Shilovsky94443f42011-10-07 18:57:45 +04003395#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003396#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003397
3398/*
3399 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
3400 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
3401 * a single wsize request with a single call.
3402 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003403#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
3404
3405/*
Jeff Laytonce91acb2012-01-17 16:08:51 -05003406 * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
3407 * those values when posix extensions aren't in force. In actuality here, we
3408 * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
3409 * to be ok with the extra byte even though Windows doesn't send writes that
3410 * are that large.
3411 *
3412 * Citation:
3413 *
3414 * 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 -04003415 */
3416#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
Jeff Laytonce91acb2012-01-17 16:08:51 -05003417#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003418
3419static unsigned int
Steve French96daf2b2011-05-27 04:34:02 +00003420cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003421{
3422 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3423 struct TCP_Server_Info *server = tcon->ses->server;
Jeff Laytonce91acb2012-01-17 16:08:51 -05003424 unsigned int wsize;
3425
3426 /* start with specified wsize, or default */
3427 if (pvolume_info->wsize)
3428 wsize = pvolume_info->wsize;
3429 else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
3430 wsize = CIFS_DEFAULT_IOSIZE;
3431 else
3432 wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003433
3434 /* can server support 24-bit write sizes? (via UNIX extensions) */
3435 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
Jeff Layton1190f6a2011-06-22 17:33:57 -04003436 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003437
Jeff Layton1190f6a2011-06-22 17:33:57 -04003438 /*
3439 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
3440 * Limit it to max buffer offered by the server, minus the size of the
3441 * WRITEX header, not including the 4 byte RFC1001 length.
3442 */
3443 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
3444 (!(server->capabilities & CAP_UNIX) &&
3445 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
3446 wsize = min_t(unsigned int, wsize,
3447 server->maxBuf - sizeof(WRITE_REQ) + 4);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003448
3449 /* hard limit of CIFS_MAX_WSIZE */
3450 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
3451
3452 return wsize;
3453}
3454
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003455static unsigned int
3456cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
3457{
3458 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3459 struct TCP_Server_Info *server = tcon->ses->server;
3460 unsigned int rsize, defsize;
3461
3462 /*
3463 * Set default value...
3464 *
3465 * HACK alert! Ancient servers have very small buffers. Even though
3466 * MS-CIFS indicates that servers are only limited by the client's
3467 * bufsize for reads, testing against win98se shows that it throws
3468 * INVALID_PARAMETER errors if you try to request too large a read.
3469 *
3470 * If the server advertises a MaxBufferSize of less than one page,
3471 * assume that it also can't satisfy reads larger than that either.
3472 *
3473 * FIXME: Is there a better heuristic for this?
3474 */
3475 if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP))
3476 defsize = CIFS_DEFAULT_IOSIZE;
3477 else if (server->capabilities & CAP_LARGE_READ_X)
3478 defsize = CIFS_DEFAULT_NON_POSIX_RSIZE;
3479 else if (server->maxBuf >= PAGE_CACHE_SIZE)
3480 defsize = CIFSMaxBufSize;
3481 else
3482 defsize = server->maxBuf - sizeof(READ_RSP);
3483
3484 rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize;
3485
3486 /*
3487 * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to
3488 * the client's MaxBufferSize.
3489 */
3490 if (!(server->capabilities & CAP_LARGE_READ_X))
3491 rsize = min_t(unsigned int, CIFSMaxBufSize, rsize);
3492
3493 /* hard limit of CIFS_MAX_RSIZE */
3494 rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE);
3495
3496 return rsize;
3497}
3498
Igor Mammedove4cce942009-02-10 14:10:26 +03003499static int
Steve French96daf2b2011-05-27 04:34:02 +00003500is_path_accessible(int xid, struct cifs_tcon *tcon,
Igor Mammedove4cce942009-02-10 14:10:26 +03003501 struct cifs_sb_info *cifs_sb, const char *full_path)
3502{
3503 int rc;
Igor Mammedove4cce942009-02-10 14:10:26 +03003504 FILE_ALL_INFO *pfile_info;
3505
Igor Mammedove4cce942009-02-10 14:10:26 +03003506 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
3507 if (pfile_info == NULL)
3508 return -ENOMEM;
3509
3510 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
3511 0 /* not legacy */, cifs_sb->local_nls,
3512 cifs_sb->mnt_cifs_flags &
3513 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton221d1d72011-05-17 06:40:30 -04003514
3515 if (rc == -EOPNOTSUPP || rc == -EINVAL)
3516 rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
3517 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
3518 CIFS_MOUNT_MAP_SPECIAL_CHR);
Igor Mammedove4cce942009-02-10 14:10:26 +03003519 kfree(pfile_info);
3520 return rc;
3521}
3522
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003523static void
3524cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003525{
Sean Finneyb9468452011-04-11 13:19:32 +00003526 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003527 kzfree(volume_info->password);
Steve French13589c42011-08-18 04:41:55 +00003528 if (volume_info->UNCip != volume_info->UNC + 2)
3529 kfree(volume_info->UNCip);
Jesper Juhl95c75452011-08-27 18:58:34 +02003530 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00003531 kfree(volume_info->domainname);
3532 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003533 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003534}
3535
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003536void
3537cifs_cleanup_volume_info(struct smb_vol *volume_info)
3538{
3539 if (!volume_info)
3540 return;
3541 cleanup_volume_info_contents(volume_info);
3542 kfree(volume_info);
3543}
3544
3545
Steve French2d6d5892009-04-09 00:36:44 +00003546#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003547/* build_path_to_root returns full path to root when
3548 * we do not have an exiting connection (tcon) */
3549static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003550build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003551 const struct cifs_sb_info *cifs_sb)
3552{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003553 char *full_path, *pos;
3554 unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
3555 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003556
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003557 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003558 if (full_path == NULL)
3559 return ERR_PTR(-ENOMEM);
3560
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003561 strncpy(full_path, vol->UNC, unc_len);
3562 pos = full_path + unc_len;
3563
3564 if (pplen) {
3565 strncpy(pos, vol->prepath, pplen);
3566 pos += pplen;
3567 }
3568
3569 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003570 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003571 cFYI(1, "%s: full_path=%s", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003572 return full_path;
3573}
Sean Finneydd613942011-04-11 13:19:30 +00003574
3575/*
3576 * Perform a dfs referral query for a share and (optionally) prefix
3577 *
Sean Finney046462a2011-04-11 13:19:33 +00003578 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3579 * to a string containing updated options for the submount. Otherwise it
3580 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003581 *
3582 * Returns the rc from get_dfs_path to the caller, which can be used to
3583 * determine whether there were referrals.
3584 */
3585static int
Steve French96daf2b2011-05-27 04:34:02 +00003586expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
Sean Finneydd613942011-04-11 13:19:30 +00003587 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003588 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003589{
3590 int rc;
3591 unsigned int num_referrals = 0;
3592 struct dfs_info3_param *referrals = NULL;
3593 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3594
3595 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3596 if (IS_ERR(full_path))
3597 return PTR_ERR(full_path);
3598
3599 /* For DFS paths, skip the first '\' of the UNC */
3600 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3601
3602 rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
3603 &num_referrals, &referrals,
3604 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3605
3606 if (!rc && num_referrals > 0) {
3607 char *fake_devname = NULL;
3608
3609 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3610 full_path + 1, referrals,
3611 &fake_devname);
3612
3613 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003614
Sean Finneydd613942011-04-11 13:19:30 +00003615 if (IS_ERR(mdata)) {
3616 rc = PTR_ERR(mdata);
3617 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003618 } else {
3619 cleanup_volume_info_contents(volume_info);
3620 memset(volume_info, '\0', sizeof(*volume_info));
3621 rc = cifs_setup_volume_info(volume_info, mdata,
3622 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003623 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003624 kfree(fake_devname);
3625 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003626 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003627 }
3628 kfree(full_path);
3629 return rc;
3630}
Steve French2d6d5892009-04-09 00:36:44 +00003631#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003632
Jeff Layton04db79b2011-07-06 08:10:38 -04003633static int
3634cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3635 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003637 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003638
Jeff Layton04db79b2011-07-06 08:10:38 -04003639 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3640 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641
Jeff Layton7586b762008-12-01 18:41:49 -05003642 if (volume_info->nullauth) {
Jeff Layton04febab2012-01-17 16:09:15 -05003643 cFYI(1, "Anonymous login");
3644 kfree(volume_info->username);
3645 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05003646 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 /* BB fixme parse for domain name here */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003648 cFYI(1, "Username: %s", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 } else {
Steve Frenchbf820672005-12-01 22:32:42 -08003650 cifserror("No username specified");
Steve French50c2f752007-07-13 00:33:32 +00003651 /* In userspace mount helper we can get user name from alternate
3652 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003653 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 }
3655
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003657 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003658 /* load_nls_default cannot return null */
3659 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003661 volume_info->local_nls = load_nls(volume_info->iocharset);
3662 if (volume_info->local_nls == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003663 cERROR(1, "CIFS mount error: iocharset %s not found",
3664 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003665 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 }
3667 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003668
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003669 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003670}
3671
3672struct smb_vol *
3673cifs_get_volume_info(char *mount_data, const char *devname)
3674{
3675 int rc;
3676 struct smb_vol *volume_info;
3677
3678 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
3679 if (!volume_info)
3680 return ERR_PTR(-ENOMEM);
3681
3682 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3683 if (rc) {
3684 cifs_cleanup_volume_info(volume_info);
3685 volume_info = ERR_PTR(rc);
3686 }
3687
3688 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003689}
3690
3691int
Al Viro2c6292a2011-06-17 09:05:48 -04003692cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003693{
Jeff Layton1daaae82012-03-21 06:30:40 -04003694 int rc;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003695 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003696 struct cifs_ses *pSesInfo;
3697 struct cifs_tcon *tcon;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003698 struct TCP_Server_Info *srvTcp;
3699 char *full_path;
3700 struct tcon_link *tlink;
3701#ifdef CONFIG_CIFS_DFS_UPCALL
3702 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003703#endif
Al Virodd854462011-06-17 08:24:42 -04003704
3705 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3706 if (rc)
3707 return rc;
3708
Jeff Layton20547492011-07-09 12:21:07 -04003709#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003710try_mount_again:
3711 /* cleanup activities if we're chasing a referral */
3712 if (referral_walks_count) {
3713 if (tcon)
3714 cifs_put_tcon(tcon);
3715 else if (pSesInfo)
3716 cifs_put_smb_ses(pSesInfo);
3717
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003718 FreeXid(xid);
3719 }
3720#endif
Jeff Layton1daaae82012-03-21 06:30:40 -04003721 rc = 0;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003722 tcon = NULL;
3723 pSesInfo = NULL;
3724 srvTcp = NULL;
3725 full_path = NULL;
3726 tlink = NULL;
3727
3728 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729
Jeff Layton63c038c2008-12-01 18:41:46 -05003730 /* get a reference to a tcp session */
Jeff Layton7586b762008-12-01 18:41:49 -05003731 srvTcp = cifs_get_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05003732 if (IS_ERR(srvTcp)) {
3733 rc = PTR_ERR(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003734 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003735 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736 }
3737
Jeff Layton36988c72010-04-24 07:57:43 -04003738 /* get a reference to a SMB session */
3739 pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
3740 if (IS_ERR(pSesInfo)) {
3741 rc = PTR_ERR(pSesInfo);
3742 pSesInfo = NULL;
3743 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744 }
Steve French50c2f752007-07-13 00:33:32 +00003745
Jeff Laytond00c28d2010-04-24 07:57:44 -04003746 /* search for existing tcon to this server share */
3747 tcon = cifs_get_tcon(pSesInfo, volume_info);
3748 if (IS_ERR(tcon)) {
3749 rc = PTR_ERR(tcon);
3750 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003751 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003752 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003753
Steve French6848b732011-05-26 18:38:54 +00003754 /* tell server which Unix caps we support */
3755 if (tcon->ses->capabilities & CAP_UNIX) {
3756 /* reset of caps checks mount to see if unix extensions
3757 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003758 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003759 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3760 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3761 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3762 rc = -EACCES;
3763 goto mount_fail_check;
3764 }
3765 } else
3766 tcon->unix_ext = 0; /* server does not support them */
3767
Steve Frenchd82c2df2008-11-15 00:07:26 +00003768 /* do not care if following two calls succeed - informational */
3769 if (!tcon->ipc) {
3770 CIFSSMBQFSDeviceInfo(xid, tcon);
3771 CIFSSMBQFSAttributeInfo(xid, tcon);
3772 }
3773
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003774 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003775 cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003776
Jeff Layton66bfaad2011-10-19 15:30:35 -04003777 /* tune readahead according to rsize */
Jeff Layton8f714652012-05-01 17:41:49 -04003778 cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
Jeff Layton03ceace2010-12-06 21:07:33 -05003779
Igor Mammedove4cce942009-02-10 14:10:26 +03003780remote_path_check:
3781#ifdef CONFIG_CIFS_DFS_UPCALL
3782 /*
3783 * Perform an unconditional check for whether there are DFS
3784 * referrals for this path without prefix, to provide support
3785 * for DFS referrals from w2k8 servers which don't seem to respond
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003786 * with PATH_NOT_COVERED to requests that include the prefix.
3787 * Chase the referral if found, otherwise continue normally.
Steve Frenchd036f502009-04-03 03:12:08 +00003788 */
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003789 if (referral_walks_count == 0) {
3790 int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
3791 cifs_sb, false);
3792 if (!refrc) {
3793 referral_walks_count++;
3794 goto try_mount_again;
3795 }
3796 }
3797#endif
3798
Steve Frenchf87d39d2011-05-27 03:50:55 +00003799 /* check if a whole path is not remote */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 if (!rc && tcon) {
3801 /* build_path_to_root works only when we have a valid tcon */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003802 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Steve French7c7b25b2006-06-01 19:20:10 +00003803 if (full_path == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 rc = -ENOMEM;
3805 goto mount_fail_check;
3806 }
3807 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
3808 if (rc != 0 && rc != -EREMOTE) {
3809 kfree(full_path);
3810 goto mount_fail_check;
3811 }
3812 kfree(full_path);
3813 }
3814
3815 /* get referral if needed */
3816 if (rc == -EREMOTE) {
3817#ifdef CONFIG_CIFS_DFS_UPCALL
3818 if (referral_walks_count > MAX_NESTED_LINKS) {
3819 /*
Steve Frencheeac8042006-01-13 21:34:58 -08003820 * BB: when we implement proper loop detection,
Steve French4523cc32007-04-30 20:13:06 +00003821 * we will remove this check. But now we need it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 * to prevent an indefinite loop if 'DFS tree' is
3823 * misconfigured (i.e. has loops).
3824 */
3825 rc = -ELOOP;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003826 goto mount_fail_check;
3827 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003828
Sean Finneydd613942011-04-11 13:19:30 +00003829 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003830 true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003831
Sean Finneydd613942011-04-11 13:19:30 +00003832 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003833 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003834 goto try_mount_again;
3835 }
Sean Finneydd613942011-04-11 13:19:30 +00003836 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003837#else /* No DFS support, return error on mount */
3838 rc = -EOPNOTSUPP;
3839#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003840 }
3841
Jeff Layton9d002df2010-10-06 19:51:11 -04003842 if (rc)
3843 goto mount_fail_check;
3844
3845 /* now, hang the tcon off of the superblock */
3846 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3847 if (tlink == NULL) {
3848 rc = -ENOMEM;
3849 goto mount_fail_check;
3850 }
3851
Jeff Laytonb647c352010-10-28 11:16:44 -04003852 tlink->tl_uid = pSesInfo->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003853 tlink->tl_tcon = tcon;
3854 tlink->tl_time = jiffies;
3855 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3856 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3857
Jeff Layton413e6612010-10-28 13:33:38 -04003858 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003859 spin_lock(&cifs_sb->tlink_tree_lock);
3860 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3861 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003862
Jeff Laytonda472fc2012-03-23 14:40:53 -04003863 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04003864 TLINK_IDLE_EXPIRE);
3865
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003866mount_fail_check:
3867 /* on error free sesinfo and tcon struct if needed */
3868 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003869 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003870 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003871 if (tcon)
3872 cifs_put_tcon(tcon);
3873 else if (pSesInfo)
3874 cifs_put_smb_ses(pSesInfo);
3875 else
3876 cifs_put_tcp_session(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003877 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003878 }
3879
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 FreeXid(xid);
3882 return rc;
3883}
3884
Jeff Layton8d1bca32011-06-11 21:17:10 -04003885/*
3886 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3887 * pointer may be NULL.
3888 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889int
Steve French96daf2b2011-05-27 04:34:02 +00003890CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3891 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 const struct nls_table *nls_codepage)
3893{
3894 struct smb_hdr *smb_buffer;
3895 struct smb_hdr *smb_buffer_response;
3896 TCONX_REQ *pSMB;
3897 TCONX_RSP *pSMBr;
3898 unsigned char *bcc_ptr;
3899 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003900 int length;
3901 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
3903 if (ses == NULL)
3904 return -EIO;
3905
3906 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003907 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003909
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 smb_buffer_response = smb_buffer;
3911
3912 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3913 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003914
3915 smb_buffer->Mid = GetNextMid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 smb_buffer->Uid = ses->Suid;
3917 pSMB = (TCONX_REQ *) smb_buffer;
3918 pSMBr = (TCONX_RSP *) smb_buffer_response;
3919
3920 pSMB->AndXCommand = 0xFF;
3921 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003923 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003924 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003925 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003926 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003927 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003928 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003929 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003930 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3931 specified as required (when that support is added to
3932 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003933 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003934 by Samba (not sure whether other servers allow
3935 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003936#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003937 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003938 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003939 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003940 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003941 SECMODE_PW_ENCRYPT ? true : false,
3942 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003943 else
3944#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003945 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05003946 bcc_ptr, nls_codepage);
Steve Frencheeac8042006-01-13 21:34:58 -08003947
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003948 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003949 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003950 /* must align unicode strings */
3951 *bcc_ptr = 0; /* null byte password */
3952 bcc_ptr++;
3953 }
Steve Frencheeac8042006-01-13 21:34:58 -08003954 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955
Steve French96daf2b2011-05-27 04:34:02 +00003956 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003957 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3959
3960 if (ses->capabilities & CAP_STATUS32) {
3961 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3962 }
3963 if (ses->capabilities & CAP_DFS) {
3964 smb_buffer->Flags2 |= SMBFLG2_DFS;
3965 }
3966 if (ses->capabilities & CAP_UNICODE) {
3967 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3968 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06003969 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00003970 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003971 (/* server len*/ + 256 /* share len */), nls_codepage);
3972 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973 bcc_ptr += 2; /* skip trailing null */
3974 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 strcpy(bcc_ptr, tree);
3976 bcc_ptr += strlen(tree) + 1;
3977 }
3978 strcpy(bcc_ptr, "?????");
3979 bcc_ptr += strlen("?????");
3980 bcc_ptr += 1;
3981 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003982 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3983 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 pSMB->ByteCount = cpu_to_le16(count);
3985
Steve French133672e2007-11-13 22:41:37 +00003986 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003987 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 /* above now done in SendReceive */
3990 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003991 bool is_unicode;
3992
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003994 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 tcon->tid = smb_buffer_response->Tid;
3996 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003997 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003998 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003999 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
4000 is_unicode = true;
4001 else
4002 is_unicode = false;
4003
Jeff Laytoncc20c032009-04-30 07:16:21 -04004004
Steve French50c2f752007-07-13 00:33:32 +00004005 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00004006 if (length == 3) {
4007 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
4008 (bcc_ptr[2] == 'C')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004009 cFYI(1, "IPC connection");
Steve French7f8ed422007-09-28 22:28:55 +00004010 tcon->ipc = 1;
4011 }
4012 } else if (length == 2) {
4013 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
4014 /* the most common case */
Joe Perchesb6b38f72010-04-21 03:50:45 +00004015 cFYI(1, "disk share connection");
Steve French7f8ed422007-09-28 22:28:55 +00004016 }
4017 }
Steve French50c2f752007-07-13 00:33:32 +00004018 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04004019 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004021
4022 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04004023 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06004024 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00004025 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04004026 nls_codepage);
4027
Joe Perchesb6b38f72010-04-21 03:50:45 +00004028 cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04004029
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004030 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00004031 (smb_buffer_response->WordCount == 7))
4032 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00004033 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
4034 else
4035 tcon->Flags = 0;
Joe Perchesb6b38f72010-04-21 03:50:45 +00004036 cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00004038 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 ses->ipc_tid = smb_buffer_response->Tid;
4040 }
4041
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00004042 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043 return rc;
4044}
4045
Al Viro2a9b9952011-06-17 09:27:16 -04004046void
4047cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048{
Jeff Laytonb647c352010-10-28 11:16:44 -04004049 struct rb_root *root = &cifs_sb->tlink_tree;
4050 struct rb_node *node;
4051 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
Jeff Layton2de970f2010-10-06 19:51:12 -04004053 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
4054
Jeff Laytonb647c352010-10-28 11:16:44 -04004055 spin_lock(&cifs_sb->tlink_tree_lock);
4056 while ((node = rb_first(root))) {
4057 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4058 cifs_get_tlink(tlink);
4059 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4060 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00004061
Jeff Laytonb647c352010-10-28 11:16:44 -04004062 spin_unlock(&cifs_sb->tlink_tree_lock);
4063 cifs_put_tlink(tlink);
4064 spin_lock(&cifs_sb->tlink_tree_lock);
4065 }
4066 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004067
Al Virodd854462011-06-17 08:24:42 -04004068 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04004069 kfree(cifs_sb->mountdata);
4070 unload_nls(cifs_sb->local_nls);
4071 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00004072}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Steve French96daf2b2011-05-27 04:34:02 +00004074int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075{
4076 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04004077 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Jeff Layton198b5682010-04-24 07:57:48 -04004079 /* only send once per connect */
4080 if (server->maxBuf != 0)
4081 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004083 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004084 rc = CIFSSMBNegotiate(xid, ses);
4085 if (rc == -EAGAIN) {
4086 /* retry only once on 1st time connection */
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04004087 cifs_set_credits(server, 1);
Jeff Layton198b5682010-04-24 07:57:48 -04004088 rc = CIFSSMBNegotiate(xid, ses);
4089 if (rc == -EAGAIN)
4090 rc = -EHOSTDOWN;
4091 }
4092 if (rc == 0) {
4093 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04004094 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04004095 server->tcpStatus = CifsGood;
4096 else
4097 rc = -EHOSTDOWN;
4098 spin_unlock(&GlobalMid_Lock);
4099
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 }
Steve French26b994f2008-08-06 05:11:33 +00004101
Jeff Layton198b5682010-04-24 07:57:48 -04004102 return rc;
4103}
Steve French26b994f2008-08-06 05:11:33 +00004104
Jeff Layton198b5682010-04-24 07:57:48 -04004105
Steve French96daf2b2011-05-27 04:34:02 +00004106int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
Jeff Layton198b5682010-04-24 07:57:48 -04004107 struct nls_table *nls_info)
4108{
4109 int rc = 0;
4110 struct TCP_Server_Info *server = ses->server;
4111
4112 ses->flags = 0;
4113 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00004114 if (linuxExtEnabled == 0)
Jeff Layton198b5682010-04-24 07:57:48 -04004115 ses->capabilities &= (~CAP_UNIX);
Steve French20418ac2009-04-30 16:13:32 +00004116
Joe Perchesb6b38f72010-04-21 03:50:45 +00004117 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
Steve French96daf2b2011-05-27 04:34:02 +00004118 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04004119
Jeff Layton198b5682010-04-24 07:57:48 -04004120 rc = CIFS_SessSetup(xid, ses, nls_info);
Steve French26b994f2008-08-06 05:11:33 +00004121 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00004122 cERROR(1, "Send error in SessSetup = %d", rc);
Steve French26b994f2008-08-06 05:11:33 +00004123 } else {
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004124 mutex_lock(&ses->server->srv_mutex);
4125 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004126 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004127 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004128 server->sequence_number = 0x2;
4129 server->session_estab = true;
4130 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05004131 }
4132 mutex_unlock(&server->srv_mutex);
4133
Joe Perchesb6b38f72010-04-21 03:50:45 +00004134 cFYI(1, "CIFS Session Established successfully");
Steve French20418ac2009-04-30 16:13:32 +00004135 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04004136 ses->status = CifsGood;
4137 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00004138 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00004139 }
4140
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004141 kfree(ses->auth_key.response);
4142 ses->auth_key.response = NULL;
4143 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05004144 kfree(ses->ntlmssp);
4145 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05004146
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 return rc;
4148}
4149
Jeff Layton8a8798a2012-01-17 16:09:15 -05004150static int
4151cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
4152{
4153 switch (ses->server->secType) {
4154 case Kerberos:
4155 vol->secFlg = CIFSSEC_MUST_KRB5;
4156 return 0;
4157 case NTLMv2:
4158 vol->secFlg = CIFSSEC_MUST_NTLMV2;
4159 break;
4160 case NTLM:
4161 vol->secFlg = CIFSSEC_MUST_NTLM;
4162 break;
4163 case RawNTLMSSP:
4164 vol->secFlg = CIFSSEC_MUST_NTLMSSP;
4165 break;
4166 case LANMAN:
4167 vol->secFlg = CIFSSEC_MUST_LANMAN;
4168 break;
4169 }
4170
4171 return cifs_set_cifscreds(vol, ses);
4172}
4173
Steve French96daf2b2011-05-27 04:34:02 +00004174static struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004175cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
4176{
Jeff Layton8a8798a2012-01-17 16:09:15 -05004177 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00004178 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
4179 struct cifs_ses *ses;
4180 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04004181 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04004182
4183 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03004184 if (vol_info == NULL)
4185 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04004186
Jeff Layton9d002df2010-10-06 19:51:11 -04004187 vol_info->local_nls = cifs_sb->local_nls;
4188 vol_info->linux_uid = fsuid;
4189 vol_info->cred_uid = fsuid;
4190 vol_info->UNC = master_tcon->treeName;
4191 vol_info->retry = master_tcon->retry;
4192 vol_info->nocase = master_tcon->nocase;
4193 vol_info->local_lease = master_tcon->local_lease;
4194 vol_info->no_linux_ext = !master_tcon->unix_ext;
4195
Jeff Layton8a8798a2012-01-17 16:09:15 -05004196 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
4197 if (rc) {
4198 tcon = ERR_PTR(rc);
4199 goto out;
4200 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004201
4202 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304203 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004204 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05304205 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004206
4207 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
4208 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00004209 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04004210 cifs_put_tcp_session(master_tcon->ses->server);
4211 goto out;
4212 }
4213
4214 tcon = cifs_get_tcon(ses, vol_info);
4215 if (IS_ERR(tcon)) {
4216 cifs_put_smb_ses(ses);
4217 goto out;
4218 }
4219
4220 if (ses->capabilities & CAP_UNIX)
4221 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4222out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05004223 kfree(vol_info->username);
4224 kfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04004225 kfree(vol_info);
4226
4227 return tcon;
4228}
4229
Steve French96daf2b2011-05-27 04:34:02 +00004230struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04004231cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
4232{
4233 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
4234}
4235
4236static int
4237cifs_sb_tcon_pending_wait(void *unused)
4238{
4239 schedule();
4240 return signal_pending(current) ? -ERESTARTSYS : 0;
4241}
4242
Jeff Laytonb647c352010-10-28 11:16:44 -04004243/* find and return a tlink with given uid */
4244static struct tcon_link *
4245tlink_rb_search(struct rb_root *root, uid_t uid)
4246{
4247 struct rb_node *node = root->rb_node;
4248 struct tcon_link *tlink;
4249
4250 while (node) {
4251 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
4252
4253 if (tlink->tl_uid > uid)
4254 node = node->rb_left;
4255 else if (tlink->tl_uid < uid)
4256 node = node->rb_right;
4257 else
4258 return tlink;
4259 }
4260 return NULL;
4261}
4262
4263/* insert a tcon_link into the tree */
4264static void
4265tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
4266{
4267 struct rb_node **new = &(root->rb_node), *parent = NULL;
4268 struct tcon_link *tlink;
4269
4270 while (*new) {
4271 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
4272 parent = *new;
4273
4274 if (tlink->tl_uid > new_tlink->tl_uid)
4275 new = &((*new)->rb_left);
4276 else
4277 new = &((*new)->rb_right);
4278 }
4279
4280 rb_link_node(&new_tlink->tl_rbnode, parent, new);
4281 rb_insert_color(&new_tlink->tl_rbnode, root);
4282}
4283
Jeff Layton9d002df2010-10-06 19:51:11 -04004284/*
4285 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
4286 * current task.
4287 *
4288 * If the superblock doesn't refer to a multiuser mount, then just return
4289 * the master tcon for the mount.
4290 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05304291 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04004292 * exists, then check to see if it's pending construction. If it is then wait
4293 * for construction to complete. Once it's no longer pending, check to see if
4294 * it failed and either return an error or retry construction, depending on
4295 * the timeout.
4296 *
4297 * If one doesn't exist then insert a new tcon_link struct into the tree and
4298 * try to construct a new one.
4299 */
4300struct tcon_link *
4301cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
4302{
4303 int ret;
Jeff Laytonb647c352010-10-28 11:16:44 -04004304 uid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04004305 struct tcon_link *tlink, *newtlink;
4306
4307 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
4308 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
4309
4310 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004311 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004312 if (tlink)
4313 cifs_get_tlink(tlink);
4314 spin_unlock(&cifs_sb->tlink_tree_lock);
4315
4316 if (tlink == NULL) {
4317 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4318 if (newtlink == NULL)
4319 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04004320 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04004321 newtlink->tl_tcon = ERR_PTR(-EACCES);
4322 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
4323 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
4324 cifs_get_tlink(newtlink);
4325
Jeff Layton9d002df2010-10-06 19:51:11 -04004326 spin_lock(&cifs_sb->tlink_tree_lock);
4327 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04004328 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04004329 if (tlink) {
4330 cifs_get_tlink(tlink);
4331 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004332 kfree(newtlink);
4333 goto wait_for_construction;
4334 }
Jeff Layton9d002df2010-10-06 19:51:11 -04004335 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04004336 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4337 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04004338 } else {
4339wait_for_construction:
4340 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
4341 cifs_sb_tcon_pending_wait,
4342 TASK_INTERRUPTIBLE);
4343 if (ret) {
4344 cifs_put_tlink(tlink);
4345 return ERR_PTR(ret);
4346 }
4347
4348 /* if it's good, return it */
4349 if (!IS_ERR(tlink->tl_tcon))
4350 return tlink;
4351
4352 /* return error if we tried this already recently */
4353 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
4354 cifs_put_tlink(tlink);
4355 return ERR_PTR(-EACCES);
4356 }
4357
4358 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
4359 goto wait_for_construction;
4360 }
4361
4362 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
4363 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
4364 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
4365
4366 if (IS_ERR(tlink->tl_tcon)) {
4367 cifs_put_tlink(tlink);
4368 return ERR_PTR(-EACCES);
4369 }
4370
4371 return tlink;
4372}
Jeff Layton2de970f2010-10-06 19:51:12 -04004373
4374/*
4375 * periodic workqueue job that scans tcon_tree for a superblock and closes
4376 * out tcons.
4377 */
4378static void
4379cifs_prune_tlinks(struct work_struct *work)
4380{
4381 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
4382 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04004383 struct rb_root *root = &cifs_sb->tlink_tree;
4384 struct rb_node *node = rb_first(root);
4385 struct rb_node *tmp;
4386 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04004387
Jeff Laytonb647c352010-10-28 11:16:44 -04004388 /*
4389 * Because we drop the spinlock in the loop in order to put the tlink
4390 * it's not guarded against removal of links from the tree. The only
4391 * places that remove entries from the tree are this function and
4392 * umounts. Because this function is non-reentrant and is canceled
4393 * before umount can proceed, this is safe.
4394 */
4395 spin_lock(&cifs_sb->tlink_tree_lock);
4396 node = rb_first(root);
4397 while (node != NULL) {
4398 tmp = node;
4399 node = rb_next(tmp);
4400 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
4401
4402 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
4403 atomic_read(&tlink->tl_count) != 0 ||
4404 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
4405 continue;
4406
4407 cifs_get_tlink(tlink);
4408 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4409 rb_erase(tmp, root);
4410
Jeff Layton2de970f2010-10-06 19:51:12 -04004411 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04004412 cifs_put_tlink(tlink);
4413 spin_lock(&cifs_sb->tlink_tree_lock);
4414 }
4415 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04004416
Jeff Laytonda472fc2012-03-23 14:40:53 -04004417 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04004418 TLINK_IDLE_EXPIRE);
4419}