blob: 0f69b311d3fc8a9893b0cb5541059ff32754ac30 [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>
Steve French0e2beda2009-01-30 21:24:41 +000040#include <net/ipv6.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include "cifspdu.h"
42#include "cifsglob.h"
43#include "cifsproto.h"
44#include "cifs_unicode.h"
45#include "cifs_debug.h"
46#include "cifs_fs_sb.h"
47#include "ntlmssp.h"
48#include "nterr.h"
49#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053050#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52#define CIFS_PORT 445
53#define RFC1001_PORT 139
54
Jeff Laytonc74093b2011-01-11 07:24:23 -050055/* SMB echo "timeout" -- FIXME: tunable? */
56#define SMB_ECHO_INTERVAL (60 * HZ)
57
Linus Torvalds1da177e2005-04-16 15:20:36 -070058extern mempool_t *cifs_req_poolp;
59
Jeff Layton2de970f2010-10-06 19:51:12 -040060/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040061#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040062#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040063
Pavel Shilovskya9f1b852010-12-13 19:08:35 +030064static int ip_connect(struct TCP_Server_Info *server);
65static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -040066static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -040067static void cifs_prune_tlinks(struct work_struct *work);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -040068static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
69 const char *devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Jeff Laytond5c56052008-12-01 18:42:33 -050071/*
72 * cifs tcp session reconnection
73 *
74 * mark tcp session as reconnecting so temporarily locked
75 * mark all smb sessions as reconnecting for tcp session
76 * reconnect tcp session
77 * wake up waiters on reconnection? - (not needed currently)
78 */
Steve French2cd646a2006-09-28 19:43:08 +000079static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070080cifs_reconnect(struct TCP_Server_Info *server)
81{
82 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -050083 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +000084 struct cifs_ses *ses;
85 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +000086 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -040087 struct list_head retry_list;
Steve French50c2f752007-07-13 00:33:32 +000088
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +000090 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +000091 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 next time through the loop */
93 spin_unlock(&GlobalMid_Lock);
94 return rc;
95 } else
96 server->tcpStatus = CifsNeedReconnect;
97 spin_unlock(&GlobalMid_Lock);
98 server->maxBuf = 0;
99
Joe Perchesb6b38f72010-04-21 03:50:45 +0000100 cFYI(1, "Reconnecting tcp session");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102 /* before reconnecting the tcp session, mark the smb session (uid)
103 and the tid bad so they are not used until reconnected */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500104 cFYI(1, "%s: marking sessions and tcons for reconnect", __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530105 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500106 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000107 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500108 ses->need_reconnect = true;
109 ses->ipc_tid = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500110 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000111 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500112 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530115 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 /* do not want to be sending data on a socket we are freeing */
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500118 cFYI(1, "%s: tearing down socket", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500119 mutex_lock(&server->srv_mutex);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000120 if (server->ssocket) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000121 cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
122 server->ssocket->flags);
Trond Myklebust91cf45f2007-11-12 18:10:39 -0800123 kernel_sock_shutdown(server->ssocket, SHUT_WR);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000124 cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx",
Steve French467a8f82007-06-27 22:41:32 +0000125 server->ssocket->state,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000126 server->ssocket->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 sock_release(server->ssocket);
128 server->ssocket = NULL;
129 }
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -0500130 server->sequence_number = 0;
131 server->session_estab = false;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -0500132 kfree(server->session_key.response);
133 server->session_key.response = NULL;
134 server->session_key.len = 0;
Steve Frenchfda35942011-01-20 18:06:34 +0000135 server->lstrp = jiffies;
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500136 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500138 /* mark submitted MIDs for retry and issue callback */
Jeff Layton3c1105d2011-05-22 07:09:13 -0400139 INIT_LIST_HEAD(&retry_list);
140 cFYI(1, "%s: moving mids to private list", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 spin_lock(&GlobalMid_Lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500142 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
143 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
144 if (mid_entry->midState == MID_REQUEST_SUBMITTED)
Steve Frenchad8b15f2008-08-08 21:10:16 +0000145 mid_entry->midState = MID_RETRY_NEEDED;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400146 list_move(&mid_entry->qhead, &retry_list);
147 }
148 spin_unlock(&GlobalMid_Lock);
149
150 cFYI(1, "%s: issuing mid callbacks", __func__);
151 list_for_each_safe(tmp, tmp2, &retry_list) {
152 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500153 list_del_init(&mid_entry->qhead);
154 mid_entry->callback(mid_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400157 do {
Steve French6c3d8902006-07-31 22:46:20 +0000158 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300159
160 /* we should try only the port we connected to before */
161 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000162 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000163 cFYI(1, "reconnect error %d", rc);
Steve French0cb766a2005-04-28 22:41:11 -0700164 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 } else {
166 atomic_inc(&tcpSesReconnectCount);
167 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000168 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000169 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000170 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400172 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 return rc;
175}
176
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000177/*
Steve Frenche4eb2952005-04-28 22:41:09 -0700178 return codes:
179 0 not a transact2, or all data present
180 >0 transact2 with that much data missing
181 -EINVAL = invalid transact2
182
183 */
Jeff Laytonc974bef2011-10-11 06:41:32 -0400184static int check2ndT2(struct smb_hdr *pSMB)
Steve Frenche4eb2952005-04-28 22:41:09 -0700185{
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000186 struct smb_t2_rsp *pSMBt;
Steve Frenche4eb2952005-04-28 22:41:09 -0700187 int remaining;
Jeff Layton26ec2542011-01-20 13:36:51 -0500188 __u16 total_data_size, data_in_this_rsp;
Steve Frenche4eb2952005-04-28 22:41:09 -0700189
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000190 if (pSMB->Command != SMB_COM_TRANSACTION2)
Steve Frenche4eb2952005-04-28 22:41:09 -0700191 return 0;
192
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000193 /* check for plausible wct, bcc and t2 data and parm sizes */
194 /* check for parm and data offset going beyond end of smb */
195 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
Joe Perchesb6b38f72010-04-21 03:50:45 +0000196 cFYI(1, "invalid transact2 word count");
Steve Frenche4eb2952005-04-28 22:41:09 -0700197 return -EINVAL;
198 }
199
200 pSMBt = (struct smb_t2_rsp *)pSMB;
201
Jeff Layton26ec2542011-01-20 13:36:51 -0500202 total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
203 data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700204
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400205 if (total_data_size == data_in_this_rsp)
Steve Frenche4eb2952005-04-28 22:41:09 -0700206 return 0;
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400207 else if (total_data_size < data_in_this_rsp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000208 cFYI(1, "total data %d smaller than data in frame %d",
209 total_data_size, data_in_this_rsp);
Steve Frenche4eb2952005-04-28 22:41:09 -0700210 return -EINVAL;
Steve Frenche4eb2952005-04-28 22:41:09 -0700211 }
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400212
213 remaining = total_data_size - data_in_this_rsp;
214
215 cFYI(1, "missing %d bytes from transact2, check next response",
216 remaining);
Jeff Laytonc974bef2011-10-11 06:41:32 -0400217 if (total_data_size > CIFSMaxBufSize) {
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400218 cERROR(1, "TotalDataSize %d is over maximum buffer %d",
Jeff Laytonc974bef2011-10-11 06:41:32 -0400219 total_data_size, CIFSMaxBufSize);
Jeff Laytonc0c7b902011-03-31 17:32:54 -0400220 return -EINVAL;
221 }
222 return remaining;
Steve Frenche4eb2952005-04-28 22:41:09 -0700223}
224
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000225static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
Steve Frenche4eb2952005-04-28 22:41:09 -0700226{
227 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
228 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000229 char *data_area_of_target;
230 char *data_area_of_buf2;
Jeff Layton26ec2542011-01-20 13:36:51 -0500231 int remaining;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400232 unsigned int byte_count, total_in_buf;
233 __u16 total_data_size, total_in_buf2;
Steve Frenche4eb2952005-04-28 22:41:09 -0700234
Jeff Layton26ec2542011-01-20 13:36:51 -0500235 total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700236
Jeff Layton26ec2542011-01-20 13:36:51 -0500237 if (total_data_size !=
238 get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount))
Joe Perchesb6b38f72010-04-21 03:50:45 +0000239 cFYI(1, "total data size of primary and secondary t2 differ");
Steve Frenche4eb2952005-04-28 22:41:09 -0700240
Jeff Layton26ec2542011-01-20 13:36:51 -0500241 total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
Steve Frenche4eb2952005-04-28 22:41:09 -0700242
243 remaining = total_data_size - total_in_buf;
Steve French50c2f752007-07-13 00:33:32 +0000244
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000245 if (remaining < 0)
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400246 return -EPROTO;
Steve Frenche4eb2952005-04-28 22:41:09 -0700247
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000248 if (remaining == 0) /* nothing to do, ignore */
Steve Frenche4eb2952005-04-28 22:41:09 -0700249 return 0;
Steve French50c2f752007-07-13 00:33:32 +0000250
Jeff Layton26ec2542011-01-20 13:36:51 -0500251 total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000252 if (remaining < total_in_buf2) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000253 cFYI(1, "transact2 2nd response contains too much data");
Steve Frenche4eb2952005-04-28 22:41:09 -0700254 }
255
256 /* find end of first SMB data area */
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000257 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
Jeff Layton26ec2542011-01-20 13:36:51 -0500258 get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
Steve Frenche4eb2952005-04-28 22:41:09 -0700259 /* validate target area */
260
Jeff Layton26ec2542011-01-20 13:36:51 -0500261 data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol +
262 get_unaligned_le16(&pSMB2->t2_rsp.DataOffset);
Steve Frenche4eb2952005-04-28 22:41:09 -0700263
264 data_area_of_target += total_in_buf;
265
266 /* copy second buffer into end of first buffer */
Steve Frenche4eb2952005-04-28 22:41:09 -0700267 total_in_buf += total_in_buf2;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400268 /* is the result too big for the field? */
269 if (total_in_buf > USHRT_MAX)
270 return -EPROTO;
Jeff Layton26ec2542011-01-20 13:36:51 -0500271 put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400272
273 /* fix up the BCC */
Jeff Layton820a8032011-05-04 08:05:26 -0400274 byte_count = get_bcc(pTargetSMB);
Steve Frenche4eb2952005-04-28 22:41:09 -0700275 byte_count += total_in_buf2;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400276 /* is the result too big for the field? */
277 if (byte_count > USHRT_MAX)
278 return -EPROTO;
Jeff Layton820a8032011-05-04 08:05:26 -0400279 put_bcc(byte_count, pTargetSMB);
Steve Frenche4eb2952005-04-28 22:41:09 -0700280
Steve Frenchbe8e3b02011-04-29 05:40:20 +0000281 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
Steve Frenche4eb2952005-04-28 22:41:09 -0700282 byte_count += total_in_buf2;
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400283 /* don't allow buffer to overflow */
284 if (byte_count > CIFSMaxBufSize)
285 return -ENOBUFS;
Steve Frenchbe8e3b02011-04-29 05:40:20 +0000286 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
Steve Frenche4eb2952005-04-28 22:41:09 -0700287
Jeff Layton2a2047bc2011-04-27 13:29:49 -0400288 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
289
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000290 if (remaining == total_in_buf2) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000291 cFYI(1, "found the last secondary response");
Steve Frenche4eb2952005-04-28 22:41:09 -0700292 return 0; /* we are done */
293 } else /* more responses to go */
294 return 1;
Steve Frenche4eb2952005-04-28 22:41:09 -0700295}
296
Jeff Laytonc74093b2011-01-11 07:24:23 -0500297static void
298cifs_echo_request(struct work_struct *work)
299{
300 int rc;
301 struct TCP_Server_Info *server = container_of(work,
302 struct TCP_Server_Info, echo.work);
303
Jeff Layton247ec9b2011-02-04 17:09:50 -0500304 /*
Jeff Layton195291e2011-02-09 12:01:42 -0500305 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is
306 * done, which is indicated by maxBuf != 0. Also, no need to ping if
307 * we got a response recently
Jeff Layton247ec9b2011-02-04 17:09:50 -0500308 */
Jeff Layton195291e2011-02-09 12:01:42 -0500309 if (server->maxBuf == 0 ||
Jeff Layton247ec9b2011-02-04 17:09:50 -0500310 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500311 goto requeue_echo;
312
313 rc = CIFSSMBEcho(server);
314 if (rc)
315 cFYI(1, "Unable to send echo request to server: %s",
316 server->hostname);
317
318requeue_echo:
319 queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
320}
321
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400322static bool
323allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size,
324 bool is_large_buf)
325{
326 char *bbuf = *bigbuf, *sbuf = *smallbuf;
327
328 if (bbuf == NULL) {
329 bbuf = (char *)cifs_buf_get();
330 if (!bbuf) {
331 cERROR(1, "No memory for large SMB response");
332 msleep(3000);
333 /* retry will check if exiting */
334 return false;
335 }
336 } else if (is_large_buf) {
337 /* we are reusing a dirty large buf, clear its start */
338 memset(bbuf, 0, size);
339 }
340
341 if (sbuf == NULL) {
342 sbuf = (char *)cifs_small_buf_get();
343 if (!sbuf) {
344 cERROR(1, "No memory for SMB response");
345 msleep(1000);
346 /* retry will check if exiting */
347 return false;
348 }
349 /* beginning of smb buffer is cleared in our buf_get */
350 } else {
351 /* if existing small buf clear beginning */
352 memset(sbuf, 0, size);
353 }
354
355 *bigbuf = bbuf;
356 *smallbuf = sbuf;
357
358 return true;
359}
360
Jeff Laytonba749e62011-10-11 06:41:32 -0400361static bool
362server_unresponsive(struct TCP_Server_Info *server)
363{
364 if (echo_retries > 0 && server->tcpStatus == CifsGood &&
365 time_after(jiffies, server->lstrp +
366 (echo_retries * SMB_ECHO_INTERVAL))) {
367 cERROR(1, "Server %s has not responded in %d seconds. "
368 "Reconnecting...", server->hostname,
369 (echo_retries * SMB_ECHO_INTERVAL / HZ));
370 cifs_reconnect(server);
371 wake_up(&server->response_q);
372 return true;
373 }
374
375 return false;
376}
377
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400378/*
379 * kvec_array_init - clone a kvec array, and advance into it
380 * @new: pointer to memory for cloned array
381 * @iov: pointer to original array
382 * @nr_segs: number of members in original array
383 * @bytes: number of bytes to advance into the cloned array
384 *
385 * This function will copy the array provided in iov to a section of memory
386 * and advance the specified number of bytes into the new array. It returns
387 * the number of segments in the new array. "new" must be at least as big as
388 * the original iov array.
389 */
390static unsigned int
391kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs,
392 size_t bytes)
393{
394 size_t base = 0;
395
396 while (bytes || !iov->iov_len) {
397 int copy = min(bytes, iov->iov_len);
398
399 bytes -= copy;
400 base += copy;
401 if (iov->iov_len == base) {
402 iov++;
403 nr_segs--;
404 base = 0;
405 }
406 }
407 memcpy(new, iov, sizeof(*iov) * nr_segs);
408 new->iov_base += base;
409 new->iov_len -= base;
410 return nr_segs;
411}
412
Jeff Layton1041e3f2011-10-19 15:28:27 -0400413static struct kvec *
414get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs)
415{
416 struct kvec *new_iov;
417
418 if (server->iov && nr_segs <= server->nr_iov)
419 return server->iov;
420
421 /* not big enough -- allocate a new one and release the old */
422 new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS);
423 if (new_iov) {
424 kfree(server->iov);
425 server->iov = new_iov;
426 server->nr_iov = nr_segs;
427 }
428 return new_iov;
429}
430
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431static int
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400432readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig,
433 unsigned int nr_segs, unsigned int to_read)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400434{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400435 int length = 0;
436 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400437 unsigned int segs;
Jeff Laytone831e6c2011-10-11 06:41:32 -0400438 struct msghdr smb_msg;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400439 struct kvec *iov;
440
Jeff Layton1041e3f2011-10-19 15:28:27 -0400441 iov = get_server_iovec(server, nr_segs);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400442 if (!iov)
443 return -ENOMEM;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400444
Jeff Laytone831e6c2011-10-11 06:41:32 -0400445 smb_msg.msg_control = NULL;
446 smb_msg.msg_controllen = 0;
447
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400448 for (total_read = 0; to_read; total_read += length, to_read -= length) {
Jeff Laytonba749e62011-10-11 06:41:32 -0400449 if (server_unresponsive(server)) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400450 total_read = -EAGAIN;
Jeff Laytonba749e62011-10-11 06:41:32 -0400451 break;
452 }
453
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400454 segs = kvec_array_init(iov, iov_orig, nr_segs, total_read);
455
456 length = kernel_recvmsg(server->ssocket, &smb_msg,
457 iov, segs, to_read, 0);
458
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400459 if (server->tcpStatus == CifsExiting) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400460 total_read = -ESHUTDOWN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400461 break;
462 } else if (server->tcpStatus == CifsNeedReconnect) {
463 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400464 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400465 break;
466 } else if (length == -ERESTARTSYS ||
467 length == -EAGAIN ||
468 length == -EINTR) {
469 /*
470 * Minimum sleep to prevent looping, allowing socket
471 * to clear and app threads to set tcpStatus
472 * CifsNeedReconnect if server hung.
473 */
474 usleep_range(1000, 2000);
475 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400476 continue;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400477 } else if (length <= 0) {
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400478 cFYI(1, "Received no data or error: expecting %d "
479 "got %d", to_read, length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400480 cifs_reconnect(server);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400481 total_read = -EAGAIN;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400482 break;
483 }
484 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400485 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400486}
487
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400488static int
489read_from_socket(struct TCP_Server_Info *server, char *buf,
490 unsigned int to_read)
491{
492 struct kvec iov;
493
494 iov.iov_base = buf;
495 iov.iov_len = to_read;
496
497 return readv_from_socket(server, &iov, 1, to_read);
498}
499
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400500static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400501is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400502{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400503 /*
504 * The first byte big endian of the length field,
505 * is actually not part of the length but the type
506 * with the most common, zero, as regular data.
507 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400508 switch (type) {
509 case RFC1002_SESSION_MESSAGE:
510 /* Regular SMB response */
511 return true;
512 case RFC1002_SESSION_KEEP_ALIVE:
513 cFYI(1, "RFC 1002 session keep alive");
514 break;
515 case RFC1002_POSITIVE_SESSION_RESPONSE:
516 cFYI(1, "RFC 1002 positive session response");
517 break;
518 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400519 /*
520 * We get this from Windows 98 instead of an error on
521 * SMB negprot response.
522 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400523 cFYI(1, "RFC 1002 negative session response");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400524 /* give server a second to clean up */
525 msleep(1000);
526 /*
527 * Always try 445 first on reconnect since we get NACK
528 * on some if we ever connected to port 139 (the NACK
529 * is since we do not begin with RFC1001 session
530 * initialize frame).
531 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400532 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400533 cifs_reconnect(server);
534 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400535 break;
536 default:
537 cERROR(1, "RFC 1002 unknown response type 0x%x", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400538 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400539 }
540
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400541 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400542}
543
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400544static struct mid_q_entry *
Jeff Laytonea1f4502011-10-19 15:29:05 -0400545find_mid(struct TCP_Server_Info *server, struct smb_hdr *buf)
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400546{
Jeff Laytonea1f4502011-10-19 15:29:05 -0400547 struct mid_q_entry *mid;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400548
549 spin_lock(&GlobalMid_Lock);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400550 list_for_each_entry(mid, &server->pending_mid_q, qhead) {
551 if (mid->mid == buf->Mid &&
552 mid->midState == MID_REQUEST_SUBMITTED &&
553 mid->command == buf->Command) {
554 spin_unlock(&GlobalMid_Lock);
555 return mid;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400556 }
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400557 }
558 spin_unlock(&GlobalMid_Lock);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400559 return NULL;
560}
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400561
Jeff Laytonea1f4502011-10-19 15:29:05 -0400562static void
563dequeue_mid(struct mid_q_entry *mid, int malformed)
564{
565#ifdef CONFIG_CIFS_STATS2
566 mid->when_received = jiffies;
567#endif
568 spin_lock(&GlobalMid_Lock);
569 if (!malformed)
570 mid->midState = MID_RESPONSE_RECEIVED;
571 else
572 mid->midState = MID_RESPONSE_MALFORMED;
573 list_del_init(&mid->qhead);
574 spin_unlock(&GlobalMid_Lock);
575}
576
577static struct mid_q_entry *
578find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf,
579 int *malformed, bool is_large_buf, bool *is_multi_rsp,
580 char **bigbuf)
581{
582 struct mid_q_entry *mid = NULL;
583
584 mid = find_mid(server, buf);
585 if (!mid)
586 return mid;
587
588 if (*malformed == 0 && check2ndT2(buf) > 0) {
589 /* We have a multipart transact2 resp */
590 *is_multi_rsp = true;
591 if (mid->resp_buf) {
592 /* merge response - fix up 1st*/
593 *malformed = coalesce_t2(buf, mid->resp_buf);
594 if (*malformed > 0) {
595 *malformed = 0;
596 mid->multiRsp = true;
597 return NULL;
598 }
599 /* All parts received or packet is malformed. */
600 mid->multiEnd = true;
601 goto multi_t2_fnd;
602 }
603 if (!is_large_buf) {
604 /*FIXME: switch to already allocated largebuf?*/
605 cERROR(1, "1st trans2 resp needs bigbuf");
606 } else {
607 /* Have first buffer */
608 mid->resp_buf = buf;
609 mid->largeBuf = true;
610 *bigbuf = NULL;
611 }
612 return mid;
613 }
614 mid->resp_buf = buf;
615 mid->largeBuf = is_large_buf;
616multi_t2_fnd:
617 dequeue_mid(mid, *malformed);
618 return mid;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400619}
620
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400621static void clean_demultiplex_info(struct TCP_Server_Info *server)
622{
623 int length;
624
625 /* take it off the list, if it's not already */
626 spin_lock(&cifs_tcp_ses_lock);
627 list_del_init(&server->tcp_ses_list);
628 spin_unlock(&cifs_tcp_ses_lock);
629
630 spin_lock(&GlobalMid_Lock);
631 server->tcpStatus = CifsExiting;
632 spin_unlock(&GlobalMid_Lock);
633 wake_up_all(&server->response_q);
634
635 /*
636 * Check if we have blocked requests that need to free. Note that
637 * cifs_max_pending is normally 50, but can be set at module install
638 * time to as little as two.
639 */
640 spin_lock(&GlobalMid_Lock);
641 if (atomic_read(&server->inFlight) >= cifs_max_pending)
642 atomic_set(&server->inFlight, cifs_max_pending - 1);
643 /*
644 * We do not want to set the max_pending too low or we could end up
645 * with the counter going negative.
646 */
647 spin_unlock(&GlobalMid_Lock);
648 /*
649 * Although there should not be any requests blocked on this queue it
650 * can not hurt to be paranoid and try to wake up requests that may
651 * haven been blocked when more than 50 at time were on the wire to the
652 * same server - they now will see the session is in exit state and get
653 * out of SendReceive.
654 */
655 wake_up_all(&server->request_q);
656 /* give those requests time to exit */
657 msleep(125);
658
659 if (server->ssocket) {
660 sock_release(server->ssocket);
661 server->ssocket = NULL;
662 }
663
664 if (!list_empty(&server->pending_mid_q)) {
665 struct list_head dispose_list;
666 struct mid_q_entry *mid_entry;
667 struct list_head *tmp, *tmp2;
668
669 INIT_LIST_HEAD(&dispose_list);
670 spin_lock(&GlobalMid_Lock);
671 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
672 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
673 cFYI(1, "Clearing mid 0x%x", mid_entry->mid);
674 mid_entry->midState = MID_SHUTDOWN;
675 list_move(&mid_entry->qhead, &dispose_list);
676 }
677 spin_unlock(&GlobalMid_Lock);
678
679 /* now walk dispose list and issue callbacks */
680 list_for_each_safe(tmp, tmp2, &dispose_list) {
681 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
682 cFYI(1, "Callback mid 0x%x", mid_entry->mid);
683 list_del_init(&mid_entry->qhead);
684 mid_entry->callback(mid_entry);
685 }
686 /* 1/8th of sec is more than enough time for them to exit */
687 msleep(125);
688 }
689
690 if (!list_empty(&server->pending_mid_q)) {
691 /*
692 * mpx threads have not exited yet give them at least the smb
693 * send timeout time for long ops.
694 *
695 * Due to delays on oplock break requests, we need to wait at
696 * least 45 seconds before giving up on a request getting a
697 * response and going ahead and killing cifsd.
698 */
699 cFYI(1, "Wait for exit from demultiplex thread");
700 msleep(46000);
701 /*
702 * If threads still have not exited they are probably never
703 * coming home not much else we can do but free the memory.
704 */
705 }
706
707 kfree(server->hostname);
Jeff Layton1041e3f2011-10-19 15:28:27 -0400708 kfree(server->iov);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400709 kfree(server);
710
711 length = atomic_dec_return(&tcpSesAllocCount);
712 if (length > 0)
713 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
714 GFP_KERNEL);
715}
716
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400717static int
Al Viro7c97c202011-06-21 08:51:28 -0400718cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719{
720 int length;
Al Viro7c97c202011-06-21 08:51:28 -0400721 struct TCP_Server_Info *server = p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 unsigned int pdu_length, total_read;
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400723 char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 struct smb_hdr *smb_buffer = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 struct task_struct *task_to_wake = NULL;
726 struct mid_q_entry *mid_entry;
Steve French4b18f2a2008-04-29 00:06:05 +0000727 bool isLargeBuf = false;
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400728 bool isMultiRsp = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 current->flags |= PF_MEMALLOC;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000731 cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -0400732
733 length = atomic_inc_return(&tcpSesAllocCount);
734 if (length > 1)
Steve French26f57362007-08-30 22:09:15 +0000735 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
736 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Rafael J. Wysocki83144182007-07-17 04:03:35 -0700738 set_freezable();
Jeff Layton469ee612008-10-16 18:46:39 +0000739 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -0700740 if (try_to_freeze())
741 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700742
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400743 if (!allocate_buffers(&bigbuf, &smallbuf,
744 sizeof(struct smb_hdr), isLargeBuf))
745 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -0700746
Steve French4b18f2a2008-04-29 00:06:05 +0000747 isLargeBuf = false;
748 isMultiRsp = false;
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400749 smb_buffer = (struct smb_hdr *)smallbuf;
750 buf = smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +0000751 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +0000752
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400753 length = read_from_socket(server, buf, pdu_length);
754 if (length < 0)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400755 continue;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400756 total_read = length;
Steve French67010fb2005-04-28 22:41:09 -0700757
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400758 /*
759 * The right amount was read from socket - 4 bytes,
760 * so we can now interpret the length field.
761 */
Steve Frenchbe8e3b02011-04-29 05:40:20 +0000762 pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);
Steve French46810cb2005-04-28 22:41:09 -0700763
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400764 cFYI(1, "RFC1002 header 0x%x", pdu_length);
765 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000766 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -0700767
Jeff Layton89482a52011-10-19 15:28:57 -0400768 /* make sure we have enough to get to the MID */
769 if (pdu_length < sizeof(struct smb_hdr) - 1 - 4) {
770 cERROR(1, "SMB response too short (%u bytes)",
771 pdu_length);
772 cifs_reconnect(server);
773 wake_up(&server->response_q);
774 continue;
775 }
776
777 /* read down to the MID */
778 length = read_from_socket(server, buf + 4,
779 sizeof(struct smb_hdr) - 1 - 4);
780 if (length < 0)
781 continue;
782 total_read += length;
783
784 if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
785 cERROR(1, "SMB response too long (%u bytes)",
786 pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400787 cifs_reconnect(server);
788 wake_up(&server->response_q);
789 continue;
790 }
791
Steve Frenche4eb2952005-04-28 22:41:09 -0700792 /* else length ok */
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000793 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
Steve French4b18f2a2008-04-29 00:06:05 +0000794 isLargeBuf = true;
Jeff Layton89482a52011-10-19 15:28:57 -0400795 memcpy(bigbuf, smallbuf, total_read);
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400796 smb_buffer = (struct smb_hdr *)bigbuf;
797 buf = bigbuf;
Steve Frenche4eb2952005-04-28 22:41:09 -0700798 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400799
Jeff Layton89482a52011-10-19 15:28:57 -0400800 /* now read the rest */
801 length = read_from_socket(server,
802 buf + sizeof(struct smb_hdr) - 1,
803 pdu_length - sizeof(struct smb_hdr) + 1 + 4);
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400804 if (length < 0)
Steve Frenche4eb2952005-04-28 22:41:09 -0700805 continue;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400806 total_read += length;
Steve French50c2f752007-07-13 00:33:32 +0000807
Jeff Layton9587fcf2011-02-01 08:40:43 -0500808 dump_smb(smb_buffer, total_read);
Jeff Layton71823ba2011-02-10 08:03:50 -0500809
810 /*
811 * We know that we received enough to get to the MID as we
812 * checked the pdu_length earlier. Now check to see
813 * if the rest of the header is OK. We borrow the length
814 * var for the rest of the loop to avoid a new stack var.
815 *
816 * 48 bytes is enough to display the header and a little bit
817 * into the payload for debugging purposes.
818 */
819 length = checkSMB(smb_buffer, smb_buffer->Mid, total_read);
820 if (length != 0)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400821 cifs_dump_mem("Bad SMB: ", buf,
822 min_t(unsigned int, total_read, 48));
Steve Frenche4eb2952005-04-28 22:41:09 -0700823
Steve Frenchfda35942011-01-20 18:06:34 +0000824 server->lstrp = jiffies;
825
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400826 mid_entry = find_cifs_mid(server, smb_buffer, &length,
827 isLargeBuf, &isMultiRsp, &bigbuf);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500828 if (mid_entry != NULL) {
Jeff Layton3c1105d2011-05-22 07:09:13 -0400829 mid_entry->callback(mid_entry);
Steve Frenchcd634992005-04-28 22:41:10 -0700830 /* Was previous buf put in mpx struct for multi-rsp? */
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000831 if (!isMultiRsp) {
Steve Frenchcd634992005-04-28 22:41:10 -0700832 /* smb buffer will be freed by user thread */
Steve French26f57362007-08-30 22:09:15 +0000833 if (isLargeBuf)
Steve Frenchcd634992005-04-28 22:41:10 -0700834 bigbuf = NULL;
Steve French26f57362007-08-30 22:09:15 +0000835 else
Steve Frenchcd634992005-04-28 22:41:10 -0700836 smallbuf = NULL;
837 }
Jeff Layton71823ba2011-02-10 08:03:50 -0500838 } else if (length != 0) {
839 /* response sanity checks failed */
840 continue;
Steve French4b18f2a2008-04-29 00:06:05 +0000841 } else if (!is_valid_oplock_break(smb_buffer, server) &&
842 !isMultiRsp) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000843 cERROR(1, "No task to wake, unknown frame received! "
Jeff Layton80975312011-01-11 07:24:02 -0500844 "NumMids %d", atomic_read(&midCount));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400845 cifs_dump_mem("Received Data is: ", buf,
Steve French70ca7342005-09-22 16:32:06 -0700846 sizeof(struct smb_hdr));
Steve French39798772006-05-31 22:40:51 +0000847#ifdef CONFIG_CIFS_DEBUG2
848 cifs_dump_detail(smb_buffer);
849 cifs_dump_mids(server);
850#endif /* CIFS_DEBUG2 */
Steve French50c2f752007-07-13 00:33:32 +0000851
Steve Frenche4eb2952005-04-28 22:41:09 -0700852 }
853 } /* end while !EXITING */
854
Justin P. Mattockfd62cb72011-02-24 22:15:02 -0800855 /* buffer usually freed in free_mid - need to free it here on exit */
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +0000856 cifs_buf_release(bigbuf);
857 if (smallbuf) /* no sense logging a debug message if NULL */
Steve Frenchb8643e12005-04-28 22:41:07 -0700858 cifs_small_buf_release(smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -0400860 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400861 clean_demultiplex_info(server);
Steve French50c2f752007-07-13 00:33:32 +0000862
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -0400863 /* if server->tsk was NULL then wait for a signal before exiting */
864 if (!task_to_wake) {
865 set_current_state(TASK_INTERRUPTIBLE);
866 while (!signal_pending(current)) {
867 schedule();
868 set_current_state(TASK_INTERRUPTIBLE);
869 }
870 set_current_state(TASK_RUNNING);
871 }
872
Jeff Layton0468a2c2008-12-01 07:09:35 -0500873 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
Jeff Laytonc359cf32007-11-16 22:22:06 +0000876/* extract the host portion of the UNC string */
877static char *
878extract_hostname(const char *unc)
879{
880 const char *src;
881 char *dst, *delim;
882 unsigned int len;
883
884 /* skip double chars at beginning of string */
885 /* BB: check validity of these bytes? */
886 src = unc + 2;
887
888 /* delimiter between hostname and sharename is always '\\' now */
889 delim = strchr(src, '\\');
890 if (!delim)
891 return ERR_PTR(-EINVAL);
892
893 len = delim - src;
894 dst = kmalloc((len + 1), GFP_KERNEL);
895 if (dst == NULL)
896 return ERR_PTR(-ENOMEM);
897
898 memcpy(dst, src, len);
899 dst[len] = '\0';
900
901 return dst;
902}
903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904static int
Sean Finneyb9468452011-04-11 13:19:32 +0000905cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve French50c2f752007-07-13 00:33:32 +0000906 struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907{
Pavel Shilovsky4906e502011-04-14 22:00:56 +0400908 char *value, *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +0400909 char *mountdata_copy = NULL, *options;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500910 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 unsigned int temp_len, i, j;
912 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -0400913 short int override_uid = -1;
914 short int override_gid = -1;
915 bool uid_specified = false;
916 bool gid_specified = false;
Jeff Layton88463992010-11-22 15:31:03 -0500917 char *nodename = utsname()->nodename;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
919 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +0000920 separator[1] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
Jeff Layton88463992010-11-22 15:31:03 -0500922 /*
923 * does not have to be perfect mapping since field is
924 * informational, only used for servers that do not support
925 * port 445 and it can be overridden at mount time
926 */
Jeff Layton1397f2e2011-01-07 11:30:28 -0500927 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
928 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -0500929 vol->source_rfc1001_name[i] = toupper(nodename[i]);
930
Jeff Layton1397f2e2011-01-07 11:30:28 -0500931 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -0700932 /* null target name indicates to use *SMBSERVR default called name
933 if we end up sending RFC1001 session initialize */
934 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -0400935 vol->cred_uid = current_uid();
936 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +1100937 vol->linux_gid = current_gid();
Jeff Laytonf55ed1a2009-05-26 16:28:11 -0400938
939 /* default to only allowing write access to owner of the mount */
940 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
942 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -0700943 /* default is always to request posix paths. */
944 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -0400945 /* default to using server inode numbers where available */
946 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -0700947
Suresh Jayaraman6d20e842010-12-01 14:42:28 +0530948 vol->actimeo = CIFS_DEF_ACTIMEO;
949
Sean Finneyb9468452011-04-11 13:19:32 +0000950 if (!mountdata)
951 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
Sean Finneyb9468452011-04-11 13:19:32 +0000953 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
954 if (!mountdata_copy)
955 goto cifs_parse_mount_err;
956
957 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +0400958 end = options + strlen(options);
Steve French50c2f752007-07-13 00:33:32 +0000959 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000960 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 separator[0] = options[4];
962 options += 5;
963 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000964 cFYI(1, "Null separator not allowed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 }
966 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -0500967 vol->backupuid_specified = false; /* no backup intent for a user */
968 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +0000969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 while ((data = strsep(&options, separator)) != NULL) {
971 if (!*data)
972 continue;
973 if ((value = strchr(data, '=')) != NULL)
974 *value++ = '\0';
975
Steve French50c2f752007-07-13 00:33:32 +0000976 /* Have to parse this before we parse for "user" */
977 if (strnicmp(data, "user_xattr", 10) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 vol->no_xattr = 0;
Steve French50c2f752007-07-13 00:33:32 +0000979 } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 vol->no_xattr = 1;
981 } else if (strnicmp(data, "user", 4) == 0) {
Steve French4b952a92006-10-30 21:46:13 +0000982 if (!value) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 printk(KERN_WARNING
984 "CIFS: invalid or missing username\n");
Sean Finneyb9468452011-04-11 13:19:32 +0000985 goto cifs_parse_mount_err;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000986 } else if (!*value) {
Steve French4b952a92006-10-30 21:46:13 +0000987 /* null user, ie anonymous, authentication */
988 vol->nullauth = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
Steve French8727c8a2011-02-25 01:11:56 -0600990 if (strnlen(value, MAX_USERNAME_SIZE) <
991 MAX_USERNAME_SIZE) {
Sean Finneyb9468452011-04-11 13:19:32 +0000992 vol->username = kstrdup(value, GFP_KERNEL);
993 if (!vol->username) {
994 printk(KERN_WARNING "CIFS: no memory "
995 "for username\n");
996 goto cifs_parse_mount_err;
997 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 } else {
999 printk(KERN_WARNING "CIFS: username too long\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001000 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002 } else if (strnicmp(data, "pass", 4) == 0) {
1003 if (!value) {
1004 vol->password = NULL;
1005 continue;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001006 } else if (value[0] == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 /* check if string begins with double comma
1008 since that would mean the password really
1009 does start with a comma, and would not
1010 indicate an empty string */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001011 if (value[1] != separator[0]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 vol->password = NULL;
1013 continue;
1014 }
1015 }
1016 temp_len = strlen(value);
1017 /* removed password length check, NTLM passwords
1018 can be arbitrarily long */
1019
Steve French50c2f752007-07-13 00:33:32 +00001020 /* if comma in password, the string will be
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 prematurely null terminated. Commas in password are
1022 specified across the cifs mount interface by a double
1023 comma ie ,, and a comma used as in other cases ie ','
1024 as a parameter delimiter/separator is single and due
1025 to the strsep above is temporarily zeroed. */
1026
1027 /* NB: password legally can have multiple commas and
1028 the only illegal character in a password is null */
1029
Steve French50c2f752007-07-13 00:33:32 +00001030 if ((value[temp_len] == 0) &&
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001031 (value + temp_len < end) &&
Steve French09d1db52005-04-28 22:41:08 -07001032 (value[temp_len+1] == separator[0])) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 /* reinsert comma */
1034 value[temp_len] = separator[0];
Steve French50c2f752007-07-13 00:33:32 +00001035 temp_len += 2; /* move after second comma */
1036 while (value[temp_len] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 if (value[temp_len] == separator[0]) {
Steve French50c2f752007-07-13 00:33:32 +00001038 if (value[temp_len+1] ==
Steve French09d1db52005-04-28 22:41:08 -07001039 separator[0]) {
1040 /* skip second comma */
1041 temp_len++;
Steve French50c2f752007-07-13 00:33:32 +00001042 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 /* single comma indicating start
1044 of next parm */
1045 break;
1046 }
1047 }
1048 temp_len++;
1049 }
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001050 if (value[temp_len] == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 options = NULL;
1052 } else {
1053 value[temp_len] = 0;
1054 /* point option to start of next parm */
1055 options = value + temp_len + 1;
1056 }
Steve French50c2f752007-07-13 00:33:32 +00001057 /* go from value to value + temp_len condensing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 double commas to singles. Note that this ends up
1059 allocating a few bytes too many, which is ok */
Pekka Enberge915fc42005-09-06 15:18:35 -07001060 vol->password = kzalloc(temp_len, GFP_KERNEL);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001061 if (vol->password == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00001062 printk(KERN_WARNING "CIFS: no memory "
1063 "for password\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001064 goto cifs_parse_mount_err;
Steve French433dc242005-04-28 22:41:08 -07001065 }
Steve French50c2f752007-07-13 00:33:32 +00001066 for (i = 0, j = 0; i < temp_len; i++, j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 vol->password[j] = value[i];
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001068 if (value[i] == separator[0]
Steve French09d1db52005-04-28 22:41:08 -07001069 && value[i+1] == separator[0]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 /* skip second comma */
1071 i++;
1072 }
1073 }
1074 vol->password[j] = 0;
1075 } else {
Pekka Enberge915fc42005-09-06 15:18:35 -07001076 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001077 if (vol->password == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00001078 printk(KERN_WARNING "CIFS: no memory "
1079 "for password\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001080 goto cifs_parse_mount_err;
Steve French433dc242005-04-28 22:41:08 -07001081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 strcpy(vol->password, value);
1083 }
Jeff Layton58f7f682009-06-10 09:57:55 -04001084 } else if (!strnicmp(data, "ip", 2) ||
1085 !strnicmp(data, "addr", 4)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if (!value || !*value) {
1087 vol->UNCip = NULL;
Jeff Layton50b64e32009-06-02 06:55:20 -04001088 } else if (strnlen(value, INET6_ADDRSTRLEN) <
1089 INET6_ADDRSTRLEN) {
Sean Finneyb9468452011-04-11 13:19:32 +00001090 vol->UNCip = kstrdup(value, GFP_KERNEL);
1091 if (!vol->UNCip) {
1092 printk(KERN_WARNING "CIFS: no memory "
1093 "for UNC IP\n");
1094 goto cifs_parse_mount_err;
1095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 } else {
Steve French50c2f752007-07-13 00:33:32 +00001097 printk(KERN_WARNING "CIFS: ip address "
1098 "too long\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001099 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
Steve French50c2f752007-07-13 00:33:32 +00001101 } else if (strnicmp(data, "sec", 3) == 0) {
1102 if (!value || !*value) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001103 cERROR(1, "no security value specified");
Steve French50c2f752007-07-13 00:33:32 +00001104 continue;
1105 } else if (strnicmp(value, "krb5i", 5) == 0) {
1106 vol->secFlg |= CIFSSEC_MAY_KRB5 |
Steve French189acaa2006-06-23 02:33:48 +00001107 CIFSSEC_MUST_SIGN;
Steve Frenchbf820672005-12-01 22:32:42 -08001108 } else if (strnicmp(value, "krb5p", 5) == 0) {
Steve French50c2f752007-07-13 00:33:32 +00001109 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
1110 CIFSSEC_MAY_KRB5; */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001111 cERROR(1, "Krb5 cifs privacy not supported");
Sean Finneyb9468452011-04-11 13:19:32 +00001112 goto cifs_parse_mount_err;
Steve Frenchbf820672005-12-01 22:32:42 -08001113 } else if (strnicmp(value, "krb5", 4) == 0) {
Steve French750d1152006-06-27 06:28:30 +00001114 vol->secFlg |= CIFSSEC_MAY_KRB5;
Steve Frenchac683922009-05-06 04:16:04 +00001115 } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
1116 vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
1117 CIFSSEC_MUST_SIGN;
1118 } else if (strnicmp(value, "ntlmssp", 7) == 0) {
1119 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
Steve Frenchbf820672005-12-01 22:32:42 -08001120 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
Steve French750d1152006-06-27 06:28:30 +00001121 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
Steve French189acaa2006-06-23 02:33:48 +00001122 CIFSSEC_MUST_SIGN;
Steve Frenchbf820672005-12-01 22:32:42 -08001123 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
Steve French750d1152006-06-27 06:28:30 +00001124 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
Steve Frenchbf820672005-12-01 22:32:42 -08001125 } else if (strnicmp(value, "ntlmi", 5) == 0) {
Steve French750d1152006-06-27 06:28:30 +00001126 vol->secFlg |= CIFSSEC_MAY_NTLM |
Steve French189acaa2006-06-23 02:33:48 +00001127 CIFSSEC_MUST_SIGN;
Steve Frenchbf820672005-12-01 22:32:42 -08001128 } else if (strnicmp(value, "ntlm", 4) == 0) {
1129 /* ntlm is default so can be turned off too */
Steve French750d1152006-06-27 06:28:30 +00001130 vol->secFlg |= CIFSSEC_MAY_NTLM;
Steve Frenchbf820672005-12-01 22:32:42 -08001131 } else if (strnicmp(value, "nontlm", 6) == 0) {
Steve French189acaa2006-06-23 02:33:48 +00001132 /* BB is there a better way to do this? */
Steve French750d1152006-06-27 06:28:30 +00001133 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
Steve French189acaa2006-06-23 02:33:48 +00001134#ifdef CONFIG_CIFS_WEAK_PW_HASH
1135 } else if (strnicmp(value, "lanman", 6) == 0) {
Steve French50c2f752007-07-13 00:33:32 +00001136 vol->secFlg |= CIFSSEC_MAY_LANMAN;
Steve French189acaa2006-06-23 02:33:48 +00001137#endif
Steve Frenchbf820672005-12-01 22:32:42 -08001138 } else if (strnicmp(value, "none", 4) == 0) {
Steve French189acaa2006-06-23 02:33:48 +00001139 vol->nullauth = 1;
Steve French50c2f752007-07-13 00:33:32 +00001140 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001141 cERROR(1, "bad security option: %s", value);
Sean Finneyb9468452011-04-11 13:19:32 +00001142 goto cifs_parse_mount_err;
Steve French50c2f752007-07-13 00:33:32 +00001143 }
Steve French1cb06d02011-02-24 18:07:19 +00001144 } else if (strnicmp(data, "vers", 3) == 0) {
1145 if (!value || !*value) {
1146 cERROR(1, "no protocol version specified"
1147 " after vers= mount option");
1148 } else if ((strnicmp(value, "cifs", 4) == 0) ||
1149 (strnicmp(value, "1", 1) == 0)) {
1150 /* this is the default */
1151 continue;
Steve French1cb06d02011-02-24 18:07:19 +00001152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 } else if ((strnicmp(data, "unc", 3) == 0)
1154 || (strnicmp(data, "target", 6) == 0)
1155 || (strnicmp(data, "path", 4) == 0)) {
1156 if (!value || !*value) {
Steve French50c2f752007-07-13 00:33:32 +00001157 printk(KERN_WARNING "CIFS: invalid path to "
1158 "network resource\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001159 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
1161 if ((temp_len = strnlen(value, 300)) < 300) {
Steve French50c2f752007-07-13 00:33:32 +00001162 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
Steve French4523cc32007-04-30 20:13:06 +00001163 if (vol->UNC == NULL)
Sean Finneyb9468452011-04-11 13:19:32 +00001164 goto cifs_parse_mount_err;
Steve French50c2f752007-07-13 00:33:32 +00001165 strcpy(vol->UNC, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 if (strncmp(vol->UNC, "//", 2) == 0) {
1167 vol->UNC[0] = '\\';
1168 vol->UNC[1] = '\\';
Steve French50c2f752007-07-13 00:33:32 +00001169 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 printk(KERN_WARNING
Steve French50c2f752007-07-13 00:33:32 +00001171 "CIFS: UNC Path does not begin "
1172 "with // or \\\\ \n");
Sean Finneyb9468452011-04-11 13:19:32 +00001173 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 }
1175 } else {
1176 printk(KERN_WARNING "CIFS: UNC name too long\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001177 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 }
1179 } else if ((strnicmp(data, "domain", 3) == 0)
1180 || (strnicmp(data, "workgroup", 5) == 0)) {
1181 if (!value || !*value) {
1182 printk(KERN_WARNING "CIFS: invalid domain name\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001183 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 }
1185 /* BB are there cases in which a comma can be valid in
1186 a domain name and need special handling? */
Steve French39798772006-05-31 22:40:51 +00001187 if (strnlen(value, 256) < 256) {
Sean Finneyb9468452011-04-11 13:19:32 +00001188 vol->domainname = kstrdup(value, GFP_KERNEL);
1189 if (!vol->domainname) {
1190 printk(KERN_WARNING "CIFS: no memory "
1191 "for domainname\n");
1192 goto cifs_parse_mount_err;
1193 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00001194 cFYI(1, "Domain name set");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 } else {
Steve French50c2f752007-07-13 00:33:32 +00001196 printk(KERN_WARNING "CIFS: domain name too "
1197 "long\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001198 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 }
Ben Greear3eb9a882010-09-01 17:06:02 -07001200 } else if (strnicmp(data, "srcaddr", 7) == 0) {
1201 vol->srcaddr.ss_family = AF_UNSPEC;
1202
1203 if (!value || !*value) {
1204 printk(KERN_WARNING "CIFS: srcaddr value"
1205 " not specified.\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001206 goto cifs_parse_mount_err;
Ben Greear3eb9a882010-09-01 17:06:02 -07001207 }
1208 i = cifs_convert_address((struct sockaddr *)&vol->srcaddr,
1209 value, strlen(value));
Dan Carpenterb235f372010-10-25 07:02:56 +02001210 if (i == 0) {
Ben Greear3eb9a882010-09-01 17:06:02 -07001211 printk(KERN_WARNING "CIFS: Could not parse"
1212 " srcaddr: %s\n",
1213 value);
Sean Finneyb9468452011-04-11 13:19:32 +00001214 goto cifs_parse_mount_err;
Ben Greear3eb9a882010-09-01 17:06:02 -07001215 }
Steve French50c2f752007-07-13 00:33:32 +00001216 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1217 if (!value || !*value) {
1218 printk(KERN_WARNING
1219 "CIFS: invalid path prefix\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001220 goto cifs_parse_mount_err;
Steve French50c2f752007-07-13 00:33:32 +00001221 }
1222 if ((temp_len = strnlen(value, 1024)) < 1024) {
Steve French4523cc32007-04-30 20:13:06 +00001223 if (value[0] != '/')
Steve French2fe87f02006-09-21 07:02:52 +00001224 temp_len++; /* missing leading slash */
Steve French50c2f752007-07-13 00:33:32 +00001225 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1226 if (vol->prepath == NULL)
Sean Finneyb9468452011-04-11 13:19:32 +00001227 goto cifs_parse_mount_err;
Steve French4523cc32007-04-30 20:13:06 +00001228 if (value[0] != '/') {
Steve French2fe87f02006-09-21 07:02:52 +00001229 vol->prepath[0] = '/';
Steve French50c2f752007-07-13 00:33:32 +00001230 strcpy(vol->prepath+1, value);
Steve French2fe87f02006-09-21 07:02:52 +00001231 } else
Steve French50c2f752007-07-13 00:33:32 +00001232 strcpy(vol->prepath, value);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001233 cFYI(1, "prefix path %s", vol->prepath);
Steve French50c2f752007-07-13 00:33:32 +00001234 } else {
1235 printk(KERN_WARNING "CIFS: prefix too long\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001236 goto cifs_parse_mount_err;
Steve French50c2f752007-07-13 00:33:32 +00001237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 } else if (strnicmp(data, "iocharset", 9) == 0) {
1239 if (!value || !*value) {
Steve French63135e02007-07-17 17:34:02 +00001240 printk(KERN_WARNING "CIFS: invalid iocharset "
1241 "specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001242 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 }
1244 if (strnlen(value, 65) < 65) {
Sean Finneyb9468452011-04-11 13:19:32 +00001245 if (strnicmp(value, "default", 7)) {
1246 vol->iocharset = kstrdup(value,
1247 GFP_KERNEL);
1248
1249 if (!vol->iocharset) {
1250 printk(KERN_WARNING "CIFS: no "
1251 "memory for"
1252 "charset\n");
1253 goto cifs_parse_mount_err;
1254 }
1255 }
Steve French50c2f752007-07-13 00:33:32 +00001256 /* if iocharset not set then load_nls_default
1257 is used by caller */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001258 cFYI(1, "iocharset set to %s", value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 } else {
Steve French63135e02007-07-17 17:34:02 +00001260 printk(KERN_WARNING "CIFS: iocharset name "
1261 "too long.\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001262 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 }
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001264 } else if (!strnicmp(data, "uid", 3) && value && *value) {
1265 vol->linux_uid = simple_strtoul(value, &value, 0);
1266 uid_specified = true;
Jeff Laytonbd763312011-01-11 10:33:24 -05001267 } else if (!strnicmp(data, "cruid", 5) && value && *value) {
1268 vol->cred_uid = simple_strtoul(value, &value, 0);
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001269 } else if (!strnicmp(data, "forceuid", 8)) {
1270 override_uid = 1;
1271 } else if (!strnicmp(data, "noforceuid", 10)) {
1272 override_uid = 0;
1273 } else if (!strnicmp(data, "gid", 3) && value && *value) {
1274 vol->linux_gid = simple_strtoul(value, &value, 0);
1275 gid_specified = true;
1276 } else if (!strnicmp(data, "forcegid", 8)) {
1277 override_gid = 1;
1278 } else if (!strnicmp(data, "noforcegid", 10)) {
1279 override_gid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 } else if (strnicmp(data, "file_mode", 4) == 0) {
1281 if (value && *value) {
1282 vol->file_mode =
1283 simple_strtoul(value, &value, 0);
1284 }
1285 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1286 if (value && *value) {
1287 vol->dir_mode =
1288 simple_strtoul(value, &value, 0);
1289 }
1290 } else if (strnicmp(data, "dirmode", 4) == 0) {
1291 if (value && *value) {
1292 vol->dir_mode =
1293 simple_strtoul(value, &value, 0);
1294 }
1295 } else if (strnicmp(data, "port", 4) == 0) {
1296 if (value && *value) {
1297 vol->port =
1298 simple_strtoul(value, &value, 0);
1299 }
1300 } else if (strnicmp(data, "rsize", 5) == 0) {
1301 if (value && *value) {
1302 vol->rsize =
1303 simple_strtoul(value, &value, 0);
1304 }
1305 } else if (strnicmp(data, "wsize", 5) == 0) {
1306 if (value && *value) {
1307 vol->wsize =
1308 simple_strtoul(value, &value, 0);
1309 }
1310 } else if (strnicmp(data, "sockopt", 5) == 0) {
Steve French6a5fa2362010-01-01 01:28:43 +00001311 if (!value || !*value) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001312 cERROR(1, "no socket option specified");
Steve French6a5fa2362010-01-01 01:28:43 +00001313 continue;
1314 } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) {
1315 vol->sockopt_tcp_nodelay = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 }
1317 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1318 if (!value || !*value || (*value == ' ')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001319 cFYI(1, "invalid (empty) netbiosname");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 } else {
Jeff Layton1397f2e2011-01-07 11:30:28 -05001321 memset(vol->source_rfc1001_name, 0x20,
1322 RFC1001_NAME_LEN);
1323 /*
1324 * FIXME: are there cases in which a comma can
1325 * be valid in workstation netbios name (and
1326 * need special handling)?
1327 */
1328 for (i = 0; i < RFC1001_NAME_LEN; i++) {
1329 /* don't ucase netbiosname for user */
Steve French50c2f752007-07-13 00:33:32 +00001330 if (value[i] == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 break;
Jeff Layton1397f2e2011-01-07 11:30:28 -05001332 vol->source_rfc1001_name[i] = value[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 }
1334 /* The string has 16th byte zero still from
1335 set at top of the function */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001336 if (i == RFC1001_NAME_LEN && value[i] != 0)
Steve French50c2f752007-07-13 00:33:32 +00001337 printk(KERN_WARNING "CIFS: netbiosname"
1338 " longer than 15 truncated.\n");
Steve Frencha10faeb22005-08-22 21:38:31 -07001339 }
1340 } else if (strnicmp(data, "servern", 7) == 0) {
1341 /* servernetbiosname specified override *SMBSERVER */
1342 if (!value || !*value || (*value == ' ')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001343 cFYI(1, "empty server netbiosname specified");
Steve Frencha10faeb22005-08-22 21:38:31 -07001344 } else {
1345 /* last byte, type, is 0x20 for servr type */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001346 memset(vol->target_rfc1001_name, 0x20,
1347 RFC1001_NAME_LEN_WITH_NULL);
Steve Frencha10faeb22005-08-22 21:38:31 -07001348
Steve French50c2f752007-07-13 00:33:32 +00001349 for (i = 0; i < 15; i++) {
Steve Frencha10faeb22005-08-22 21:38:31 -07001350 /* BB are there cases in which a comma can be
Steve French50c2f752007-07-13 00:33:32 +00001351 valid in this workstation netbios name
1352 (and need special handling)? */
Steve Frencha10faeb22005-08-22 21:38:31 -07001353
Steve French50c2f752007-07-13 00:33:32 +00001354 /* user or mount helper must uppercase
1355 the netbiosname */
1356 if (value[i] == 0)
Steve Frencha10faeb22005-08-22 21:38:31 -07001357 break;
1358 else
Steve French50c2f752007-07-13 00:33:32 +00001359 vol->target_rfc1001_name[i] =
1360 value[i];
Steve Frencha10faeb22005-08-22 21:38:31 -07001361 }
1362 /* The string has 16th byte zero still from
1363 set at top of the function */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001364 if (i == RFC1001_NAME_LEN && value[i] != 0)
Steve French50c2f752007-07-13 00:33:32 +00001365 printk(KERN_WARNING "CIFS: server net"
1366 "biosname longer than 15 truncated.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 }
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301368 } else if (strnicmp(data, "actimeo", 7) == 0) {
1369 if (value && *value) {
1370 vol->actimeo = HZ * simple_strtoul(value,
1371 &value, 0);
1372 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1373 cERROR(1, "CIFS: attribute cache"
1374 "timeout too large");
Sean Finneyb9468452011-04-11 13:19:32 +00001375 goto cifs_parse_mount_err;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301376 }
1377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 } else if (strnicmp(data, "credentials", 4) == 0) {
1379 /* ignore */
1380 } else if (strnicmp(data, "version", 3) == 0) {
1381 /* ignore */
Steve French50c2f752007-07-13 00:33:32 +00001382 } else if (strnicmp(data, "guest", 5) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 /* ignore */
Steve Frenchc9c7fa02011-08-29 18:54:12 +00001384 } else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) {
Steve French71a394f2009-06-26 04:07:18 +00001385 /* ignore */
1386 } else if (strnicmp(data, "ro", 2) == 0) {
1387 /* ignore */
Steve Frenchedf1ae42008-10-29 00:47:57 +00001388 } else if (strnicmp(data, "noblocksend", 11) == 0) {
1389 vol->noblocksnd = 1;
1390 } else if (strnicmp(data, "noautotune", 10) == 0) {
1391 vol->noautotune = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 } else if ((strnicmp(data, "suid", 4) == 0) ||
1393 (strnicmp(data, "nosuid", 6) == 0) ||
1394 (strnicmp(data, "exec", 4) == 0) ||
1395 (strnicmp(data, "noexec", 6) == 0) ||
1396 (strnicmp(data, "nodev", 5) == 0) ||
1397 (strnicmp(data, "noauto", 6) == 0) ||
1398 (strnicmp(data, "dev", 3) == 0)) {
1399 /* The mount tool or mount.cifs helper (if present)
Steve French50c2f752007-07-13 00:33:32 +00001400 uses these opts to set flags, and the flags are read
1401 by the kernel vfs layer before we get here (ie
1402 before read super) so there is no point trying to
1403 parse these options again and set anything and it
1404 is ok to just ignore them */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 } else if (strnicmp(data, "hard", 4) == 0) {
1407 vol->retry = 1;
1408 } else if (strnicmp(data, "soft", 4) == 0) {
1409 vol->retry = 0;
1410 } else if (strnicmp(data, "perm", 4) == 0) {
1411 vol->noperm = 0;
1412 } else if (strnicmp(data, "noperm", 6) == 0) {
1413 vol->noperm = 1;
Steve French6a0b4822005-04-28 22:41:05 -07001414 } else if (strnicmp(data, "mapchars", 8) == 0) {
1415 vol->remap = 1;
1416 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1417 vol->remap = 0;
Steve French50c2f752007-07-13 00:33:32 +00001418 } else if (strnicmp(data, "sfu", 3) == 0) {
1419 vol->sfu_emul = 1;
1420 } else if (strnicmp(data, "nosfu", 5) == 0) {
1421 vol->sfu_emul = 0;
Steve French2c1b8612008-10-16 18:35:21 +00001422 } else if (strnicmp(data, "nodfs", 5) == 0) {
1423 vol->nodfs = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001424 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1425 vol->posix_paths = 1;
1426 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1427 vol->posix_paths = 0;
Steve Frenchc18c8422007-07-18 23:21:09 +00001428 } else if (strnicmp(data, "nounix", 6) == 0) {
1429 vol->no_linux_ext = 1;
1430 } else if (strnicmp(data, "nolinux", 7) == 0) {
1431 vol->no_linux_ext = 1;
Steve French50c2f752007-07-13 00:33:32 +00001432 } else if ((strnicmp(data, "nocase", 6) == 0) ||
Steve Frencha10faeb22005-08-22 21:38:31 -07001433 (strnicmp(data, "ignorecase", 10) == 0)) {
Steve French50c2f752007-07-13 00:33:32 +00001434 vol->nocase = 1;
Jeff Laytonf636a342010-07-26 10:29:58 -04001435 } else if (strnicmp(data, "mand", 4) == 0) {
1436 /* ignore */
1437 } else if (strnicmp(data, "nomand", 6) == 0) {
1438 /* ignore */
1439 } else if (strnicmp(data, "_netdev", 7) == 0) {
1440 /* ignore */
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001441 } else if (strnicmp(data, "brl", 3) == 0) {
1442 vol->nobrl = 0;
Steve French50c2f752007-07-13 00:33:32 +00001443 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
Steve French1c955182005-08-30 20:58:07 -07001444 (strnicmp(data, "nolock", 6) == 0)) {
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001445 vol->nobrl = 1;
Steve Frenchd3485d32005-08-19 11:04:29 -07001446 /* turn off mandatory locking in mode
1447 if remote locking is turned off since the
1448 local vfs will do advisory */
Steve French50c2f752007-07-13 00:33:32 +00001449 if (vol->file_mode ==
1450 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001451 vol->file_mode = S_IALLUGO;
Steve French13a6e422008-12-02 17:24:33 +00001452 } else if (strnicmp(data, "forcemandatorylock", 9) == 0) {
1453 /* will take the shorter form "forcemand" as well */
1454 /* This mount option will force use of mandatory
1455 (DOS/Windows style) byte range locks, instead of
1456 using posix advisory byte range locks, even if the
1457 Unix extensions are available and posix locks would
1458 be supported otherwise. If Unix extensions are not
1459 negotiated this has no effect since mandatory locks
1460 would be used (mandatory locks is all that those
1461 those servers support) */
1462 vol->mand_lock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 } else if (strnicmp(data, "setuids", 7) == 0) {
1464 vol->setuids = 1;
1465 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1466 vol->setuids = 0;
Jeff Laytond0a9c072008-05-12 22:23:49 +00001467 } else if (strnicmp(data, "dynperm", 7) == 0) {
1468 vol->dynperm = true;
1469 } else if (strnicmp(data, "nodynperm", 9) == 0) {
1470 vol->dynperm = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 } else if (strnicmp(data, "nohard", 6) == 0) {
1472 vol->retry = 0;
1473 } else if (strnicmp(data, "nosoft", 6) == 0) {
1474 vol->retry = 1;
1475 } else if (strnicmp(data, "nointr", 6) == 0) {
1476 vol->intr = 0;
1477 } else if (strnicmp(data, "intr", 4) == 0) {
1478 vol->intr = 1;
Steve Frenchbe652442009-02-23 15:21:59 +00001479 } else if (strnicmp(data, "nostrictsync", 12) == 0) {
1480 vol->nostrictsync = 1;
1481 } else if (strnicmp(data, "strictsync", 10) == 0) {
1482 vol->nostrictsync = 0;
Steve French50c2f752007-07-13 00:33:32 +00001483 } else if (strnicmp(data, "serverino", 7) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 vol->server_ino = 1;
Steve French50c2f752007-07-13 00:33:32 +00001485 } else if (strnicmp(data, "noserverino", 9) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 vol->server_ino = 0;
Steve Frenchc9c7fa02011-08-29 18:54:12 +00001487 } else if (strnicmp(data, "rwpidforward", 12) == 0) {
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001488 vol->rwpidforward = 1;
Steve French50c2f752007-07-13 00:33:32 +00001489 } else if (strnicmp(data, "cifsacl", 7) == 0) {
Steve French0a4b92c2006-01-12 15:44:21 -08001490 vol->cifs_acl = 1;
1491 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1492 vol->cifs_acl = 0;
Steve French50c2f752007-07-13 00:33:32 +00001493 } else if (strnicmp(data, "acl", 3) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 vol->no_psx_acl = 0;
Steve French50c2f752007-07-13 00:33:32 +00001495 } else if (strnicmp(data, "noacl", 5) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 vol->no_psx_acl = 1;
Steve French84210e92008-10-23 04:42:37 +00001497 } else if (strnicmp(data, "locallease", 6) == 0) {
1498 vol->local_lease = 1;
Steve French50c2f752007-07-13 00:33:32 +00001499 } else if (strnicmp(data, "sign", 4) == 0) {
Steve French750d1152006-06-27 06:28:30 +00001500 vol->secFlg |= CIFSSEC_MUST_SIGN;
Steve French95b1cb92008-05-15 16:44:38 +00001501 } else if (strnicmp(data, "seal", 4) == 0) {
1502 /* we do not do the following in secFlags because seal
1503 is a per tree connection (mount) not a per socket
1504 or per-smb connection option in the protocol */
1505 /* vol->secFlg |= CIFSSEC_MUST_SEAL; */
1506 vol->seal = 1;
Steve French50c2f752007-07-13 00:33:32 +00001507 } else if (strnicmp(data, "direct", 6) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 vol->direct_io = 1;
Steve French50c2f752007-07-13 00:33:32 +00001509 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 vol->direct_io = 1;
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05001511 } else if (strnicmp(data, "strictcache", 11) == 0) {
1512 vol->strict_io = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 } else if (strnicmp(data, "noac", 4) == 0) {
Steve French50c2f752007-07-13 00:33:32 +00001514 printk(KERN_WARNING "CIFS: Mount option noac not "
1515 "supported. Instead set "
1516 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301517 } else if (strnicmp(data, "fsc", 3) == 0) {
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301518#ifndef CONFIG_CIFS_FSCACHE
Jeff Layton83fb0862011-06-08 07:35:24 -04001519 cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE "
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301520 "kernel config option set");
Sean Finneyb9468452011-04-11 13:19:32 +00001521 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301522#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301523 vol->fsc = true;
Stefan Metzmacher736a3322010-07-30 14:56:00 +02001524 } else if (strnicmp(data, "mfsymlinks", 10) == 0) {
1525 vol->mfsymlinks = true;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001526 } else if (strnicmp(data, "multiuser", 8) == 0) {
1527 vol->multiuser = true;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001528 } else if (!strnicmp(data, "backupuid", 9) && value && *value) {
1529 err = kstrtouint(value, 0, &vol->backupuid);
1530 if (err < 0) {
1531 cERROR(1, "%s: Invalid backupuid value",
1532 __func__);
1533 goto cifs_parse_mount_err;
1534 }
1535 vol->backupuid_specified = true;
1536 } else if (!strnicmp(data, "backupgid", 9) && value && *value) {
1537 err = kstrtouint(value, 0, &vol->backupgid);
1538 if (err < 0) {
1539 cERROR(1, "%s: Invalid backupgid value",
1540 __func__);
1541 goto cifs_parse_mount_err;
1542 }
1543 vol->backupgid_specified = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 } else
Steve French50c2f752007-07-13 00:33:32 +00001545 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1546 data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 }
1548 if (vol->UNC == NULL) {
Steve French4523cc32007-04-30 20:13:06 +00001549 if (devname == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00001550 printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1551 "target\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001552 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 }
1554 if ((temp_len = strnlen(devname, 300)) < 300) {
Steve French50c2f752007-07-13 00:33:32 +00001555 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
Steve French4523cc32007-04-30 20:13:06 +00001556 if (vol->UNC == NULL)
Sean Finneyb9468452011-04-11 13:19:32 +00001557 goto cifs_parse_mount_err;
Steve French50c2f752007-07-13 00:33:32 +00001558 strcpy(vol->UNC, devname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 if (strncmp(vol->UNC, "//", 2) == 0) {
1560 vol->UNC[0] = '\\';
1561 vol->UNC[1] = '\\';
1562 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
Steve French50c2f752007-07-13 00:33:32 +00001563 printk(KERN_WARNING "CIFS: UNC Path does not "
1564 "begin with // or \\\\ \n");
Sean Finneyb9468452011-04-11 13:19:32 +00001565 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 }
Igor Mammedov7c5e6282008-05-08 20:48:42 +00001567 value = strpbrk(vol->UNC+2, "/\\");
1568 if (value)
1569 *value = '\\';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 } else {
1571 printk(KERN_WARNING "CIFS: UNC name too long\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001572 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 }
1574 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04001575
1576 if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
1577 cERROR(1, "Multiuser mounts currently require krb5 "
1578 "authentication!");
Sean Finneyb9468452011-04-11 13:19:32 +00001579 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04001580 }
1581
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001582 if (vol->UNCip == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 vol->UNCip = &vol->UNC[2];
1584
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001585 if (uid_specified)
1586 vol->override_uid = override_uid;
1587 else if (override_uid == 1)
1588 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1589 "specified with no uid= option.\n");
1590
1591 if (gid_specified)
1592 vol->override_gid = override_gid;
1593 else if (override_gid == 1)
1594 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1595 "specified with no gid= option.\n");
1596
Sean Finneyb9468452011-04-11 13:19:32 +00001597 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00001599
1600cifs_parse_mount_err:
1601 kfree(mountdata_copy);
1602 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603}
1604
Ben Greear3eb9a882010-09-01 17:06:02 -07001605/** Returns true if srcaddr isn't specified and rhs isn't
1606 * specified, or if srcaddr is specified and
1607 * matches the IP address of the rhs argument.
1608 */
Jeff Layton45151482010-07-06 20:43:02 -04001609static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07001610srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
1611{
1612 switch (srcaddr->sa_family) {
1613 case AF_UNSPEC:
1614 return (rhs->sa_family == AF_UNSPEC);
1615 case AF_INET: {
1616 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
1617 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
1618 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
1619 }
1620 case AF_INET6: {
1621 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
1622 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
1623 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
1624 }
1625 default:
1626 WARN_ON(1);
1627 return false; /* don't expect to be here */
1628 }
1629}
1630
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001631/*
1632 * If no port is specified in addr structure, we try to match with 445 port
1633 * and if it fails - with 139 ports. It should be called only if address
1634 * families of server and addr are equal.
1635 */
1636static bool
1637match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
1638{
Steve French6da97912011-03-13 18:55:55 +00001639 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03001640
1641 switch (addr->sa_family) {
1642 case AF_INET:
1643 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
1644 port = ((struct sockaddr_in *) addr)->sin_port;
1645 break;
1646 case AF_INET6:
1647 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
1648 port = ((struct sockaddr_in6 *) addr)->sin6_port;
1649 break;
1650 default:
1651 WARN_ON(1);
1652 return false;
1653 }
1654
1655 if (!port) {
1656 port = htons(CIFS_PORT);
1657 if (port == *sport)
1658 return true;
1659
1660 port = htons(RFC1001_PORT);
1661 }
1662
1663 return port == *sport;
1664}
Ben Greear3eb9a882010-09-01 17:06:02 -07001665
1666static bool
1667match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
1668 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
Jeff Layton45151482010-07-06 20:43:02 -04001670 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001671 case AF_INET: {
1672 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1673 struct sockaddr_in *srv_addr4 =
1674 (struct sockaddr_in *)&server->dstaddr;
1675
1676 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04001677 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001678 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001679 }
1680 case AF_INET6: {
1681 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1682 struct sockaddr_in6 *srv_addr6 =
1683 (struct sockaddr_in6 *)&server->dstaddr;
1684
Jeff Layton45151482010-07-06 20:43:02 -04001685 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001686 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04001687 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001688 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04001689 return false;
Jeff Layton45151482010-07-06 20:43:02 -04001690 break;
1691 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001692 default:
1693 WARN_ON(1);
1694 return false; /* don't expect to be here */
1695 }
Jeff Layton45151482010-07-06 20:43:02 -04001696
Ben Greear3eb9a882010-09-01 17:06:02 -07001697 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
1698 return false;
1699
Jeff Layton45151482010-07-06 20:43:02 -04001700 return true;
1701}
1702
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001703static bool
1704match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
1705{
1706 unsigned int secFlags;
1707
1708 if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
1709 secFlags = vol->secFlg;
1710 else
1711 secFlags = global_secflags | vol->secFlg;
1712
1713 switch (server->secType) {
1714 case LANMAN:
1715 if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT)))
1716 return false;
1717 break;
1718 case NTLMv2:
1719 if (!(secFlags & CIFSSEC_MAY_NTLMV2))
1720 return false;
1721 break;
1722 case NTLM:
1723 if (!(secFlags & CIFSSEC_MAY_NTLM))
1724 return false;
1725 break;
1726 case Kerberos:
1727 if (!(secFlags & CIFSSEC_MAY_KRB5))
1728 return false;
1729 break;
1730 case RawNTLMSSP:
1731 if (!(secFlags & CIFSSEC_MAY_NTLMSSP))
1732 return false;
1733 break;
1734 default:
1735 /* shouldn't happen */
1736 return false;
1737 }
1738
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001739 /* now check if signing mode is acceptable */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001740 if ((secFlags & CIFSSEC_MAY_SIGN) == 0 &&
Steve French96daf2b2011-05-27 04:34:02 +00001741 (server->sec_mode & SECMODE_SIGN_REQUIRED))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001742 return false;
1743 else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) &&
Steve French96daf2b2011-05-27 04:34:02 +00001744 (server->sec_mode &
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001745 (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0)
1746 return false;
1747
1748 return true;
1749}
1750
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00001751static int match_server(struct TCP_Server_Info *server, struct sockaddr *addr,
1752 struct smb_vol *vol)
1753{
1754 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
1755 return 0;
1756
1757 if (!match_address(server, addr,
1758 (struct sockaddr *)&vol->srcaddr))
1759 return 0;
1760
1761 if (!match_port(server, addr))
1762 return 0;
1763
1764 if (!match_security(server, vol))
1765 return 0;
1766
1767 return 1;
1768}
1769
Jeff Layton45151482010-07-06 20:43:02 -04001770static struct TCP_Server_Info *
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001771cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04001772{
Jeff Laytone7ddee92008-11-14 13:44:38 -05001773 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301775 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04001776 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00001777 if (!match_server(server, addr, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001778 continue;
1779
Jeff Laytone7ddee92008-11-14 13:44:38 -05001780 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301781 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001782 cFYI(1, "Existing tcp session with server found");
Jeff Laytone7ddee92008-11-14 13:44:38 -05001783 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301785 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 return NULL;
1787}
1788
Jeff Layton14fbf502008-11-14 13:53:46 -05001789static void
Jeff Laytone7ddee92008-11-14 13:44:38 -05001790cifs_put_tcp_session(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791{
Jeff Laytone7ddee92008-11-14 13:44:38 -05001792 struct task_struct *task;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301794 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05001795 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301796 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05001797 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 }
Steve Frenchdea570e02008-05-06 22:05:51 +00001799
Rob Landleyf1d0c992011-01-22 15:44:05 -06001800 put_net(cifs_net_ns(server));
1801
Jeff Laytone7ddee92008-11-14 13:44:38 -05001802 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301803 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05001804
Jeff Laytonc74093b2011-01-11 07:24:23 -05001805 cancel_delayed_work_sync(&server->echo);
1806
Jeff Laytone7ddee92008-11-14 13:44:38 -05001807 spin_lock(&GlobalMid_Lock);
1808 server->tcpStatus = CifsExiting;
1809 spin_unlock(&GlobalMid_Lock);
1810
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05001811 cifs_crypto_shash_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05301812 cifs_fscache_release_client_cookie(server);
1813
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05001814 kfree(server->session_key.response);
1815 server->session_key.response = NULL;
1816 server->session_key.len = 0;
1817
Jeff Laytone7ddee92008-11-14 13:44:38 -05001818 task = xchg(&server->tsk, NULL);
1819 if (task)
1820 force_sig(SIGKILL, task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821}
1822
Jeff Layton63c038c2008-12-01 18:41:46 -05001823static struct TCP_Server_Info *
1824cifs_get_tcp_session(struct smb_vol *volume_info)
1825{
1826 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Laytona9ac49d2009-01-22 14:43:21 -05001827 struct sockaddr_storage addr;
Jeff Layton63c038c2008-12-01 18:41:46 -05001828 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
1829 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
1830 int rc;
1831
Jeff Laytona9ac49d2009-01-22 14:43:21 -05001832 memset(&addr, 0, sizeof(struct sockaddr_storage));
Jeff Layton63c038c2008-12-01 18:41:46 -05001833
Joe Perchesb6b38f72010-04-21 03:50:45 +00001834 cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04001835
Jeff Layton63c038c2008-12-01 18:41:46 -05001836 if (volume_info->UNCip && volume_info->UNC) {
Jeff Layton50d97162010-07-06 20:43:01 -04001837 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
1838 volume_info->UNCip,
David Howells67b76262010-07-22 18:33:01 +01001839 strlen(volume_info->UNCip),
Jeff Layton50d97162010-07-06 20:43:01 -04001840 volume_info->port);
Jeff Layton1e68b2b2009-06-11 10:27:30 -04001841 if (!rc) {
Jeff Layton63c038c2008-12-01 18:41:46 -05001842 /* we failed translating address */
1843 rc = -EINVAL;
1844 goto out_err;
1845 }
Jeff Layton63c038c2008-12-01 18:41:46 -05001846 } else if (volume_info->UNCip) {
1847 /* BB using ip addr as tcp_ses name to connect to the
1848 DFS root below */
Joe Perchesb6b38f72010-04-21 03:50:45 +00001849 cERROR(1, "Connecting to DFS root not implemented yet");
Jeff Layton63c038c2008-12-01 18:41:46 -05001850 rc = -EINVAL;
1851 goto out_err;
1852 } else /* which tcp_sess DFS root would we conect to */ {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001853 cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
1854 "unc=//192.168.1.100/public) specified");
Jeff Layton63c038c2008-12-01 18:41:46 -05001855 rc = -EINVAL;
1856 goto out_err;
1857 }
1858
1859 /* see if we already have a matching tcp_ses */
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04001860 tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05001861 if (tcp_ses)
1862 return tcp_ses;
1863
1864 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1865 if (!tcp_ses) {
1866 rc = -ENOMEM;
1867 goto out_err;
1868 }
1869
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05001870 rc = cifs_crypto_shash_allocate(tcp_ses);
1871 if (rc) {
1872 cERROR(1, "could not setup hash structures rc %d", rc);
1873 goto out_err;
1874 }
1875
Rob Landleyf1d0c992011-01-22 15:44:05 -06001876 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05001877 tcp_ses->hostname = extract_hostname(volume_info->UNC);
1878 if (IS_ERR(tcp_ses->hostname)) {
1879 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05001880 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05001881 }
1882
1883 tcp_ses->noblocksnd = volume_info->noblocksnd;
1884 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00001885 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Jeff Layton63c038c2008-12-01 18:41:46 -05001886 atomic_set(&tcp_ses->inFlight, 0);
1887 init_waitqueue_head(&tcp_ses->response_q);
1888 init_waitqueue_head(&tcp_ses->request_q);
1889 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
1890 mutex_init(&tcp_ses->srv_mutex);
1891 memcpy(tcp_ses->workstation_RFC1001_name,
1892 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1893 memcpy(tcp_ses->server_RFC1001_name,
1894 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05001895 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05001896 tcp_ses->sequence_number = 0;
Steve Frenchfda35942011-01-20 18:06:34 +00001897 tcp_ses->lstrp = jiffies;
Jeff Layton63c038c2008-12-01 18:41:46 -05001898 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
1899 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05001900 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Jeff Layton63c038c2008-12-01 18:41:46 -05001901
1902 /*
1903 * at this point we are the only ones with the pointer
1904 * to the struct since the kernel thread not created yet
1905 * no need to spinlock this init of tcpStatus or srv_count
1906 */
1907 tcp_ses->tcpStatus = CifsNew;
Ben Greear3eb9a882010-09-01 17:06:02 -07001908 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
1909 sizeof(tcp_ses->srcaddr));
Jeff Layton63c038c2008-12-01 18:41:46 -05001910 ++tcp_ses->srv_count;
1911
Jeff Laytona9ac49d2009-01-22 14:43:21 -05001912 if (addr.ss_family == AF_INET6) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001913 cFYI(1, "attempting ipv6 connect");
Jeff Layton63c038c2008-12-01 18:41:46 -05001914 /* BB should we allow ipv6 on port 139? */
1915 /* other OS never observed in Wild doing 139 with v6 */
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03001916 memcpy(&tcp_ses->dstaddr, sin_server6,
1917 sizeof(struct sockaddr_in6));
1918 } else
1919 memcpy(&tcp_ses->dstaddr, sin_server,
1920 sizeof(struct sockaddr_in));
1921
1922 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05001923 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00001924 cERROR(1, "Error connecting to socket. Aborting operation");
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05001925 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05001926 }
1927
1928 /*
1929 * since we're in a cifs function already, we know that
1930 * this will succeed. No need for try_module_get().
1931 */
1932 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04001933 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05001934 tcp_ses, "cifsd");
1935 if (IS_ERR(tcp_ses->tsk)) {
1936 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesb6b38f72010-04-21 03:50:45 +00001937 cERROR(1, "error %d create cifsd thread", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05001938 module_put(THIS_MODULE);
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05001939 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05001940 }
Steve Frenchfd88ce92011-04-12 01:01:14 +00001941 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05001942
1943 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301944 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05001945 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301946 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05001947
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05301948 cifs_fscache_get_client_cookie(tcp_ses);
1949
Jeff Laytonc74093b2011-01-11 07:24:23 -05001950 /* queue echo request delayed work */
1951 queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
1952
Jeff Layton63c038c2008-12-01 18:41:46 -05001953 return tcp_ses;
1954
Shirish Pargaonkarf7c54452010-10-26 18:10:24 -05001955out_err_crypto_release:
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05001956 cifs_crypto_shash_release(tcp_ses);
1957
Rob Landleyf1d0c992011-01-22 15:44:05 -06001958 put_net(cifs_net_ns(tcp_ses));
1959
Jeff Layton63c038c2008-12-01 18:41:46 -05001960out_err:
1961 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00001962 if (!IS_ERR(tcp_ses->hostname))
1963 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05001964 if (tcp_ses->ssocket)
1965 sock_release(tcp_ses->ssocket);
1966 kfree(tcp_ses);
1967 }
1968 return ERR_PTR(rc);
1969}
1970
Steve French96daf2b2011-05-27 04:34:02 +00001971static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00001972{
1973 switch (ses->server->secType) {
1974 case Kerberos:
1975 if (vol->cred_uid != ses->cred_uid)
1976 return 0;
1977 break;
1978 default:
1979 /* anything else takes username/password */
1980 if (ses->user_name == NULL)
1981 return 0;
1982 if (strncmp(ses->user_name, vol->username,
1983 MAX_USERNAME_SIZE))
1984 return 0;
1985 if (strlen(vol->username) != 0 &&
1986 ses->password != NULL &&
1987 strncmp(ses->password,
1988 vol->password ? vol->password : "",
1989 MAX_PASSWORD_SIZE))
1990 return 0;
1991 }
1992 return 1;
1993}
1994
Steve French96daf2b2011-05-27 04:34:02 +00001995static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04001996cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997{
Steve French96daf2b2011-05-27 04:34:02 +00001998 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302000 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002001 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002002 if (!match_session(ses, vol))
2003 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002004 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302005 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002006 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302008 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 return NULL;
2010}
2011
Jeff Layton14fbf502008-11-14 13:53:46 -05002012static void
Steve French96daf2b2011-05-27 04:34:02 +00002013cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002014{
2015 int xid;
2016 struct TCP_Server_Info *server = ses->server;
2017
Jeff Layton36988c72010-04-24 07:57:43 -04002018 cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302019 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002020 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302021 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002022 return;
2023 }
2024
2025 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302026 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002027
2028 if (ses->status == CifsGood) {
2029 xid = GetXid();
2030 CIFSSMBLogoff(xid, ses);
2031 _FreeXid(xid);
2032 }
2033 sesInfoFree(ses);
2034 cifs_put_tcp_session(server);
2035}
2036
Steve Frenchd9b94202011-04-12 01:24:57 +00002037static bool warned_on_ntlm; /* globals init to false automatically */
2038
Steve French96daf2b2011-05-27 04:34:02 +00002039static struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04002040cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2041{
2042 int rc = -ENOMEM, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002043 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002044 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2045 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04002046
2047 xid = GetXid();
2048
Jeff Layton4ff67b72010-07-06 20:43:02 -04002049 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04002050 if (ses) {
2051 cFYI(1, "Existing smb sess found (status=%d)", ses->status);
2052
Jeff Layton36988c72010-04-24 07:57:43 -04002053 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002054 rc = cifs_negotiate_protocol(xid, ses);
2055 if (rc) {
2056 mutex_unlock(&ses->session_mutex);
2057 /* problem -- put our ses reference */
2058 cifs_put_smb_ses(ses);
2059 FreeXid(xid);
2060 return ERR_PTR(rc);
2061 }
Jeff Layton36988c72010-04-24 07:57:43 -04002062 if (ses->need_reconnect) {
2063 cFYI(1, "Session needs reconnect");
2064 rc = cifs_setup_session(xid, ses,
2065 volume_info->local_nls);
2066 if (rc) {
2067 mutex_unlock(&ses->session_mutex);
2068 /* problem -- put our reference */
2069 cifs_put_smb_ses(ses);
2070 FreeXid(xid);
2071 return ERR_PTR(rc);
2072 }
2073 }
2074 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04002075
2076 /* existing SMB ses has a server reference already */
2077 cifs_put_tcp_session(server);
Jeff Layton36988c72010-04-24 07:57:43 -04002078 FreeXid(xid);
2079 return ses;
2080 }
2081
2082 cFYI(1, "Existing smb sess not found");
2083 ses = sesInfoAlloc();
2084 if (ses == NULL)
2085 goto get_ses_fail;
2086
2087 /* new SMB session uses our server ref */
2088 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002089 if (server->dstaddr.ss_family == AF_INET6)
2090 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002091 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002092 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04002093
Steve French8727c8a2011-02-25 01:11:56 -06002094 if (volume_info->username) {
2095 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
2096 if (!ses->user_name)
2097 goto get_ses_fail;
2098 }
Jeff Layton36988c72010-04-24 07:57:43 -04002099
2100 /* volume_info->password freed at unmount */
2101 if (volume_info->password) {
2102 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
2103 if (!ses->password)
2104 goto get_ses_fail;
2105 }
2106 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05002107 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
2108 if (!ses->domainName)
2109 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04002110 }
Jeff Layton3e4b3e12010-07-19 18:00:17 -04002111 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04002112 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00002113
2114 /* ntlmv2 is much stronger than ntlm security, and has been broadly
2115 supported for many years, time to update default security mechanism */
2116 if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
2117 warned_on_ntlm = true;
2118 cERROR(1, "default security mechanism requested. The default "
2119 "security mechanism will be upgraded from ntlm to "
Steve French9d1e3972011-10-06 23:14:07 -05002120 "ntlmv2 in kernel release 3.2");
Steve Frenchd9b94202011-04-12 01:24:57 +00002121 }
Jeff Layton36988c72010-04-24 07:57:43 -04002122 ses->overrideSecFlg = volume_info->secFlg;
2123
2124 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04002125 rc = cifs_negotiate_protocol(xid, ses);
2126 if (!rc)
2127 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04002128 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00002129 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04002130 goto get_ses_fail;
2131
2132 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302133 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002134 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302135 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04002136
2137 FreeXid(xid);
2138 return ses;
2139
2140get_ses_fail:
2141 sesInfoFree(ses);
2142 FreeXid(xid);
2143 return ERR_PTR(rc);
2144}
2145
Steve French96daf2b2011-05-27 04:34:02 +00002146static int match_tcon(struct cifs_tcon *tcon, const char *unc)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002147{
2148 if (tcon->tidStatus == CifsExiting)
2149 return 0;
2150 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2151 return 0;
2152 return 1;
2153}
2154
Steve French96daf2b2011-05-27 04:34:02 +00002155static struct cifs_tcon *
2156cifs_find_tcon(struct cifs_ses *ses, const char *unc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157{
2158 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00002159 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302161 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002162 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00002163 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002164 if (!match_tcon(tcon, unc))
Jeff Laytonf1987b42008-11-15 11:12:47 -05002165 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002166 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302167 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 return tcon;
2169 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302170 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 return NULL;
2172}
2173
Jeff Laytonf1987b42008-11-15 11:12:47 -05002174static void
Steve French96daf2b2011-05-27 04:34:02 +00002175cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05002176{
2177 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00002178 struct cifs_ses *ses = tcon->ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05002179
Jeff Laytond00c28d2010-04-24 07:57:44 -04002180 cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302181 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002182 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302183 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002184 return;
2185 }
2186
2187 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302188 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002189
2190 xid = GetXid();
2191 CIFSSMBTDis(xid, tcon);
2192 _FreeXid(xid);
2193
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302194 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00002195 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05002196 cifs_put_smb_ses(ses);
2197}
2198
Steve French96daf2b2011-05-27 04:34:02 +00002199static struct cifs_tcon *
2200cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04002201{
2202 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00002203 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04002204
2205 tcon = cifs_find_tcon(ses, volume_info->UNC);
2206 if (tcon) {
2207 cFYI(1, "Found match on UNC path");
2208 /* existing tcon already has a reference */
2209 cifs_put_smb_ses(ses);
2210 if (tcon->seal != volume_info->seal)
2211 cERROR(1, "transport encryption setting "
2212 "conflicts with existing tid");
2213 return tcon;
2214 }
2215
2216 tcon = tconInfoAlloc();
2217 if (tcon == NULL) {
2218 rc = -ENOMEM;
2219 goto out_fail;
2220 }
2221
2222 tcon->ses = ses;
2223 if (volume_info->password) {
2224 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
2225 if (!tcon->password) {
2226 rc = -ENOMEM;
2227 goto out_fail;
2228 }
2229 }
2230
2231 if (strchr(volume_info->UNC + 3, '\\') == NULL
2232 && strchr(volume_info->UNC + 3, '/') == NULL) {
2233 cERROR(1, "Missing share name");
2234 rc = -ENODEV;
2235 goto out_fail;
2236 }
2237
2238 /* BB Do we need to wrap session_mutex around
2239 * this TCon call and Unix SetFS as
2240 * we do on SessSetup and reconnect? */
2241 xid = GetXid();
2242 rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
2243 FreeXid(xid);
2244 cFYI(1, "CIFS Tcon rc = %d", rc);
2245 if (rc)
2246 goto out_fail;
2247
2248 if (volume_info->nodfs) {
2249 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2250 cFYI(1, "DFS disabled (%d)", tcon->Flags);
2251 }
2252 tcon->seal = volume_info->seal;
2253 /* we can have only one retry value for a connection
2254 to a share so for resources mounted more than once
2255 to the same server share the last value passed in
2256 for the retry flag is used */
2257 tcon->retry = volume_info->retry;
2258 tcon->nocase = volume_info->nocase;
2259 tcon->local_lease = volume_info->local_lease;
2260
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302261 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002262 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302263 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04002264
Suresh Jayaramand03382c2010-07-05 18:12:27 +05302265 cifs_fscache_get_super_cookie(tcon);
2266
Jeff Laytond00c28d2010-04-24 07:57:44 -04002267 return tcon;
2268
2269out_fail:
2270 tconInfoFree(tcon);
2271 return ERR_PTR(rc);
2272}
2273
Jeff Layton9d002df2010-10-06 19:51:11 -04002274void
2275cifs_put_tlink(struct tcon_link *tlink)
2276{
2277 if (!tlink || IS_ERR(tlink))
2278 return;
2279
2280 if (!atomic_dec_and_test(&tlink->tl_count) ||
2281 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
2282 tlink->tl_time = jiffies;
2283 return;
2284 }
2285
2286 if (!IS_ERR(tlink_tcon(tlink)))
2287 cifs_put_tcon(tlink_tcon(tlink));
2288 kfree(tlink);
2289 return;
2290}
Jeff Laytond00c28d2010-04-24 07:57:44 -04002291
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002292static inline struct tcon_link *
Pavel Shilovskycd518752011-06-09 12:58:53 +04002293cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
2294{
2295 return cifs_sb->master_tlink;
2296}
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002297
2298static int
2299compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2300{
2301 struct cifs_sb_info *old = CIFS_SB(sb);
2302 struct cifs_sb_info *new = mnt_data->cifs_sb;
2303
2304 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
2305 return 0;
2306
2307 if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
2308 (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
2309 return 0;
2310
2311 if (old->rsize != new->rsize)
2312 return 0;
2313
2314 /*
2315 * We want to share sb only if we don't specify wsize or specified wsize
2316 * is greater or equal than existing one.
2317 */
2318 if (new->wsize && new->wsize < old->wsize)
2319 return 0;
2320
2321 if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid)
2322 return 0;
2323
2324 if (old->mnt_file_mode != new->mnt_file_mode ||
2325 old->mnt_dir_mode != new->mnt_dir_mode)
2326 return 0;
2327
2328 if (strcmp(old->local_nls->charset, new->local_nls->charset))
2329 return 0;
2330
2331 if (old->actimeo != new->actimeo)
2332 return 0;
2333
2334 return 1;
2335}
2336
2337int
2338cifs_match_super(struct super_block *sb, void *data)
2339{
2340 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2341 struct smb_vol *volume_info;
2342 struct cifs_sb_info *cifs_sb;
2343 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00002344 struct cifs_ses *ses;
2345 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002346 struct tcon_link *tlink;
2347 struct sockaddr_storage addr;
2348 int rc = 0;
2349
2350 memset(&addr, 0, sizeof(struct sockaddr_storage));
2351
2352 spin_lock(&cifs_tcp_ses_lock);
2353 cifs_sb = CIFS_SB(sb);
2354 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
2355 if (IS_ERR(tlink)) {
2356 spin_unlock(&cifs_tcp_ses_lock);
2357 return rc;
2358 }
2359 tcon = tlink_tcon(tlink);
2360 ses = tcon->ses;
2361 tcp_srv = ses->server;
2362
2363 volume_info = mnt_data->vol;
2364
2365 if (!volume_info->UNCip || !volume_info->UNC)
2366 goto out;
2367
2368 rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
2369 volume_info->UNCip,
2370 strlen(volume_info->UNCip),
2371 volume_info->port);
2372 if (!rc)
2373 goto out;
2374
2375 if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
2376 !match_session(ses, volume_info) ||
2377 !match_tcon(tcon, volume_info->UNC)) {
2378 rc = 0;
2379 goto out;
2380 }
2381
2382 rc = compare_mount_options(sb, mnt_data);
2383out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002384 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04002385 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002386 return rc;
2387}
2388
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389int
Steve French96daf2b2011-05-27 04:34:02 +00002390get_dfs_path(int xid, struct cifs_ses *pSesInfo, const char *old_path,
Steve French50c2f752007-07-13 00:33:32 +00002391 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
Steve French366781c2008-01-25 10:12:41 +00002392 struct dfs_info3_param **preferrals, int remap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393{
2394 char *temp_unc;
2395 int rc = 0;
2396
2397 *pnum_referrals = 0;
Steve French366781c2008-01-25 10:12:41 +00002398 *preferrals = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
2400 if (pSesInfo->ipc_tid == 0) {
2401 temp_unc = kmalloc(2 /* for slashes */ +
Steve French50c2f752007-07-13 00:33:32 +00002402 strnlen(pSesInfo->serverName,
2403 SERVER_NAME_LEN_WITH_NULL * 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 + 1 + 4 /* slash IPC$ */ + 2,
2405 GFP_KERNEL);
2406 if (temp_unc == NULL)
2407 return -ENOMEM;
2408 temp_unc[0] = '\\';
2409 temp_unc[1] = '\\';
2410 strcpy(temp_unc + 2, pSesInfo->serverName);
2411 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
2412 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
Joe Perchesb6b38f72010-04-21 03:50:45 +00002413 cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 kfree(temp_unc);
2415 }
2416 if (rc == 0)
Steve Frenchc2cf07d2008-05-15 06:20:02 +00002417 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
Steve French737b7582005-04-28 22:41:06 -07002418 pnum_referrals, nls_codepage, remap);
Steve French366781c2008-01-25 10:12:41 +00002419 /* BB map targetUNCs to dfs_info3 structures, here or
2420 in CIFSGetDFSRefer BB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
2422 return rc;
2423}
2424
Jeff Layton09e50d52008-07-23 10:11:19 -04002425#ifdef CONFIG_DEBUG_LOCK_ALLOC
2426static struct lock_class_key cifs_key[2];
2427static struct lock_class_key cifs_slock_key[2];
2428
2429static inline void
2430cifs_reclassify_socket4(struct socket *sock)
2431{
2432 struct sock *sk = sock->sk;
2433 BUG_ON(sock_owned_by_user(sk));
2434 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
2435 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
2436}
2437
2438static inline void
2439cifs_reclassify_socket6(struct socket *sock)
2440{
2441 struct sock *sk = sock->sk;
2442 BUG_ON(sock_owned_by_user(sk));
2443 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
2444 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
2445}
2446#else
2447static inline void
2448cifs_reclassify_socket4(struct socket *sock)
2449{
2450}
2451
2452static inline void
2453cifs_reclassify_socket6(struct socket *sock)
2454{
2455}
2456#endif
2457
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00002459static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460{
Steve French50c2f752007-07-13 00:33:32 +00002461 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
Steve French50c2f752007-07-13 00:33:32 +00002463 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 /* mask a nibble at a time and encode */
2465 target[j] = 'A' + (0x0F & (source[i] >> 4));
2466 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00002467 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 }
2469
2470}
2471
Ben Greear3eb9a882010-09-01 17:06:02 -07002472static int
2473bind_socket(struct TCP_Server_Info *server)
2474{
2475 int rc = 0;
2476 if (server->srcaddr.ss_family != AF_UNSPEC) {
2477 /* Bind to the specified local IP address */
2478 struct socket *socket = server->ssocket;
2479 rc = socket->ops->bind(socket,
2480 (struct sockaddr *) &server->srcaddr,
2481 sizeof(server->srcaddr));
2482 if (rc < 0) {
2483 struct sockaddr_in *saddr4;
2484 struct sockaddr_in6 *saddr6;
2485 saddr4 = (struct sockaddr_in *)&server->srcaddr;
2486 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
2487 if (saddr6->sin6_family == AF_INET6)
2488 cERROR(1, "cifs: "
2489 "Failed to bind to: %pI6c, error: %d\n",
2490 &saddr6->sin6_addr, rc);
2491 else
2492 cERROR(1, "cifs: "
2493 "Failed to bind to: %pI4, error: %d\n",
2494 &saddr4->sin_addr.s_addr, rc);
2495 }
2496 }
2497 return rc;
2498}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
2500static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002501ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502{
2503 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002504 /*
2505 * some servers require RFC1001 sessinit before sending
2506 * negprot - BB check reconnection in case where second
2507 * sessinit is sent but no second negprot
2508 */
2509 struct rfc1002_session_packet *ses_init_buf;
2510 struct smb_hdr *smb_buf;
2511 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
2512 GFP_KERNEL);
2513 if (ses_init_buf) {
2514 ses_init_buf->trailer.session_req.called_len = 32;
2515
2516 if (server->server_RFC1001_name &&
2517 server->server_RFC1001_name[0] != 0)
2518 rfc1002mangle(ses_init_buf->trailer.
2519 session_req.called_name,
2520 server->server_RFC1001_name,
2521 RFC1001_NAME_LEN_WITH_NULL);
2522 else
2523 rfc1002mangle(ses_init_buf->trailer.
2524 session_req.called_name,
2525 DEFAULT_CIFS_CALLED_NAME,
2526 RFC1001_NAME_LEN_WITH_NULL);
2527
2528 ses_init_buf->trailer.session_req.calling_len = 32;
2529
2530 /*
2531 * calling name ends in null (byte 16) from old smb
2532 * convention.
2533 */
2534 if (server->workstation_RFC1001_name &&
2535 server->workstation_RFC1001_name[0] != 0)
2536 rfc1002mangle(ses_init_buf->trailer.
2537 session_req.calling_name,
2538 server->workstation_RFC1001_name,
2539 RFC1001_NAME_LEN_WITH_NULL);
2540 else
2541 rfc1002mangle(ses_init_buf->trailer.
2542 session_req.calling_name,
2543 "LINUX_CIFS_CLNT",
2544 RFC1001_NAME_LEN_WITH_NULL);
2545
2546 ses_init_buf->trailer.session_req.scope1 = 0;
2547 ses_init_buf->trailer.session_req.scope2 = 0;
2548 smb_buf = (struct smb_hdr *)ses_init_buf;
2549
2550 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00002551 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002552 rc = smb_send(server, smb_buf, 0x44);
2553 kfree(ses_init_buf);
2554 /*
2555 * RFC1001 layer in at least one server
2556 * requires very short break before negprot
2557 * presumably because not expecting negprot
2558 * to follow so fast. This is a simple
2559 * solution that works without
2560 * complicating the code and causes no
2561 * significant slowing down on mount
2562 * for everyone else
2563 */
2564 usleep_range(1000, 2000);
2565 }
2566 /*
2567 * else the negprot may still work without this
2568 * even though malloc failed
2569 */
2570
2571 return rc;
2572}
2573
2574static int
2575generic_ip_connect(struct TCP_Server_Info *server)
2576{
2577 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00002578 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002579 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002580 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002581 struct sockaddr *saddr;
2582
2583 saddr = (struct sockaddr *) &server->dstaddr;
2584
2585 if (server->dstaddr.ss_family == AF_INET6) {
2586 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
2587 slen = sizeof(struct sockaddr_in6);
2588 sfamily = AF_INET6;
2589 } else {
2590 sport = ((struct sockaddr_in *) saddr)->sin_port;
2591 slen = sizeof(struct sockaddr_in);
2592 sfamily = AF_INET;
2593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002595 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06002596 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
2597 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 if (rc < 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002599 cERROR(1, "Error %d creating socket", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002600 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002603
2604 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002605 cFYI(1, "Socket created");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05002606 server->ssocket = socket;
2607 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002608 if (sfamily == AF_INET6)
2609 cifs_reclassify_socket6(socket);
2610 else
2611 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 }
2613
Ben Greear3eb9a882010-09-01 17:06:02 -07002614 rc = bind_socket(server);
2615 if (rc < 0)
2616 return rc;
2617
Jeff Laytond5c56052008-12-01 18:42:33 -05002618 /*
2619 * Eventually check for other socket options to change from
2620 * the default. sock_setsockopt not used because it expects
2621 * user space buffer
2622 */
2623 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00002624 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00002625
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002626 /* make the bufsizes depend on wsize/rsize and max requests */
2627 if (server->noautotune) {
2628 if (socket->sk->sk_sndbuf < (200 * 1024))
2629 socket->sk->sk_sndbuf = 200 * 1024;
2630 if (socket->sk->sk_rcvbuf < (140 * 1024))
2631 socket->sk->sk_rcvbuf = 140 * 1024;
2632 }
2633
Steve French6a5fa2362010-01-01 01:28:43 +00002634 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002635 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00002636 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
2637 (char *)&val, sizeof(val));
2638 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002639 cFYI(1, "set TCP_NODELAY socket option error %d", rc);
Steve French6a5fa2362010-01-01 01:28:43 +00002640 }
2641
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002642 cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
2643 socket->sk->sk_sndbuf,
2644 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
2645
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04002646 rc = socket->ops->connect(socket, saddr, slen, 0);
2647 if (rc < 0) {
2648 cFYI(1, "Error %d connecting to server", rc);
2649 sock_release(socket);
2650 server->ssocket = NULL;
2651 return rc;
2652 }
2653
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002654 if (sport == htons(RFC1001_PORT))
2655 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00002656
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 return rc;
2658}
2659
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002660static int
2661ip_connect(struct TCP_Server_Info *server)
2662{
Steve French6da97912011-03-13 18:55:55 +00002663 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002664 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
2665 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
2666
2667 if (server->dstaddr.ss_family == AF_INET6)
2668 sport = &addr6->sin6_port;
2669 else
2670 sport = &addr->sin_port;
2671
2672 if (*sport == 0) {
2673 int rc;
2674
2675 /* try with 445 port at first */
2676 *sport = htons(CIFS_PORT);
2677
2678 rc = generic_ip_connect(server);
2679 if (rc >= 0)
2680 return rc;
2681
2682 /* if it failed, try with 139 port */
2683 *sport = htons(RFC1001_PORT);
2684 }
2685
2686 return generic_ip_connect(server);
2687}
2688
Steve French96daf2b2011-05-27 04:34:02 +00002689void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04002690 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00002691{
2692 /* if we are reconnecting then should we check to see if
2693 * any requested capabilities changed locally e.g. via
2694 * remount but we can not do much about it here
2695 * if they have (even if we could detect it by the following)
2696 * Perhaps we could add a backpointer to array of sb from tcon
2697 * or if we change to make all sb to same share the same
2698 * sb as NFS - then we only have one backpointer to sb.
2699 * What if we wanted to mount the server share twice once with
2700 * and once without posixacls or posix paths? */
2701 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00002702
Steve Frenchc18c8422007-07-18 23:21:09 +00002703 if (vol_info && vol_info->no_linux_ext) {
2704 tcon->fsUnixInfo.Capability = 0;
2705 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002706 cFYI(1, "Linux protocol extensions disabled");
Steve Frenchc18c8422007-07-18 23:21:09 +00002707 return;
2708 } else if (vol_info)
2709 tcon->unix_ext = 1; /* Unix Extensions supported */
2710
2711 if (tcon->unix_ext == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002712 cFYI(1, "Unix extensions disabled so not set on reconnect");
Steve Frenchc18c8422007-07-18 23:21:09 +00002713 return;
2714 }
Steve French50c2f752007-07-13 00:33:32 +00002715
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002716 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00002717 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French6848b732011-05-26 18:38:54 +00002718 cFYI(1, "unix caps which server supports %lld", cap);
Steve French8af18972007-02-14 04:42:51 +00002719 /* check for reconnect case in which we do not
2720 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00002721 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00002722 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00002723 originally at mount time */
2724 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
2725 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00002726 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
2727 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002728 cERROR(1, "POSIXPATH support change");
Steve French8af18972007-02-14 04:42:51 +00002729 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00002730 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002731 cERROR(1, "possible reconnect error");
2732 cERROR(1, "server disabled POSIX path support");
Igor Mammedov11b6d642008-02-15 19:06:04 +00002733 }
Steve French8af18972007-02-14 04:42:51 +00002734 }
Steve French50c2f752007-07-13 00:33:32 +00002735
Steve French6848b732011-05-26 18:38:54 +00002736 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
2737 cERROR(1, "per-share encryption not supported yet");
2738
Steve French8af18972007-02-14 04:42:51 +00002739 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00002740 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00002741 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00002742 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002743 cFYI(1, "negotiated posix acl support");
Al Viro2c6292a2011-06-17 09:05:48 -04002744 if (cifs_sb)
2745 cifs_sb->mnt_cifs_flags |=
2746 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00002747 }
2748
Steve French75865f8c2007-06-24 18:30:48 +00002749 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00002750 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00002751 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002752 cFYI(1, "negotiate posix pathnames");
Al Viro2c6292a2011-06-17 09:05:48 -04002753 if (cifs_sb)
2754 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00002755 CIFS_MOUNT_POSIX_PATHS;
2756 }
Steve French50c2f752007-07-13 00:33:32 +00002757
Al Viro2c6292a2011-06-17 09:05:48 -04002758 if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) {
Steve French75865f8c2007-06-24 18:30:48 +00002759 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
Al Viro2c6292a2011-06-17 09:05:48 -04002760 cifs_sb->rsize = 127 * 1024;
Joe Perchesb6b38f72010-04-21 03:50:45 +00002761 cFYI(DBG2, "larger reads not supported by srv");
Steve French75865f8c2007-06-24 18:30:48 +00002762 }
2763 }
Steve French50c2f752007-07-13 00:33:32 +00002764
2765
Joe Perchesb6b38f72010-04-21 03:50:45 +00002766 cFYI(1, "Negotiate caps 0x%x", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00002767#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00002768 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002769 cFYI(1, "FCNTL cap");
Steve French75865f8c2007-06-24 18:30:48 +00002770 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002771 cFYI(1, "EXTATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00002772 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002773 cFYI(1, "POSIX path cap");
Steve French75865f8c2007-06-24 18:30:48 +00002774 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002775 cFYI(1, "XATTR cap");
Steve French75865f8c2007-06-24 18:30:48 +00002776 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002777 cFYI(1, "POSIX ACL cap");
Steve French75865f8c2007-06-24 18:30:48 +00002778 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002779 cFYI(1, "very large read cap");
Steve French75865f8c2007-06-24 18:30:48 +00002780 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesb6b38f72010-04-21 03:50:45 +00002781 cFYI(1, "very large write cap");
Steve French6848b732011-05-26 18:38:54 +00002782 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
2783 cFYI(1, "transport encryption cap");
2784 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
2785 cFYI(1, "mandatory transport encryption cap");
Steve French8af18972007-02-14 04:42:51 +00002786#endif /* CIFS_DEBUG2 */
2787 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00002788 if (vol_info == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002789 cFYI(1, "resetting capabilities failed");
Steve French442aa312007-09-24 20:25:46 +00002790 } else
Joe Perchesb6b38f72010-04-21 03:50:45 +00002791 cERROR(1, "Negotiating Unix capabilities "
Steve French5a44b312007-09-20 15:16:24 +00002792 "with the server failed. Consider "
2793 "mounting with the Unix Extensions\n"
2794 "disabled, if problems are found, "
2795 "by specifying the nounix mount "
Joe Perchesb6b38f72010-04-21 03:50:45 +00002796 "option.");
Steve French5a44b312007-09-20 15:16:24 +00002797
Steve French8af18972007-02-14 04:42:51 +00002798 }
2799 }
2800}
2801
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00002802void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
2803 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04002804{
Jeff Layton2de970f2010-10-06 19:51:12 -04002805 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
2806
Al Viro2ced6f62011-06-17 09:20:04 -04002807 spin_lock_init(&cifs_sb->tlink_tree_lock);
2808 cifs_sb->tlink_tree = RB_ROOT;
2809
Steve French3b795212008-11-13 19:45:32 +00002810 if (pvolume_info->rsize > CIFSMaxBufSize) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002811 cERROR(1, "rsize %d too large, using MaxBufSize",
2812 pvolume_info->rsize);
Steve French3b795212008-11-13 19:45:32 +00002813 cifs_sb->rsize = CIFSMaxBufSize;
2814 } else if ((pvolume_info->rsize) &&
2815 (pvolume_info->rsize <= CIFSMaxBufSize))
2816 cifs_sb->rsize = pvolume_info->rsize;
2817 else /* default */
2818 cifs_sb->rsize = CIFSMaxBufSize;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04002819
Steve French3b795212008-11-13 19:45:32 +00002820 if (cifs_sb->rsize < 2048) {
2821 cifs_sb->rsize = 2048;
2822 /* Windows ME may prefer this */
Joe Perchesb6b38f72010-04-21 03:50:45 +00002823 cFYI(1, "readsize set to minimum: 2048");
Steve French3b795212008-11-13 19:45:32 +00002824 }
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04002825
2826 /*
2827 * Temporarily set wsize for matching superblock. If we end up using
2828 * new sb then cifs_negotiate_wsize will later negotiate it downward
2829 * if needed.
2830 */
2831 cifs_sb->wsize = pvolume_info->wsize;
2832
Steve French3b795212008-11-13 19:45:32 +00002833 cifs_sb->mnt_uid = pvolume_info->linux_uid;
2834 cifs_sb->mnt_gid = pvolume_info->linux_gid;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05002835 if (pvolume_info->backupuid_specified)
2836 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
2837 if (pvolume_info->backupgid_specified)
2838 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
Steve French3b795212008-11-13 19:45:32 +00002839 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
2840 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesb6b38f72010-04-21 03:50:45 +00002841 cFYI(1, "file mode: 0x%x dir mode: 0x%x",
2842 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00002843
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302844 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00002845 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05302846
Steve French3b795212008-11-13 19:45:32 +00002847 if (pvolume_info->noperm)
2848 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2849 if (pvolume_info->setuids)
2850 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2851 if (pvolume_info->server_ino)
2852 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2853 if (pvolume_info->remap)
2854 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2855 if (pvolume_info->no_xattr)
2856 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2857 if (pvolume_info->sfu_emul)
2858 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2859 if (pvolume_info->nobrl)
2860 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve Frenchbe652442009-02-23 15:21:59 +00002861 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00002862 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00002863 if (pvolume_info->mand_lock)
2864 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00002865 if (pvolume_info->rwpidforward)
2866 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French3b795212008-11-13 19:45:32 +00002867 if (pvolume_info->cifs_acl)
2868 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05002869 if (pvolume_info->backupuid_specified)
2870 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
2871 if (pvolume_info->backupgid_specified)
2872 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Steve French3b795212008-11-13 19:45:32 +00002873 if (pvolume_info->override_uid)
2874 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2875 if (pvolume_info->override_gid)
2876 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2877 if (pvolume_info->dynperm)
2878 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05302879 if (pvolume_info->fsc)
2880 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002881 if (pvolume_info->multiuser)
2882 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
2883 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05002884 if (pvolume_info->strict_io)
2885 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00002886 if (pvolume_info->direct_io) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00002887 cFYI(1, "mounting share using direct i/o");
Steve French3b795212008-11-13 19:45:32 +00002888 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2889 }
Stefan Metzmacher736a3322010-07-30 14:56:00 +02002890 if (pvolume_info->mfsymlinks) {
2891 if (pvolume_info->sfu_emul) {
2892 cERROR(1, "mount option mfsymlinks ignored if sfu "
2893 "mount option is used");
2894 } else {
2895 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
2896 }
2897 }
Steve French3b795212008-11-13 19:45:32 +00002898
2899 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesb6b38f72010-04-21 03:50:45 +00002900 cERROR(1, "mount option dynperm ignored if cifsacl "
2901 "mount option supported");
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04002902}
2903
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002904/*
2905 * When the server supports very large writes via POSIX extensions, we can
Jeff Layton1190f6a2011-06-22 17:33:57 -04002906 * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
2907 * the RFC1001 length.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002908 *
2909 * Note that this might make for "interesting" allocation problems during
Jeff Layton1190f6a2011-06-22 17:33:57 -04002910 * writeback however as we have to allocate an array of pointers for the
2911 * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002912 */
Jeff Layton1190f6a2011-06-22 17:33:57 -04002913#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002914
2915/*
Jeff Layton1190f6a2011-06-22 17:33:57 -04002916 * When the server doesn't allow large posix writes, only allow a wsize of
Pavel Shilovsky94443f42011-10-07 18:57:45 +04002917 * 2^17-1 minus the size of the WRITE_AND_X header. That allows for a write up
Jeff Layton1190f6a2011-06-22 17:33:57 -04002918 * to the maximum size described by RFC1002.
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002919 */
Pavel Shilovsky94443f42011-10-07 18:57:45 +04002920#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002921
2922/*
2923 * The default wsize is 1M. find_get_pages seems to return a maximum of 256
2924 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
2925 * a single wsize request with a single call.
2926 */
2927#define CIFS_DEFAULT_WSIZE (1024 * 1024)
2928
2929static unsigned int
Steve French96daf2b2011-05-27 04:34:02 +00002930cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002931{
2932 __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2933 struct TCP_Server_Info *server = tcon->ses->server;
2934 unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
2935 CIFS_DEFAULT_WSIZE;
2936
2937 /* can server support 24-bit write sizes? (via UNIX extensions) */
2938 if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
Jeff Layton1190f6a2011-06-22 17:33:57 -04002939 wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002940
Jeff Layton1190f6a2011-06-22 17:33:57 -04002941 /*
2942 * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
2943 * Limit it to max buffer offered by the server, minus the size of the
2944 * WRITEX header, not including the 4 byte RFC1001 length.
2945 */
2946 if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
2947 (!(server->capabilities & CAP_UNIX) &&
2948 (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
2949 wsize = min_t(unsigned int, wsize,
2950 server->maxBuf - sizeof(WRITE_REQ) + 4);
Jeff Laytonf7910cb2011-05-19 16:22:58 -04002951
2952 /* hard limit of CIFS_MAX_WSIZE */
2953 wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
2954
2955 return wsize;
2956}
2957
Igor Mammedove4cce942009-02-10 14:10:26 +03002958static int
Steve French96daf2b2011-05-27 04:34:02 +00002959is_path_accessible(int xid, struct cifs_tcon *tcon,
Igor Mammedove4cce942009-02-10 14:10:26 +03002960 struct cifs_sb_info *cifs_sb, const char *full_path)
2961{
2962 int rc;
Igor Mammedove4cce942009-02-10 14:10:26 +03002963 FILE_ALL_INFO *pfile_info;
2964
Igor Mammedove4cce942009-02-10 14:10:26 +03002965 pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
2966 if (pfile_info == NULL)
2967 return -ENOMEM;
2968
2969 rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
2970 0 /* not legacy */, cifs_sb->local_nls,
2971 cifs_sb->mnt_cifs_flags &
2972 CIFS_MOUNT_MAP_SPECIAL_CHR);
Jeff Layton221d1d72011-05-17 06:40:30 -04002973
2974 if (rc == -EOPNOTSUPP || rc == -EINVAL)
2975 rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
2976 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
2977 CIFS_MOUNT_MAP_SPECIAL_CHR);
Igor Mammedove4cce942009-02-10 14:10:26 +03002978 kfree(pfile_info);
2979 return rc;
2980}
2981
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04002982static void
2983cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04002984{
Sean Finneyb9468452011-04-11 13:19:32 +00002985 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04002986 kzfree(volume_info->password);
2987 kfree(volume_info->UNC);
Steve French13589c42011-08-18 04:41:55 +00002988 if (volume_info->UNCip != volume_info->UNC + 2)
2989 kfree(volume_info->UNCip);
Sean Finneyb9468452011-04-11 13:19:32 +00002990 kfree(volume_info->domainname);
2991 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04002992 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04002993}
2994
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04002995void
2996cifs_cleanup_volume_info(struct smb_vol *volume_info)
2997{
2998 if (!volume_info)
2999 return;
3000 cleanup_volume_info_contents(volume_info);
3001 kfree(volume_info);
3002}
3003
3004
Steve French2d6d5892009-04-09 00:36:44 +00003005#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003006/* build_path_to_root returns full path to root when
3007 * we do not have an exiting connection (tcon) */
3008static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003009build_unc_path_to_root(const struct smb_vol *vol,
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003010 const struct cifs_sb_info *cifs_sb)
3011{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003012 char *full_path, *pos;
3013 unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0;
3014 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003015
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003016 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003017 if (full_path == NULL)
3018 return ERR_PTR(-ENOMEM);
3019
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003020 strncpy(full_path, vol->UNC, unc_len);
3021 pos = full_path + unc_len;
3022
3023 if (pplen) {
3024 strncpy(pos, vol->prepath, pplen);
3025 pos += pplen;
3026 }
3027
3028 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003029 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04003030 cFYI(1, "%s: full_path=%s", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003031 return full_path;
3032}
Sean Finneydd613942011-04-11 13:19:30 +00003033
3034/*
3035 * Perform a dfs referral query for a share and (optionally) prefix
3036 *
Sean Finney046462a2011-04-11 13:19:33 +00003037 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
3038 * to a string containing updated options for the submount. Otherwise it
3039 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00003040 *
3041 * Returns the rc from get_dfs_path to the caller, which can be used to
3042 * determine whether there were referrals.
3043 */
3044static int
Steve French96daf2b2011-05-27 04:34:02 +00003045expand_dfs_referral(int xid, struct cifs_ses *pSesInfo,
Sean Finneydd613942011-04-11 13:19:30 +00003046 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003047 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00003048{
3049 int rc;
3050 unsigned int num_referrals = 0;
3051 struct dfs_info3_param *referrals = NULL;
3052 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
3053
3054 full_path = build_unc_path_to_root(volume_info, cifs_sb);
3055 if (IS_ERR(full_path))
3056 return PTR_ERR(full_path);
3057
3058 /* For DFS paths, skip the first '\' of the UNC */
3059 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3060
3061 rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls,
3062 &num_referrals, &referrals,
3063 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
3064
3065 if (!rc && num_referrals > 0) {
3066 char *fake_devname = NULL;
3067
3068 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3069 full_path + 1, referrals,
3070 &fake_devname);
3071
3072 free_dfs_info_array(referrals, num_referrals);
Sean Finney046462a2011-04-11 13:19:33 +00003073
Sean Finneydd613942011-04-11 13:19:30 +00003074 if (IS_ERR(mdata)) {
3075 rc = PTR_ERR(mdata);
3076 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003077 } else {
3078 cleanup_volume_info_contents(volume_info);
3079 memset(volume_info, '\0', sizeof(*volume_info));
3080 rc = cifs_setup_volume_info(volume_info, mdata,
3081 fake_devname);
Sean Finneydd613942011-04-11 13:19:30 +00003082 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04003083 kfree(fake_devname);
3084 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00003085 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00003086 }
3087 kfree(full_path);
3088 return rc;
3089}
Steve French2d6d5892009-04-09 00:36:44 +00003090#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003091
Jeff Layton04db79b2011-07-06 08:10:38 -04003092static int
3093cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3094 const char *devname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003096 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00003097
Jeff Layton04db79b2011-07-06 08:10:38 -04003098 if (cifs_parse_mount_options(mount_data, devname, volume_info))
3099 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100
Jeff Layton7586b762008-12-01 18:41:49 -05003101 if (volume_info->nullauth) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003102 cFYI(1, "null user");
Pavel Shilovsky446b23a2011-06-20 12:33:16 +04003103 volume_info->username = kzalloc(1, GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04003104 if (volume_info->username == NULL)
3105 return -ENOMEM;
Jeff Layton7586b762008-12-01 18:41:49 -05003106 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 /* BB fixme parse for domain name here */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003108 cFYI(1, "Username: %s", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 } else {
Steve Frenchbf820672005-12-01 22:32:42 -08003110 cifserror("No username specified");
Steve French50c2f752007-07-13 00:33:32 +00003111 /* In userspace mount helper we can get user name from alternate
3112 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04003113 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 }
3115
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05003117 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003118 /* load_nls_default cannot return null */
3119 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04003121 volume_info->local_nls = load_nls(volume_info->iocharset);
3122 if (volume_info->local_nls == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003123 cERROR(1, "CIFS mount error: iocharset %s not found",
3124 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04003125 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 }
3127 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003128
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003129 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04003130}
3131
3132struct smb_vol *
3133cifs_get_volume_info(char *mount_data, const char *devname)
3134{
3135 int rc;
3136 struct smb_vol *volume_info;
3137
3138 volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
3139 if (!volume_info)
3140 return ERR_PTR(-ENOMEM);
3141
3142 rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3143 if (rc) {
3144 cifs_cleanup_volume_info(volume_info);
3145 volume_info = ERR_PTR(rc);
3146 }
3147
3148 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003149}
3150
3151int
Al Viro2c6292a2011-06-17 09:05:48 -04003152cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003153{
3154 int rc = 0;
3155 int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003156 struct cifs_ses *pSesInfo;
3157 struct cifs_tcon *tcon;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003158 struct TCP_Server_Info *srvTcp;
3159 char *full_path;
3160 struct tcon_link *tlink;
3161#ifdef CONFIG_CIFS_DFS_UPCALL
3162 int referral_walks_count = 0;
Jeff Layton20547492011-07-09 12:21:07 -04003163#endif
Al Virodd854462011-06-17 08:24:42 -04003164
3165 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
3166 if (rc)
3167 return rc;
3168
3169 cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
3170
Jeff Layton20547492011-07-09 12:21:07 -04003171#ifdef CONFIG_CIFS_DFS_UPCALL
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003172try_mount_again:
3173 /* cleanup activities if we're chasing a referral */
3174 if (referral_walks_count) {
3175 if (tcon)
3176 cifs_put_tcon(tcon);
3177 else if (pSesInfo)
3178 cifs_put_smb_ses(pSesInfo);
3179
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00003180 FreeXid(xid);
3181 }
3182#endif
3183 tcon = NULL;
3184 pSesInfo = NULL;
3185 srvTcp = NULL;
3186 full_path = NULL;
3187 tlink = NULL;
3188
3189 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Jeff Layton63c038c2008-12-01 18:41:46 -05003191 /* get a reference to a tcp session */
Jeff Layton7586b762008-12-01 18:41:49 -05003192 srvTcp = cifs_get_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05003193 if (IS_ERR(srvTcp)) {
3194 rc = PTR_ERR(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003195 bdi_destroy(&cifs_sb->bdi);
Jeff Layton63c038c2008-12-01 18:41:46 -05003196 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 }
3198
Jeff Layton36988c72010-04-24 07:57:43 -04003199 /* get a reference to a SMB session */
3200 pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
3201 if (IS_ERR(pSesInfo)) {
3202 rc = PTR_ERR(pSesInfo);
3203 pSesInfo = NULL;
3204 goto mount_fail_check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 }
Steve French50c2f752007-07-13 00:33:32 +00003206
Jeff Laytond00c28d2010-04-24 07:57:44 -04003207 /* search for existing tcon to this server share */
3208 tcon = cifs_get_tcon(pSesInfo, volume_info);
3209 if (IS_ERR(tcon)) {
3210 rc = PTR_ERR(tcon);
3211 tcon = NULL;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003212 goto remote_path_check;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003213 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003214
Steve French6848b732011-05-26 18:38:54 +00003215 /* tell server which Unix caps we support */
3216 if (tcon->ses->capabilities & CAP_UNIX) {
3217 /* reset of caps checks mount to see if unix extensions
3218 disabled for just this mount */
Al Viro2c6292a2011-06-17 09:05:48 -04003219 reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
Steve French6848b732011-05-26 18:38:54 +00003220 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
3221 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
3222 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
3223 rc = -EACCES;
3224 goto mount_fail_check;
3225 }
3226 } else
3227 tcon->unix_ext = 0; /* server does not support them */
3228
Steve Frenchd82c2df2008-11-15 00:07:26 +00003229 /* do not care if following two calls succeed - informational */
3230 if (!tcon->ipc) {
3231 CIFSSMBQFSDeviceInfo(xid, tcon);
3232 CIFSSMBQFSAttributeInfo(xid, tcon);
3233 }
3234
Steve Frenchd82c2df2008-11-15 00:07:26 +00003235 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
3236 cifs_sb->rsize = 1024 * 127;
Joe Perchesb6b38f72010-04-21 03:50:45 +00003237 cFYI(DBG2, "no very large read support, rsize now 127K");
Steve Frenchd82c2df2008-11-15 00:07:26 +00003238 }
Steve Frenchd82c2df2008-11-15 00:07:26 +00003239 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
Jeff Laytonc974bef2011-10-11 06:41:32 -04003240 cifs_sb->rsize = min(cifs_sb->rsize, CIFSMaxBufSize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241
Jeff Laytonf7910cb2011-05-19 16:22:58 -04003242 cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
3243
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003244remote_path_check:
Sean Finneyc1508ca2011-04-11 13:19:31 +00003245#ifdef CONFIG_CIFS_DFS_UPCALL
3246 /*
3247 * Perform an unconditional check for whether there are DFS
3248 * referrals for this path without prefix, to provide support
3249 * for DFS referrals from w2k8 servers which don't seem to respond
3250 * with PATH_NOT_COVERED to requests that include the prefix.
3251 * Chase the referral if found, otherwise continue normally.
3252 */
3253 if (referral_walks_count == 0) {
3254 int refrc = expand_dfs_referral(xid, pSesInfo, volume_info,
Sean Finney046462a2011-04-11 13:19:33 +00003255 cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00003256 if (!refrc) {
3257 referral_walks_count++;
3258 goto try_mount_again;
3259 }
3260 }
3261#endif
3262
Steve Frenchf87d39d2011-05-27 03:50:55 +00003263 /* check if a whole path is not remote */
Jeff Layton70945642011-03-14 13:48:08 -04003264 if (!rc && tcon) {
Igor Mammedove4cce942009-02-10 14:10:26 +03003265 /* build_path_to_root works only when we have a valid tcon */
Steve Frenchf87d39d2011-05-27 03:50:55 +00003266 full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
Igor Mammedove4cce942009-02-10 14:10:26 +03003267 if (full_path == NULL) {
3268 rc = -ENOMEM;
3269 goto mount_fail_check;
3270 }
3271 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
Jeff Layton03ceace2010-12-06 21:07:33 -05003272 if (rc != 0 && rc != -EREMOTE) {
Igor Mammedove4cce942009-02-10 14:10:26 +03003273 kfree(full_path);
3274 goto mount_fail_check;
3275 }
3276 kfree(full_path);
3277 }
3278
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003279 /* get referral if needed */
3280 if (rc == -EREMOTE) {
Steve Frenchd036f502009-04-03 03:12:08 +00003281#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003282 if (referral_walks_count > MAX_NESTED_LINKS) {
3283 /*
3284 * BB: when we implement proper loop detection,
3285 * we will remove this check. But now we need it
3286 * to prevent an indefinite loop if 'DFS tree' is
3287 * misconfigured (i.e. has loops).
3288 */
3289 rc = -ELOOP;
3290 goto mount_fail_check;
3291 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003292
Sean Finneydd613942011-04-11 13:19:30 +00003293 rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00003294 true);
Jeff Layton7b91e262009-07-23 15:22:30 -04003295
Sean Finneydd613942011-04-11 13:19:30 +00003296 if (!rc) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04003297 referral_walks_count++;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003298 goto try_mount_again;
3299 }
Sean Finneydd613942011-04-11 13:19:30 +00003300 goto mount_fail_check;
Steve Frenchd036f502009-04-03 03:12:08 +00003301#else /* No DFS support, return error on mount */
3302 rc = -EOPNOTSUPP;
3303#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003304 }
3305
Jeff Layton9d002df2010-10-06 19:51:11 -04003306 if (rc)
3307 goto mount_fail_check;
3308
3309 /* now, hang the tcon off of the superblock */
3310 tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
3311 if (tlink == NULL) {
3312 rc = -ENOMEM;
3313 goto mount_fail_check;
3314 }
3315
Jeff Laytonb647c352010-10-28 11:16:44 -04003316 tlink->tl_uid = pSesInfo->linux_uid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003317 tlink->tl_tcon = tcon;
3318 tlink->tl_time = jiffies;
3319 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
3320 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3321
Jeff Layton413e6612010-10-28 13:33:38 -04003322 cifs_sb->master_tlink = tlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003323 spin_lock(&cifs_sb->tlink_tree_lock);
3324 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3325 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton413e6612010-10-28 13:33:38 -04003326
Jeff Layton2de970f2010-10-06 19:51:12 -04003327 queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
3328 TLINK_IDLE_EXPIRE);
3329
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003330mount_fail_check:
3331 /* on error free sesinfo and tcon struct if needed */
3332 if (rc) {
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003333 /* If find_unc succeeded then rc == 0 so we can not end */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003334 /* up accidentally freeing someone elses tcon struct */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003335 if (tcon)
3336 cifs_put_tcon(tcon);
3337 else if (pSesInfo)
3338 cifs_put_smb_ses(pSesInfo);
3339 else
3340 cifs_put_tcp_session(srvTcp);
Al Virodd854462011-06-17 08:24:42 -04003341 bdi_destroy(&cifs_sb->bdi);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04003342 }
3343
Jeff Layton70fe7dc2007-11-16 22:21:07 +00003344out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345 FreeXid(xid);
3346 return rc;
3347}
3348
Jeff Layton8d1bca32011-06-11 21:17:10 -04003349/*
3350 * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
3351 * pointer may be NULL.
3352 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353int
Steve French96daf2b2011-05-27 04:34:02 +00003354CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3355 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 const struct nls_table *nls_codepage)
3357{
3358 struct smb_hdr *smb_buffer;
3359 struct smb_hdr *smb_buffer_response;
3360 TCONX_REQ *pSMB;
3361 TCONX_RSP *pSMBr;
3362 unsigned char *bcc_ptr;
3363 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05003364 int length;
3365 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366
3367 if (ses == NULL)
3368 return -EIO;
3369
3370 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00003371 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00003373
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 smb_buffer_response = smb_buffer;
3375
3376 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3377 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07003378
3379 smb_buffer->Mid = GetNextMid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 smb_buffer->Uid = ses->Suid;
3381 pSMB = (TCONX_REQ *) smb_buffer;
3382 pSMBr = (TCONX_RSP *) smb_buffer_response;
3383
3384 pSMB->AndXCommand = 0xFF;
3385 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 bcc_ptr = &pSMB->Password[0];
Jeff Layton8d1bca32011-06-11 21:17:10 -04003387 if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08003388 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00003389 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08003390 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00003391 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08003392 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003393 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08003394 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3395 specified as required (when that support is added to
3396 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00003397 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08003398 by Samba (not sure whether other servers allow
3399 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00003400#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04003401 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton00e485b2008-12-05 20:41:21 -05003402 (ses->server->secType == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05003403 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00003404 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05003405 SECMODE_PW_ENCRYPT ? true : false,
3406 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00003407 else
3408#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06003409 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
3410 bcc_ptr);
Steve Frencheeac8042006-01-13 21:34:58 -08003411
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06003412 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003413 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00003414 /* must align unicode strings */
3415 *bcc_ptr = 0; /* null byte password */
3416 bcc_ptr++;
3417 }
Steve Frencheeac8042006-01-13 21:34:58 -08003418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419
Steve French96daf2b2011-05-27 04:34:02 +00003420 if (ses->server->sec_mode &
Steve Frencha878fb22006-05-30 18:04:19 +00003421 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3423
3424 if (ses->capabilities & CAP_STATUS32) {
3425 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3426 }
3427 if (ses->capabilities & CAP_DFS) {
3428 smb_buffer->Flags2 |= SMBFLG2_DFS;
3429 }
3430 if (ses->capabilities & CAP_UNICODE) {
3431 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3432 length =
Steve French50c2f752007-07-13 00:33:32 +00003433 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3434 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00003435 (/* server len*/ + 256 /* share len */), nls_codepage);
3436 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437 bcc_ptr += 2; /* skip trailing null */
3438 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439 strcpy(bcc_ptr, tree);
3440 bcc_ptr += strlen(tree) + 1;
3441 }
3442 strcpy(bcc_ptr, "?????");
3443 bcc_ptr += strlen("?????");
3444 bcc_ptr += 1;
3445 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003446 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
3447 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448 pSMB->ByteCount = cpu_to_le16(count);
3449
Steve French133672e2007-11-13 22:41:37 +00003450 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05003451 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 /* above now done in SendReceive */
3454 if ((rc == 0) && (tcon != NULL)) {
Steve French0e0d2cf2009-05-01 05:27:32 +00003455 bool is_unicode;
3456
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00003458 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 tcon->tid = smb_buffer_response->Tid;
3460 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05003461 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003462 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00003463 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
3464 is_unicode = true;
3465 else
3466 is_unicode = false;
3467
Jeff Laytoncc20c032009-04-30 07:16:21 -04003468
Steve French50c2f752007-07-13 00:33:32 +00003469 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00003470 if (length == 3) {
3471 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3472 (bcc_ptr[2] == 'C')) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003473 cFYI(1, "IPC connection");
Steve French7f8ed422007-09-28 22:28:55 +00003474 tcon->ipc = 1;
3475 }
3476 } else if (length == 2) {
3477 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3478 /* the most common case */
Joe Perchesb6b38f72010-04-21 03:50:45 +00003479 cFYI(1, "disk share connection");
Steve French7f8ed422007-09-28 22:28:55 +00003480 }
3481 }
Steve French50c2f752007-07-13 00:33:32 +00003482 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04003483 bytes_left -= (length + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003485
3486 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04003487 kfree(tcon->nativeFileSystem);
Steve Frenchd185cda2009-04-30 17:45:10 +00003488 tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00003489 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04003490 nls_codepage);
3491
Joe Perchesb6b38f72010-04-21 03:50:45 +00003492 cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04003493
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003494 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00003495 (smb_buffer_response->WordCount == 7))
3496 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00003497 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3498 else
3499 tcon->Flags = 0;
Joe Perchesb6b38f72010-04-21 03:50:45 +00003500 cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 } else if ((rc == 0) && tcon == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003502 /* all we need to save for IPC$ connection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 ses->ipc_tid = smb_buffer_response->Tid;
3504 }
3505
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00003506 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 return rc;
3508}
3509
Al Viro2a9b9952011-06-17 09:27:16 -04003510void
3511cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512{
Jeff Laytonb647c352010-10-28 11:16:44 -04003513 struct rb_root *root = &cifs_sb->tlink_tree;
3514 struct rb_node *node;
3515 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516
Jeff Layton2de970f2010-10-06 19:51:12 -04003517 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
3518
Jeff Laytonb647c352010-10-28 11:16:44 -04003519 spin_lock(&cifs_sb->tlink_tree_lock);
3520 while ((node = rb_first(root))) {
3521 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3522 cifs_get_tlink(tlink);
3523 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3524 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00003525
Jeff Laytonb647c352010-10-28 11:16:44 -04003526 spin_unlock(&cifs_sb->tlink_tree_lock);
3527 cifs_put_tlink(tlink);
3528 spin_lock(&cifs_sb->tlink_tree_lock);
3529 }
3530 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003531
Al Virodd854462011-06-17 08:24:42 -04003532 bdi_destroy(&cifs_sb->bdi);
Al Virod757d712011-06-17 09:42:43 -04003533 kfree(cifs_sb->mountdata);
3534 unload_nls(cifs_sb->local_nls);
3535 kfree(cifs_sb);
Steve French50c2f752007-07-13 00:33:32 +00003536}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537
Steve French96daf2b2011-05-27 04:34:02 +00003538int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539{
3540 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04003541 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
Jeff Layton198b5682010-04-24 07:57:48 -04003543 /* only send once per connect */
3544 if (server->maxBuf != 0)
3545 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546
Jeff Layton198b5682010-04-24 07:57:48 -04003547 rc = CIFSSMBNegotiate(xid, ses);
3548 if (rc == -EAGAIN) {
3549 /* retry only once on 1st time connection */
3550 rc = CIFSSMBNegotiate(xid, ses);
3551 if (rc == -EAGAIN)
3552 rc = -EHOSTDOWN;
3553 }
3554 if (rc == 0) {
3555 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04003556 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04003557 server->tcpStatus = CifsGood;
3558 else
3559 rc = -EHOSTDOWN;
3560 spin_unlock(&GlobalMid_Lock);
3561
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562 }
Steve French26b994f2008-08-06 05:11:33 +00003563
Jeff Layton198b5682010-04-24 07:57:48 -04003564 return rc;
3565}
Steve French26b994f2008-08-06 05:11:33 +00003566
Jeff Layton198b5682010-04-24 07:57:48 -04003567
Steve French96daf2b2011-05-27 04:34:02 +00003568int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
Jeff Layton198b5682010-04-24 07:57:48 -04003569 struct nls_table *nls_info)
3570{
3571 int rc = 0;
3572 struct TCP_Server_Info *server = ses->server;
3573
3574 ses->flags = 0;
3575 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00003576 if (linuxExtEnabled == 0)
Jeff Layton198b5682010-04-24 07:57:48 -04003577 ses->capabilities &= (~CAP_UNIX);
Steve French20418ac2009-04-30 16:13:32 +00003578
Joe Perchesb6b38f72010-04-21 03:50:45 +00003579 cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
Steve French96daf2b2011-05-27 04:34:02 +00003580 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04003581
Jeff Layton198b5682010-04-24 07:57:48 -04003582 rc = CIFS_SessSetup(xid, ses, nls_info);
Steve French26b994f2008-08-06 05:11:33 +00003583 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +00003584 cERROR(1, "Send error in SessSetup = %d", rc);
Steve French26b994f2008-08-06 05:11:33 +00003585 } else {
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003586 mutex_lock(&ses->server->srv_mutex);
3587 if (!server->session_estab) {
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003588 server->session_key.response = ses->auth_key.response;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003589 server->session_key.len = ses->auth_key.len;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003590 server->sequence_number = 0x2;
3591 server->session_estab = true;
3592 ses->auth_key.response = NULL;
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05003593 }
3594 mutex_unlock(&server->srv_mutex);
3595
Joe Perchesb6b38f72010-04-21 03:50:45 +00003596 cFYI(1, "CIFS Session Established successfully");
Steve French20418ac2009-04-30 16:13:32 +00003597 spin_lock(&GlobalMid_Lock);
Jeff Layton198b5682010-04-24 07:57:48 -04003598 ses->status = CifsGood;
3599 ses->need_reconnect = false;
Steve French20418ac2009-04-30 16:13:32 +00003600 spin_unlock(&GlobalMid_Lock);
Steve French26b994f2008-08-06 05:11:33 +00003601 }
3602
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003603 kfree(ses->auth_key.response);
3604 ses->auth_key.response = NULL;
3605 ses->auth_key.len = 0;
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003606 kfree(ses->ntlmssp);
3607 ses->ntlmssp = NULL;
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05003608
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 return rc;
3610}
3611
Steve French96daf2b2011-05-27 04:34:02 +00003612static struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04003613cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
3614{
Steve French96daf2b2011-05-27 04:34:02 +00003615 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
3616 struct cifs_ses *ses;
3617 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04003618 struct smb_vol *vol_info;
Steve French34c87902011-03-01 05:02:57 +00003619 char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */
3620 /* We used to have this as MAX_USERNAME which is */
3621 /* way too big now (256 instead of 32) */
Jeff Layton9d002df2010-10-06 19:51:11 -04003622
3623 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
3624 if (vol_info == NULL) {
3625 tcon = ERR_PTR(-ENOMEM);
3626 goto out;
3627 }
3628
Steve Frenchea1be1a2011-07-12 18:24:43 +00003629 snprintf(username, sizeof(username), "krb50x%x", fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04003630 vol_info->username = username;
3631 vol_info->local_nls = cifs_sb->local_nls;
3632 vol_info->linux_uid = fsuid;
3633 vol_info->cred_uid = fsuid;
3634 vol_info->UNC = master_tcon->treeName;
3635 vol_info->retry = master_tcon->retry;
3636 vol_info->nocase = master_tcon->nocase;
3637 vol_info->local_lease = master_tcon->local_lease;
3638 vol_info->no_linux_ext = !master_tcon->unix_ext;
3639
3640 /* FIXME: allow for other secFlg settings */
3641 vol_info->secFlg = CIFSSEC_MUST_KRB5;
3642
3643 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303644 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003645 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303646 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003647
3648 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
3649 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00003650 tcon = (struct cifs_tcon *)ses;
Jeff Layton9d002df2010-10-06 19:51:11 -04003651 cifs_put_tcp_session(master_tcon->ses->server);
3652 goto out;
3653 }
3654
3655 tcon = cifs_get_tcon(ses, vol_info);
3656 if (IS_ERR(tcon)) {
3657 cifs_put_smb_ses(ses);
3658 goto out;
3659 }
3660
3661 if (ses->capabilities & CAP_UNIX)
3662 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
3663out:
3664 kfree(vol_info);
3665
3666 return tcon;
3667}
3668
Steve French96daf2b2011-05-27 04:34:02 +00003669struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04003670cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
3671{
3672 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
3673}
3674
3675static int
3676cifs_sb_tcon_pending_wait(void *unused)
3677{
3678 schedule();
3679 return signal_pending(current) ? -ERESTARTSYS : 0;
3680}
3681
Jeff Laytonb647c352010-10-28 11:16:44 -04003682/* find and return a tlink with given uid */
3683static struct tcon_link *
3684tlink_rb_search(struct rb_root *root, uid_t uid)
3685{
3686 struct rb_node *node = root->rb_node;
3687 struct tcon_link *tlink;
3688
3689 while (node) {
3690 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
3691
3692 if (tlink->tl_uid > uid)
3693 node = node->rb_left;
3694 else if (tlink->tl_uid < uid)
3695 node = node->rb_right;
3696 else
3697 return tlink;
3698 }
3699 return NULL;
3700}
3701
3702/* insert a tcon_link into the tree */
3703static void
3704tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
3705{
3706 struct rb_node **new = &(root->rb_node), *parent = NULL;
3707 struct tcon_link *tlink;
3708
3709 while (*new) {
3710 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
3711 parent = *new;
3712
3713 if (tlink->tl_uid > new_tlink->tl_uid)
3714 new = &((*new)->rb_left);
3715 else
3716 new = &((*new)->rb_right);
3717 }
3718
3719 rb_link_node(&new_tlink->tl_rbnode, parent, new);
3720 rb_insert_color(&new_tlink->tl_rbnode, root);
3721}
3722
Jeff Layton9d002df2010-10-06 19:51:11 -04003723/*
3724 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
3725 * current task.
3726 *
3727 * If the superblock doesn't refer to a multiuser mount, then just return
3728 * the master tcon for the mount.
3729 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05303730 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04003731 * exists, then check to see if it's pending construction. If it is then wait
3732 * for construction to complete. Once it's no longer pending, check to see if
3733 * it failed and either return an error or retry construction, depending on
3734 * the timeout.
3735 *
3736 * If one doesn't exist then insert a new tcon_link struct into the tree and
3737 * try to construct a new one.
3738 */
3739struct tcon_link *
3740cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
3741{
3742 int ret;
Jeff Laytonb647c352010-10-28 11:16:44 -04003743 uid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04003744 struct tcon_link *tlink, *newtlink;
3745
3746 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
3747 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3748
3749 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04003750 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04003751 if (tlink)
3752 cifs_get_tlink(tlink);
3753 spin_unlock(&cifs_sb->tlink_tree_lock);
3754
3755 if (tlink == NULL) {
3756 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
3757 if (newtlink == NULL)
3758 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04003759 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04003760 newtlink->tl_tcon = ERR_PTR(-EACCES);
3761 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
3762 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
3763 cifs_get_tlink(newtlink);
3764
Jeff Layton9d002df2010-10-06 19:51:11 -04003765 spin_lock(&cifs_sb->tlink_tree_lock);
3766 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04003767 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04003768 if (tlink) {
3769 cifs_get_tlink(tlink);
3770 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003771 kfree(newtlink);
3772 goto wait_for_construction;
3773 }
Jeff Layton9d002df2010-10-06 19:51:11 -04003774 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04003775 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
3776 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04003777 } else {
3778wait_for_construction:
3779 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
3780 cifs_sb_tcon_pending_wait,
3781 TASK_INTERRUPTIBLE);
3782 if (ret) {
3783 cifs_put_tlink(tlink);
3784 return ERR_PTR(ret);
3785 }
3786
3787 /* if it's good, return it */
3788 if (!IS_ERR(tlink->tl_tcon))
3789 return tlink;
3790
3791 /* return error if we tried this already recently */
3792 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
3793 cifs_put_tlink(tlink);
3794 return ERR_PTR(-EACCES);
3795 }
3796
3797 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
3798 goto wait_for_construction;
3799 }
3800
3801 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
3802 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
3803 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
3804
3805 if (IS_ERR(tlink->tl_tcon)) {
3806 cifs_put_tlink(tlink);
3807 return ERR_PTR(-EACCES);
3808 }
3809
3810 return tlink;
3811}
Jeff Layton2de970f2010-10-06 19:51:12 -04003812
3813/*
3814 * periodic workqueue job that scans tcon_tree for a superblock and closes
3815 * out tcons.
3816 */
3817static void
3818cifs_prune_tlinks(struct work_struct *work)
3819{
3820 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
3821 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04003822 struct rb_root *root = &cifs_sb->tlink_tree;
3823 struct rb_node *node = rb_first(root);
3824 struct rb_node *tmp;
3825 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04003826
Jeff Laytonb647c352010-10-28 11:16:44 -04003827 /*
3828 * Because we drop the spinlock in the loop in order to put the tlink
3829 * it's not guarded against removal of links from the tree. The only
3830 * places that remove entries from the tree are this function and
3831 * umounts. Because this function is non-reentrant and is canceled
3832 * before umount can proceed, this is safe.
3833 */
3834 spin_lock(&cifs_sb->tlink_tree_lock);
3835 node = rb_first(root);
3836 while (node != NULL) {
3837 tmp = node;
3838 node = rb_next(tmp);
3839 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
3840
3841 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
3842 atomic_read(&tlink->tl_count) != 0 ||
3843 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
3844 continue;
3845
3846 cifs_get_tlink(tlink);
3847 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
3848 rb_erase(tmp, root);
3849
Jeff Layton2de970f2010-10-06 19:51:12 -04003850 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04003851 cifs_put_tlink(tlink);
3852 spin_lock(&cifs_sb->tlink_tree_lock);
3853 }
3854 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04003855
3856 queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks,
3857 TLINK_IDLE_EXPIRE);
3858}